Skip to content

Experience · Repository · Active

cs-portal

Codestorm operations portal for HR, administration, documents, productivity integrations and Salesforce-backed operational workflows.

  • NestJS
  • React 18
  • Vite
  • Tailwind
  • Google APIs
  • Microsoft Graph
  • pdf-lib

Spec sheet

Area

Experience / Portal

Public host

http://portal.cs.lvh.me:8080

Runtime shape

Frontend + NestJS BFF

Backend port

3003

Frontend port

5177

Datasource access

Delegated to platform-connectors-service

Responsibilities

  • Own HR, administration, payroll, document and productivity workflows.
  • Own the Salesforce-backed economic forecast workflow for monthly revenue, personnel cost and margin planning.
  • Expose a product BFF that wraps platform auth and platform connectors behind same-origin /api routes.
  • Use structured Salesforce lookup endpoints instead of browser-authored raw SOQL.
  • Keep large page and service implementations split into runtime modules and thin exported wrappers.

Interfaces and contract surface

  • Same-origin /api surface
  • GET /api/health
  • Frontend React routes

Internal modules

Backend

cs-portal backend

NestJS BFF for CS Portal, owning HR, administration, document and productivity workflows while delegating shared auth and Salesforce access to Core services.

Frontend

cs-portal frontend

React and Vite frontend for CS Portal, rendering HR, operations, administration, documents and lookup workflows through same-origin APIs.

Consumers

  • Internal Codestorm operators via portal host

Dependencies and external touchpoints

Notes

  • The backend is the only layer allowed to talk to Core services; the frontend remains same-origin.
  • Economic forecast data is stored on dedicated Salesforce prebilling objects and kept separate from real invoices and cashflow records; personnel costs and margins are calculated read-only from monthly cost Salesforce objects.
  • Recent commits extracted heavy backend services and React pages into runtime modules to keep wrappers smaller.

Source references

  • cs-portal/README.md
  • cs-portal/AGENTS.md
  • cs-portal/package.json
  • cs-portal/backend/package.json
  • cs-portal/frontend/package.json
  • cs-portal/docs/backend-api-map.md
  • cs-portal/backend/src/administration-prebilling
  • cs-portal/backend/src/monthly-costs
  • cs-portal/frontend/src/features/prebilling

La sidebar espone collegamenti diretti alle pagine, raggruppati per categoria nelle app espandibili. L'app della pagina corrente si apre al cambio di percorso; espandere un'altra app mostra le sue pagine senza cambiare destinazione. Il drawer mobile usa lo stesso menu.

Sidebar, drawer e ricerca globale condividono risultati ordinati per pertinenza, con descrizione, breadcrumb e conteggio completo. Tutte le destinazioni corrispondenti sono raggiungibili scorrendo l'elenco: non esiste un taglio della UI ai primi sei risultati. Nome e keyword della pagina prevalgono sui match generici dell'app; l'ordine configurato risolve soltanto i pareggi e non viene alterato per promuovere una pagina.

Una query puo' combinare termini di app, categoria e pagina, ad esempio importa costi HR. Sinonimi e denominazioni d'uso sono metadata curati in keywords; accenti e punteggiatura sono normalizzati. La tolleranza ai refusi e' limitata a una sola modifica su un solo termine di almeno cinque caratteri. Gli acronimi brevi restano esatti.

Nel confronto statico del 7 settembre 2026 sulla configurazione completa, cercando Costi, Importa costi del personale passa dall'undicesimo al primo risultato. La sessione continua a cercare esclusivamente nelle destinazioni gia' autorizzate dal BFF.

Ctrl/Cmd+K apre Pagine per gli utenti autenticati. La scheda Record mantiene il precedente vincolo di permessi: solo questa modalita' avvia la ricerca Salesforce attraverso /api/global-search, con debounce e annullamento delle richieste superate.

La verifica UI controllata deve coprire interazione, navigazione, layout desktop/mobile e separazione Pagine/Record; quando usa sessioni o risposte simulate non certifica accessi Salesforce o sessioni in produzione. Rilascio e verifica autenticata dell'istanza distribuita restano evidenze distinte. Il dettaglio del contratto di ricerca e delle verifiche si trova in cs-portal/docs/navigation-taxonomy.md.

La sola revisione della navigazione non modifica route o boundary runtime; le nuove capability che seguono hanno documentazione e runtime dedicati.

API integration ​

CS Portal mantiene l'autorità su endpoint, ACL, data scope e audit applicativo. Il IntegrationBearerGuard accetta Bearer solo sulle route registrate esplicitamente e costruisce lo stesso PortalPrincipalContext usato dal browser. Le route non registrate restano session-only anche se ricevono un Bearer.

Facade same-origin:

  • POST /api/auth/token per il token exchange delegato a platform-auth-service;
  • /api/me/api-credentials/* per PAT human;
  • /api/me/service-accounts/* per service account con owner derivato dalla sessione; l'elenco include il riepilogo della credenziale corrente senza secret;
  • GET /api/integrations/v1/me e /api/integrations/v1/capabilities per contesto e discovery.

La gestione visuale è disponibile in /#/settings/integrations per utenti autenticati. Il frontend mostra secret e client ID una sola volta e non espone la route di token exchange.

La registry abilita preview ed esecuzione della chiusura mese HR, il contesto mensile HR in sola lettura, lettura e sincronizzazione commesse, e i sei GET di /api/hr/consumptive-management. Il contesto mensile GET /api/hr/monthly-check?month=YYYY-MM include le risorse attive e tutti i consuntivi del mese (query Salesforce limitate a 5.000 risorse e 10.000 consuntivi). In ciascun consuntivo, il progetto collegato tramite Project_Resource__r.Project__r espone Customer__c e Customer__r con nome e VAT__c; richiede rest:hr-monthly-check (Portal HR, Portal Admin). Le sei letture di consumptive-management richiedono l'ACL rest:hr-consumptive-management (Portal HR, Portal Admin); le quattro POST mutanti di share, clear-share, move e status restano session-only. Il bridge usa il metodo/path del descriptor e non un router invoke generico. La feature richiede CS_PORTAL_INTEGRATION_TOKENS_ENABLED=true, disabilitato per default; la risoluzione di auth, ACL, datasource obbligatorio e audit è fail-closed.

Richieste dipendente di assenza e smart working ​

La pagina consuntivi consente al dipendente di inviare richieste di ferie/permessi e smart working tramite le route same-origin POST /api/consumptives/me/request-absence e POST /api/consumptives/me/request-smart-working. Le richieste richiedono almeno un'intera giornata lavorativa tra invio e inizio: sono esclusi entrambi i giorni e si contano lunedì-venerdì. Per iniziare martedì, la richiesta va inviata entro venerdì. La data corrente è calcolata in Europe/Rome; la commessa MA per malattia è esente. Il BFF ripete la validazione prima di creare consuntivi o eventi calendario e restituisce INSUFFICIENT_NOTICE quando il preavviso manca. Il frontend mostra una modal con le istruzioni e indica di contattare HR per le urgenze, mantenendo i dati inseriti al ritorno.

Gestione operativa dei contratti HR ​

/hr/contract apre una overview con KPI, evidenze e drill-down; /hr/contract/list mostra la lista completa. Il BFF gestisce le route new, view/:id, edit/:id, renew/:id e close/:id. Accesso e mutazioni richiedono l'ACL entity:contract, assegnata a Portal HR, Portal Amministrazione e Portal Admin.

La card Scaduti senza contratto attivo è evidenziata come urgente. Per le risorse attive mostra l'ultimo contratto scaduto e consente di avviare il rinnovo. Il rinnovo è ammesso da un contratto attivo oppure dall'ultimo scaduto, se la risorsa non ha già un altro contratto attivo. Nel caso scaduto, la decorrenza del successore deve essere oggi o futura, l'intervallo senza copertura è mostrato nell'anteprima e End_Date__c del contratto storico resta invariata. Il controllo viene ripetuto nel BFF e blocca sovrapposizioni o revisioni obsolete.

La chiusura senza rinnovo è disponibile solo per un contratto attivo. L'operatore seleziona l'ultimo giorno incluso; Portal salva il giorno successivo come limite esclusivo di End_Date__c. L'update del contratto e l'audit HR_Lifecycle_Operation__c con azione CONTRACT_CLOSURE sono atomici e idempotenti. Il processo non crea un successore, non tocca Contract_Work_Schedule__c e non modifica Application_Status__c, riservato a onboarding/offboarding. Le correzioni retroattive restano nel form di modifica.

Il browser usa solo le API same-origin /api/hr/contracts/*; il BFF applica validazione, ACL, revisioni e transazioni Salesforce delegate a platform-connectors-service. La specifica funzionale e i criteri di rilascio sono in cs-portal/docs/contract-management-target-solution.md.

Chiusura mensile HR ​

/hr/chiudi-mese consente a Portal HR e Portal Admin di rigenerare la parte strutturale dei costi di un periodo selezionato, dopo una preview esplicita e una conferma testuale del mese.

  • il browser usa esclusivamente /api/hr/month-close/* e non riceve consuntivi, Fee o SOQL;
  • il BFF confronta un fingerprint SHA-256 della sorgente appena prima di eseguire la mutazione e risponde con conflitto se la preview e' obsoleta;
  • il BFF delega il calcolo storico a MontlyCostManageRest tramite platform-connectors-service, senza duplicare logica Apex nel frontend;
  • la rigenerazione aggiorna linee e Fee, sostituisce i costi progetto e conserva i dettagli non Fee provenienti dall'import costi;
  • l'import CSV/PDF e la chiusura restano due flussi operativi distinti.

Pagamenti Qonto ​

/hr/qonto-payments e' una pagina HR dedicata, raggiungibile dal riepilogo costi e dalla categoria Costi del personale. Mantiene filtri URL per mese, stato e risorsa, selezione bulk, export CSV e conferma esplicita per segnare o annullare il tracciamento di un pagamento. La pagina non dispone bonifici in Qonto: il BFF registra soltanto stato e data nei dettagli costo autorizzati.

Recruiting HR: Job, Talent Pool e Curriculum ​

/hr/jobs e l'area operativa per utenti Portal HR e Portal Admin: lista e form Job, workspace con requisiti, CV in lavorazione e Job Member ufficiali. /hr/talent-pool contiene i CV senza assegnazioni, anche approvati; /hr/curricula conserva review, errori e storico. L'approvazione rimane individuale, con risoluzione Contact e merge campo-per-campo. Un Contact approvato puo avere candidature distinte su Job diversi.

Il bulk invia fino a 50 PDF al BFF con Job comune e massimo tre upload concorrenti. Ogni file ha stato e retry indipendenti. La coda sopravvive alla navigazione interna, non alla chiusura della scheda; soltanto i CV accettati sono recuperabili dal server. Confidenza estrazione e compatibilita Job sono segnali distinti: l'assessment usa soltanto Profilo, Tecnologia, Tipo e Sede del Job e non cambia stati di candidatura.

Il prodotto mantiene i boundary seguenti:

  • il browser chiama soltanto il BFF same-origin /api/hr/*;
  • SharePoint, tramite Microsoft Graph, e l'unico storage dei PDF Curriculum;
  • l'ingresso CV del Documentale converge sulla stessa intake tramite una route multipart dedicata, mentre gli altri documenti conservano il flusso esistente;
  • platform-agent-service esegue i profili versionati cs-portal.hr-curriculum-extractor e cs-portal.hr-curriculum-job-fit, redigendo input/output dopo callback acquisita;
  • platform-connectors-service e l'unico runtime Salesforce e pubblica il profilo con una transazione atomica;
  • Salesforce espone due permission set distinti: Curriculum_Integration per il runtime scrivente e Curriculum_HR_User read-only per audit/reporting HR;
  • Contact non viene creato o aggiornato prima della conferma HR e non esiste matching automatico per nome, telefono o email.

Un PDF senza text layer termina esplicitamente con NO_TEXT_LAYER: non esiste fallback OCR, vision o Google Drive.

Il rollout richiede prima metadata/FLS Salesforce e validazione Apex, poi BFF e UI, sync dei profili Agent e prova end-to-end autorizzata. Il vecchio LWC non viene rimosso prima di quella prova. Contratti, limiti e gate sono in cs-portal/docs/hr-recruiting.md; i test locali con fixture non costituiscono prova di rilascio in produzione.

Rapporto HR: onboarding e offboarding ​

Il nuovo pannello nel dettaglio CV e Contact separa la revisione del curriculum dal rapporto aziendale. Un CV corrente approvato abilita soltanto la CTA di onboarding; la conferma finale del wizard attiva accesso, contratto e assegnazioni interne. Durante l’onboarding HR assegna anche il responsabile BU o dichiara la persona responsabile di una BU; il valore alimenta BU__c e l’organigramma. L'offboarding parte anche da una risorsa senza CV e conserva Record Type e storico.

Il rilascio e sequenziale: campi e audit, backfill conservativo dalla formula corrente, confronto degli stessi Contact abilitati, cambio formula, ritiro legacy e bonifica individuale approvata HR. Nessun requisito CV/Hired retroattivo sul pregresso. La bonifica non introduce una pagina permanente e non invia email. Le operazioni distinte di onboarding e offboarding usano invece i template email gestiti da cs-portal; la notifica di offboarding raggiunge la risorsa e HR. I dettagli operativi e i gate sono in cs-portal/docs/hr-lifecycle-runbook.md.

Il 7 settembre 2026 è stato distribuito su csprod il solo pacchetto Salesforce di preparazione, incluso Administration: 48 componenti, 5 test Apex superati. Formula legacy e insieme dei 52 Contact abilitati invariati; migrazione, cutover, rilascio del portale e bonifica restano fasi separate. Evidenze in cs-salesforce/docs/hr-lifecycle-release-2026-09-07.md.

Task tracking multi-board ​

/tasks rende disponibili le board a ogni Contact con sessione Portal valida, senza una ACL globale specifica. La visibilità deriva dalla membership attiva della singola board; Owner, Editor e Viewer governano rispettivamente proprietà/condivisione, mutazioni task e sola lettura. Board, membri, colonne, task e audit sono persistiti in un PostgreSQL dedicato a CS Portal. Salesforce resta la fonte autorevole per stato e nome dei Contact, consultati dal BFF tramite platform-connectors-service con una query circoscritta e read-only. Per le capability MCP, CS Portal mantiene il provider e le regole nel BFF; platform-mcp-service usa il contratto generico @platform/contracts-mcp per il relay. Gli scope OAuth e i controlli di ruolo e idempotenza sono nel runbook Task Board. Flusso: docs/architecture-images/cs-portal-task-board-mcp.svg.

Il creatore è l'assegnatario predefinito dei nuovi task. I task urgenti hanno una segnalazione persistita e precedono gli altri nel Kanban di ciascuna colonna; gli stati testuali “Scaduto” e “In scadenza” seguono il calendario Portal Europe/Rome.

Le API sono same-origin sotto /api/task-boards/*. Prisma migra il database dedicato; lo stack portal avvia portal-postgres prima del backend. La readiness distingue l'indisponibilità PostgreSQL dalle capability diagnostiche HR, e platform-status-service monitora entrambi i segnali. Setup, restore e gate per ambiente sono nel runbook cs-portal/docs/task-tracking-operations.md.

Le notifiche email coprono soltanto nuovo accesso/riattivazione a una board, cambio ruolo effettivo e assegnazione di un task. Il backend usa l'outbox PostgreSQL e il sistema mail esistente con Email_Queue__c; TASK_NOTIFICATIONS_ENABLED resta disabilitato fino alla verifica di datasource e permessi Salesforce. Reminder, digest e notifiche per modifiche ordinarie non sono inclusi.

Workspace reference: /Users/jeanpaul/projects/cs-repository