Skip to content

cs transaction api ​

Experience · Backend · Active

cs transaction api

NestJS BFF for CS Transaction Manage, delegating auth/session/role flows to platform-auth-service and subscription status to platform-payments-service while owning ledger, planning setup, transaction, series, investment and agenda APIs.

  • NestJS 11
  • Prisma 7
  • PostgreSQL
  • class-validator
  • helmet
  • cookie-parser

Spec sheet

Repository path

cs-transacion-manage/apps/api

Runtime

NestJS 11 BFF

Default port

3005

Public surface

Same-origin /api on transactions host

Database

transaction-postgres via Prisma 7

Responsibilities

  • Expose auth, optional planning setup, user, relationship, counterparty, transaction, series, pay-yourself-first, investment and agenda endpoints.
  • Resolve login and request sessions through platform-auth-service, then maintain product-local user profiles for ledger ownership.
  • Resolve AccessContext in the access module and enforce capability guards on sensitive endpoints.
  • Persist transaction-management state through Prisma.
  • Expose health checks that include database connectivity.
  • Keep controllers thin and centralize domain behavior in services.

Interfaces and contract surface

  • GET /api/health
  • GET /api/auth/bootstrap
  • GET /api/auth/me
  • POST /api/auth/register
  • POST /api/auth/login
  • GET /api/planning/setup
  • POST /api/planning/setup
  • access: role + subscriptionTier + capabilities + isAdmin
  • GET /api/transactions
  • GET /api/series
  • GET /api/investments
  • GET /api/agenda

Consumers

Dependencies and external touchpoints

Notes

  • The local-stack entrypoint runs Prisma db push and generate before Nest watch.
  • Denied capabilities return 403 Forbidden; the frontend capability filter is not the security boundary.

Source references

  • cs-transacion-manage/apps/api/package.json
  • cs-transacion-manage/apps/api/prisma/schema.prisma
  • cs-transacion-manage/apps/api/src

Access contract ​

GET /api/auth/me, login e primo register restituiscono user.role e access con role, subscriptionTier, capabilities e isAdmin.

Il modulo access risolve:

  • ruolo, tenantId e subjectId dalla sessione platform-auth-service;
  • stato piano da platform-payments-service;
  • capability finali applicate dai guard NestJS.

Gli endpoint /users/* richiedono users.manage. GET /api/users/:id/capabilities e PATCH /api/users/:id/capabilities richiedono anche che l'attore risolto dal BFF abbia role=ADMIN; questi endpoint normalizzano i grant membership su platform-auth-service e mantengono il frontend same-origin.

Import/export, sharing, serie, investimenti, simulazione e pay-yourself-first richiedono capability dedicate e restituiscono 403 Forbidden quando il piano o il ruolo non le concede.

Contratto di classificazione ​

La creazione di una transazione o di una TransactionSeries richiede financialNature. Il BFF rifiuta una combinazione incompatibile con la direzione: CREDIT accetta ACTIVE/PASSIVE, DEBT accetta MAINTENANCE/INVESTMENT. L’aggiornamento applica la stessa validazione e, quando il movimento eredita una ricorrenza, conserva la sorgente SERIES_INHERITED.

I read model restituiscono financialNature, financialNatureSource e periodicity. periodicity è calcolata dalla presenza della serie o dalla cadenza di un interesse investimento; non esiste un campo persistito duplicato per la periodicità. Gli investimenti non ricevono una classificazione: gli interessi sono PASSIVE con sorgente INVESTMENT_DERIVED e il capitale rimborsato è passivo e straordinario.

Il CSV usa l’header natura e i valori della nuova classificazione (ATTIVO, PASSIVO, MANTENIMENTO, INVESTIMENTO, oppure i corrispondenti enum inglesi). I vecchi header, valori e contratti non hanno alias o fallback.

Setup della Plancia ​

Il contratto di configurazione è ristretto a:

ts
type PlanningSetupRequest = {
  profile: {
    displayName?: string;
    primaryObjective: string;
  };
};

GET /api/planning/setup restituisce lo stato corrente. POST /api/planning/setup rilegge nella stessa transazione i movimenti owner, le ricorrenze attive e gli investimenti owner, costruisce il baseline della finestra corrente di dodici mesi e salva soltanto profilo e ciclo. Rapporti, controparti e serie non vengono creati indirettamente.

La readiness richiede almeno un costo reale nel baseline. Se manca, la risposta è un errore strutturato con codice PLANNING_DATASET_INSUFFICIENT e il database non riceve scritture parziali. Le entrate passive possono essere zero; una proiezione senza costi espone lo stato NON_CALCOLABILE e non la copertura del 100%.

Rollout PostgreSQL ​

Il rollout distruttivo richiede un database di staging e scritture bloccate durante il cutover. I comandi disponibili in apps/api/package.json sono:

  1. db:financial-nature:backup crea un dump custom PostgreSQL e il relativo checksum SHA-256.
  2. db:financial-nature:restore-staging verifica il checksum e ripristina il dump nello staging.
  3. db:financial-nature:stage applica la migrazione temporanea e la registra con prisma migrate resolve, mantenendo il lock durante la traduzione delle entrate.
  4. db:financial-nature:generate-manifest genera il manifest completo delle vecchie uscite ordinarie.
  5. db:financial-nature:apply-manifest acquisisce il lock sulle tabelle di ledger, verifica copertura e immutabilità dei dati e applica soltanto MAINTENANCE/INVESTMENT.
  6. db:financial-nature:finalize riacquisisce il lock, riusa il manifest in modo idempotente, applica la migrazione finale e la registra.
  7. db:financial-nature:snapshot e db:financial-nature:verify confrontano conteggi, totali, relazioni, combinazioni valide e rimozione dei tipi legacy.

La migrazione staging traduce automaticamente solo le entrate. La migrazione finale interrompe il processo se manca anche una sola voce del manifest, verifica le combinazioni direzione/natura e poi rimuove colonne, enum e tabella temporanea legacy.

Cancellazione bulk movimenti ​

POST /api/transactions/bulk-delete accetta {"transactionIds":["..."]} con un numero compreso tra 1 e 5000 di ID univoci e richiede transactions.write.

Il BFF verifica l'ownership dell'intero insieme e rifiuta i movimenti generati da interessi investimento. Verifica e deleteMany avvengono nella stessa transazione database: se anche un solo ID non e accessibile o non e eliminabile, nessun movimento viene cancellato. La risposta di successo e {"deletedCount":<numero>}.

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