Backend Strategy
The backend defaults to NestJS with a modular-monolith structure.
Recommended Layers
domainapplicationinfrastructureinterfaces
Current starter baseline:
src/main.tssrc/app.module.tssrc/common/config/src/health/src/observability/src/modules/as the reserved home for the first real product modules
First Real Module
New backend modules should be added under:
src/modules/<module-name>/
├── domain/
├── application/
├── infrastructure/
└── interfaces/http/
Guardrails
- keep controllers transport-focused
- validate untrusted input at boundaries
- keep orchestration out of controllers
- keep domain logic free from infrastructure details
- keep observability and user-safe error handling in the runtime path for every protected workflow
- avoid logging secrets, uploaded contents, transaction descriptions, or personal finance details
- document transaction and ownership boundaries before feature breadth grows
- async finance jobs must be persisted, scoped by authenticated user, expose progress/current-step/fallback-error state, and be safe to resume or inspect without exposing another user's preview data
- AI integrations may return suggestions for human review, but backend code must not auto-create user categories from model output
- Import direction must be normalized from source evidence before preview and before category classification: explicit negative/debit/saída lines become withdrawals, explicit positive/credit/entrada lines become deposits, and AI category output cannot flip signed rows or convert them into transfers. Transfers require explicit transfer evidence without an overriding source sign.
- Import reimport and ignored-row handling must be backend-owned before preview totals and again at confirmation. The backend detects fuzzy duplicates against saved transactions and PDF summary/balance/total rows that AI or parsers return as false positives. It must not auto-collapse equal rows inside one upload because those can be legitimate repeated movements.
- user-managed finance categories must be scoped by authenticated user; default classifier categories are protected, and deletion must be blocked while transactions reference the category
- voice AI output must be normalized against transcript-derived facts; spoken amount, income/expense intent, payment-vs-income direction, and explicit account/category mentions cannot be overridden by contradictory model JSON