Fase 03 — Product Delivery
HITLs #7-#10 Aprovados Architect + Backend + Frontend + QA

Fase 03 — Product Delivery

Arquitetura DDD, API REST, frontend React SPA e qualidade — do design de domínio ao deploy.

5
Bounded Contexts
7
ADRs
27
Endpoints
9
Tabelas
10
Páginas
29
Test Cases
10/10
Quality Gates

Arquitetura — Domain-Driven Design

5 Bounded Contexts em monólito modular Node.js (Fastify). Separação lógica em módulos distintos em /server, com path de extração para microsserviços no futuro.

classDiagram class IdentityAccess { +User (aggregate root) +Session (stateless JWT) +Email, CPF, HashedPassword POST /auth/register POST /auth/login GET /users/me } class BankingCore { +Account (aggregate root) +Transaction +Money, TransactionCategory GET /accounts/balance GET /transactions GET /transactions/summary } class Pix { +PixKey (aggregate root) +PixTransfer +PixKeyType, PixLimit POST /pix/transfer GET /pix/keys POST /pix/keys } class CardsPayments { +Card (aggregate root) +Invoice, CardPurchase +CardNumber, CardLimit GET /cards POST /payments/boleto } class Intelligence { +Notification (aggregate root) +SalaryCycle, CategoryRule GET /transactions/summary } IdentityAccess --> BankingCore : UserRegistered IdentityAccess --> Pix : User exists IdentityAccess --> CardsPayments : User exists Pix --> BankingCore : debit/credit CardsPayments --> BankingCore : debit BankingCore --> Intelligence : events Pix --> Intelligence : events CardsPayments --> Intelligence : events

Bounded Contexts

BCNomeTipoMódulosResponsabilidade
BC-01Identity & AccessSupportingauth, usersIdentidade, autenticação JWT, autorização, ciclo de vida de sessões
BC-02Banking CoreCoreaccounts, transactionsCustódia do saldo, débito/crédito atômicos, ledger imutável, categorização
BC-03PixCorepixChaves Pix, transferências, limites por horário, QR Code
BC-04Cards & PaymentsSupportingcards, paymentsCartão virtual, faturas, compras, pagamento de boletos
BC-05IntelligenceSupportingtransactions (summary), notificationsCategorização automática, insights, notificações, ciclo salarial

Architecture Decision Records (ADRs)

ADR-001
SQLite3 como banco de dados do MVP em vez de PostgreSQL
Status: Accepted
Zero configuração — arquivo único database.sqlite. Sem servidor separado. Transações ACID completas via better-sqlite3 (síncrono). Performance excelente para cargas <100 writes/segundo. Migração para PostgreSQL planejada quando escala horizontal for requisito.
ADR-002
SQL direto via better-sqlite3 em vez de ORM (Prisma, TypeORM, Drizzle)
Status: Accepted
Queries de domínio financeiro (débito + registro de transação) são explícitas e auditáveis. Zero overhead de ORM. Prepared statements automáticos via better-sqlite3 — SQL injection impossível com uso correto.
ADR-003
Autenticação JWT local com bcryptjs em vez de provedor externo
Status: Accepted
Zero dependência externa. CPF e e-mail nunca saem do servidor. Autenticação reforçada (RN-03) implementada como middleware nativo Fastify. Token JWT HS256 com expiry de 24h. bcryptjs (pure JS, saltRounds=10).
ADR-004
SPA com React+Vite em vez de SSR com Next.js
Status: Accepted
Produto web-first autenticado — nenhuma tela precisa de SEO. SPA oferece experiência mais próxima de desktop app. Vite HMR <50ms. Bundle servido pelo próprio Fastify como arquivos estáticos.
ADR-005
Valores monetários como INTEGER em centavos em vez de DECIMAL/FLOAT
Status: Accepted
Padrão Stripe/Adyen/PagSeguro. Precisão absoluta — sem ponto flutuante. R$1.234,56 = 123456 centavos. Limites de Pix verificados com comparação inteira. SQLite INTEGER 64-bit suporta até ~R$92 quadrilhões.
ADR-006
Soft delete com coluna deleted_at em vez de deleção física
Status: Accepted
RN-07 define soft delete como requisito. Histórico de auditoria 100% preservado. Compliance bancário: registros nunca destruídos. Reversibilidade de operações equivocadas.
ADR-007
Convenção de 3 arquivos por módulo: schema.ts + routes.ts + service.ts
Status: Accepted
schema.ts: Zod schemas para validação + tipos TypeScript inferidos. routes.ts: Fastify plugin com rotas (zero lógica de negócio). service.ts: lógica de domínio pura com acesso direto ao banco. Service testável sem servidor HTTP.

Stack Tecnológica

Backend
  • Runtime: Node.js 18+
  • Framework: Fastify 5.0
  • Database: SQLite3 (better-sqlite3) com WAL mode
  • Auth: JWT (jsonwebtoken) + bcryptjs
  • Validation: Zod 3.23
  • Language: TypeScript 5.6 (strict)
  • Test: Vitest
Frontend
  • Framework: React 18.3
  • Build: Vite 5.4
  • Routing: React Router 6.26
  • Styling: Tailwind CSS 3.4
  • Icons: Lucide React
  • Language: TypeScript 5.5 (strict)
  • State: React hooks + Context

Diagramas de Sequência

Autenticação — Registro e Login

sequenceDiagram participant U as Usuário (Browser) participant F as Frontend (React) participant A as API (Fastify) participant DB as SQLite Note over U,DB: Registro de nova conta U->>F: Preenche nome, email, CPF, senha F->>A: POST /api/auth/register A->>DB: SELECT user WHERE email = ? DB-->>A: null (não existe) A->>A: bcrypt.hash(senha, 12) A->>DB: INSERT users + INSERT accounts DB-->>A: userId, accountId A->>A: jwt.sign({ id, email }) A-->>F: { token, user } F->>F: localStorage.set(ecp_token) F-->>U: Redirect /dashboard Note over U,DB: Login U->>F: Preenche email, senha F->>A: POST /api/auth/login A->>DB: SELECT user WHERE email = ? DB-->>A: user (com password_hash) A->>A: bcrypt.compare(senha, hash) A->>A: jwt.sign({ id, email }, 7d) A-->>F: { token, user } F->>F: localStorage.set(ecp_token) F-->>U: Redirect /dashboard

Envio de Pix — Fluxo Completo com Validações

sequenceDiagram participant U as Usuário (Browser) participant F as Frontend (React) participant A as API (Fastify) participant DB as SQLite U->>F: Informa chave Pix destino F->>A: GET /api/pix/lookup?key=... A->>DB: SELECT pix_key WHERE key_value = ? DB-->>A: { userId, name, keyType } A-->>F: { name: "João Silva", keyType: "cpf" } F-->>U: Exibe destinatário U->>F: Informa valor (ex: R$ 500) F->>A: POST /api/pix/transfer Note over A: Middleware: JWT auth A->>A: Verificar rate limit (RN-10: max 10/hora) A->>DB: SELECT COUNT pix_rate_limit (ultima hora) DB-->>A: count = 3 (OK) A->>A: Verificar limite horário alt 22h-6h (noturno) A->>A: RN-02: valor <= R$ 1.000? else 6h-22h (diurno) A->>A: RN-01: acumulado dia <= R$ 5.000? end alt Valor > R$ 2.000 A-->>F: Requer autenticação reforçada (RN-03) F-->>U: Modal de confirmação + senha U->>F: Confirma com senha F->>A: POST /api/pix/transfer (com confirmação) end A->>A: Verificar saldo (RN-04) A->>DB: SELECT balance_cents FROM accounts DB-->>A: balance = 150000 (R$ 1.500) Note over A,DB: Transação atômica (SQLite) A->>DB: BEGIN TRANSACTION A->>DB: UPDATE accounts SET balance -= 50000 (remetente) A->>DB: UPDATE accounts SET balance += 50000 (destinatário) A->>DB: INSERT transactions (débito remetente) A->>DB: INSERT transactions (crédito destinatário) A->>DB: INSERT pix_rate_limit A->>DB: INSERT notifications (destinatário) A->>DB: COMMIT A-->>F: { transactionId, status: "completed", balanceAfter } F-->>U: Tela de sucesso com comprovante

Compra com Cartão Virtual

sequenceDiagram participant M as Merchant / FoodFlow participant A as API (Fastify) participant DB as SQLite M->>A: POST /api/cards/:id/purchase Note over A: { amountCents, description, merchantName } Note over A: Middleware: JWT auth A->>DB: SELECT card WHERE id = ? AND user_id = ? DB-->>A: card { limitCents: 300000, usedCents: 124750, isBlocked: false } A->>A: Verificar cartão ativo e não bloqueado A->>A: Verificar limite disponível Note over A: disponivel = 300000 - 124750 = 175250 alt amountCents > disponível A-->>M: 400 CARD_LIMIT_EXCEEDED else amountCents <= disponível A->>DB: SELECT/CREATE invoice (mês atual, status open) DB-->>A: invoice { id, totalCents } Note over A,DB: Transação atômica A->>DB: BEGIN TRANSACTION A->>DB: INSERT card_purchases A->>DB: UPDATE cards SET used_cents += amountCents A->>DB: UPDATE invoices SET total_cents += amountCents A->>DB: COMMIT A-->>M: 201 { purchaseId, status: "completed", availableAfterCents } end

Pagamento de Boleto

sequenceDiagram participant U as Usuário (Browser) participant F as Frontend (React) participant A as API (Fastify) participant DB as SQLite U->>F: Cola código de barras do boleto F->>F: Decodifica linha digitável (valor, vencimento, beneficiário) F-->>U: Exibe breakdown de transparência U->>F: Confirma pagamento F->>A: POST /api/payments/boleto Note over A: { barcode, amount, scheduledFor? } Note over A: Middleware: JWT auth A->>A: Verificar saldo (RN-04) A->>DB: SELECT balance_cents FROM accounts DB-->>A: balance = 423578 alt scheduledFor (agendado) A->>DB: INSERT transactions (status: pending, scheduled_for) A-->>F: { transactionId, status: "pending", scheduledFor } F-->>U: "Boleto agendado para DD/MM" else Pagamento imediato Note over A,DB: Transação atômica A->>DB: BEGIN TRANSACTION A->>DB: UPDATE accounts SET balance -= amountCents A->>DB: INSERT transactions (status: completed, category: boleto) A->>DB: INSERT notifications A->>DB: COMMIT A-->>F: { transactionId, status: "completed", balanceAfter } F-->>U: Tela de sucesso com comprovante end

Dashboard — Carregamento Inicial

sequenceDiagram participant U as Usuário (Browser) participant F as Frontend (React) participant A as API (Fastify) participant DB as SQLite U->>F: Acessa /dashboard F->>F: Verifica JWT no localStorage par Chamadas paralelas F->>A: GET /api/accounts/me/balance A->>DB: SELECT balance_cents FROM accounts A-->>F: { balanceCents: 423578 } and F->>A: GET /api/transactions?limit=5 A->>DB: SELECT * FROM transactions ORDER BY created_at DESC LIMIT 5 A-->>F: { transactions: [...] } and F->>A: GET /api/transactions/summary A->>DB: SELECT category, SUM(amount) GROUP BY category A-->>F: { categories: [...], totalIncome, totalExpense } and F->>A: GET /api/cards A->>DB: SELECT * FROM cards WHERE user_id = ? A-->>F: { cards: [...] } and F->>A: GET /api/notifications/unread-count A->>DB: SELECT COUNT(*) WHERE is_read = 0 A-->>F: { count: 3 } end F->>F: Renderiza dashboard completo F-->>U: Saldo + Donut chart + Transações + Cartão + Notificações

API — 9 Módulos, 27 Endpoints

Auth (3 endpoints)

POST/api/auth/register
POST/api/auth/login
GET/api/auth/me

Accounts (3 endpoints)

GET/api/accounts/me
GET/api/accounts/me/balance
PATCH/api/accounts/me/limit

Pix (5 endpoints)

GET/api/pix/keys
POST/api/pix/keys
DELETE/api/pix/keys/:keyId
POST/api/pix/transfer
GET/api/pix/lookup

Transactions (2 endpoints)

GET/api/transactions
GET/api/transactions/:id

Cards (5 endpoints)

GET/api/cards
GET/api/cards/:id
PATCH/api/cards/:id/limit
PATCH/api/cards/:id/block
GET/api/cards/:id/invoice

Payments (3 endpoints)

POST/api/payments/boleto
GET/api/payments/scheduled
DELETE/api/payments/scheduled/:id

Users (3 endpoints)

GET/api/users/me
PATCH/api/users/me
POST/api/users/me/change-password

Notifications (4 endpoints)

GET/api/notifications
GET/api/notifications/unread-count
PATCH/api/notifications/:id/read
POST/api/notifications/read-all

Dashboard (1 endpoint)

GET/api/dashboard

Modelo Entidade-Relacionamento (MER)

9 tabelas, 12 índices. SQLite3 com WAL mode e foreign keys habilitadas. Valores monetários em centavos (INTEGER).

erDiagram users { TEXT id PK TEXT name TEXT email UK TEXT cpf UK TEXT password_hash TEXT phone TEXT avatar_url INTEGER is_active TEXT created_at TEXT updated_at } accounts { TEXT id PK TEXT user_id FK "UK" TEXT agency TEXT number UK INTEGER balance_cents INTEGER daily_transfer_limit_cents INTEGER daily_transferred_cents TEXT last_transfer_date INTEGER is_active TEXT created_at TEXT updated_at } pix_keys { TEXT id PK TEXT user_id FK TEXT account_id FK TEXT key_type "cpf email phone random" TEXT key_value UK INTEGER is_active TEXT created_at TEXT deleted_at "soft delete" } transactions { TEXT id PK TEXT account_id FK TEXT type "credit debit" TEXT category "pix boleto card_purchase transfer deposit withdrawal refund fee" INTEGER amount_cents INTEGER balance_after_cents TEXT description TEXT counterpart_name TEXT counterpart_document TEXT counterpart_institution TEXT pix_key TEXT pix_key_type TEXT boleto_code TEXT status "pending completed failed cancelled" TEXT scheduled_for TEXT created_at } cards { TEXT id PK TEXT user_id FK TEXT account_id FK TEXT type "physical virtual" TEXT card_number TEXT last4 TEXT card_holder TEXT card_expiry INTEGER limit_cents INTEGER used_cents INTEGER due_day INTEGER is_active INTEGER is_blocked TEXT created_at TEXT updated_at } invoices { TEXT id PK TEXT card_id FK TEXT reference_month INTEGER total_cents TEXT due_date TEXT status "open closed paid overdue" TEXT paid_at TEXT created_at TEXT updated_at } card_purchases { TEXT id PK TEXT card_id FK TEXT invoice_id FK TEXT description TEXT merchant_name TEXT merchant_category INTEGER amount_cents INTEGER installments INTEGER current_installment TEXT status "pending completed cancelled refunded" TEXT purchased_at } notifications { TEXT id PK TEXT user_id FK TEXT title TEXT body TEXT type "transaction security marketing system" INTEGER is_read TEXT created_at } pix_rate_limit { TEXT id PK TEXT account_id FK TEXT window_start INTEGER transfer_count } users ||--|| accounts : "1:1 possui" users ||--o{ pix_keys : "1:N registra" users ||--o{ cards : "1:N possui" users ||--o{ notifications : "1:N recebe" accounts ||--o{ pix_keys : "1:N vincula" accounts ||--o{ transactions : "1:N movimenta" accounts ||--o{ cards : "1:N associa" accounts ||--o{ pix_rate_limit : "1:N controla" cards ||--o{ invoices : "1:N gera" cards ||--o{ card_purchases : "1:N registra" invoices ||--o{ card_purchases : "1:N agrupa"

Cardinalidades

RelacionamentoTipoDescrição
users ↔ accounts1:1Cada usuário possui exatamente uma conta bancária
users ↔ pix_keys1:NAté 5 chaves Pix por usuário (RN-05)
users ↔ cards1:NMúltiplos cartões virtuais por usuário
users ↔ notifications1:NNotificações de eventos financeiros e segurança
accounts ↔ transactions1:NLedger imutável de movimentações (crédito/débito)
accounts ↔ pix_rate_limit1:NControle de 10 Pix/hora por conta (RN-10)
cards ↔ invoices1:NUma fatura por mês de referência por cartão
cards ↔ card_purchases1:NCompras registradas no cartão (merchant + categoria)
invoices ↔ card_purchases1:NCompras agrupadas na fatura do mês

Banco de Dados

SQLite3 com WAL mode e foreign keys. 9 tabelas, 12 índices.

TabelaDescriçãoAggregate Root
usersDados de identidade (nome, email, CPF, password hash, salary_day)User (BC-01)
accountsConta bancária com saldo em centavos, número da conta, limitesAccount (BC-02)
transactionsLedger imutável de movimentações (crédito/débito) com categoria
pix_keysChaves Pix (CPF, email, telefone, EVP) com soft deletePixKey (BC-03)
cardsCartão virtual com limite, status (active/blocked/cancelled)Card (BC-04)
invoicesFaturas mensais do cartão (open/closed/paid)
card_purchasesCompras registradas no cartão com merchant e categoria
notificationsNotificações de eventos financeiros com status read/unreadNotification (BC-05)
pix_rate_limitControle de rate limit de Pix por hora por usuário (RN-10)

Frontend — React SPA

10 Páginas

PáginaArquivoFeatures Principais
Loginroutes/login.tsxEmail + senha, show/hide password, error handling
Registroroutes/register.tsxNome, email, CPF mask, validação de senha (regex)
Dashboardroutes/dashboard.tsxSaldo show/hide, quick actions, SVG donut chart, card summary, últimas 5 transações
Extratoroutes/extrato.tsxLista paginada com filtros, category badges, paginação com contador
Pix Enviarroutes/pix/enviar.tsxFluxo multi-step (chave → valor → confirmar → sucesso), lookup de chave
Pix Receberroutes/pix/receber.tsxLista de chaves, copy-to-clipboard, dados da conta
Pix Chavesroutes/pix/chaves.tsxCRUD completo, modal, contador 5/5, confirm dialog
Cartõesroutes/cartoes.tsxCard visual com gradiente, barra de limite, block/unblock, fatura
Pagamentosroutes/pagamentos.tsxFormulário de boleto, agendamento, lista de agendados
Perfilroutes/perfil.tsxEditar nome/telefone, alterar senha, logout

9 Componentes

UI Components
  • Button: 4 variants (primary, secondary, ghost, danger), 3 sizes, loading spinner
  • Card: 2 variants (default, highlighted), 4 paddings, sub-components
  • Input: Label, error, hint, left/right icons, forwardRef
  • Modal: Escape key, backdrop click, scroll lock, 3 sizes
  • Badge: 6 variants (success, warning, danger, info, lime, default)
  • Table: Full table primitives
Layout Components
  • Sidebar: Desktop nav com 6 itens, user info, logout
  • Header: Greeting dinâmico, notificações com dropdown (unread count, polling 30s)
  • MobileNav: Bottom nav com 5 itens (lg:hidden)

QA — Qualidade e Testes

Quality Gates — 10/10 Passando

GateStatusDetalhe
Type SafetyPassTypeScript strict em server (39 files) e web (28 files). Zod enforces runtime validation.
Input ValidationPassTodos 27 endpoints validam inputs via Zod + Fastify validation hooks.
Business RulesPass10/10 RNs implementadas (RN-01 a RN-10).
Auth SecurityPassJWT + bcrypt (cost 10). Auth middleware em todas rotas protegidas. CORS configurado.
Error HandlingPassAppError com ErrorCode enum (15 categorias). ZodError transformado. Safe 500 responses.
Design SystemPass100% compliance com design_spec.md. Dark theme, lime accent, Inter font.
API IntegrationPassWeb integra com todos 27 endpoints via fetch wrapper centralizado (api.ts).
ResponsivePassSidebar desktop (≥1024px) + bottom nav mobile. Testado: 375px, 768px, 1024px, 1440px.
Test CoveragePass29 test cases em 4 files. Módulos de maior risco: auth (10), pix (11), accounts (4), payments (4).
AccessibilityPass*Semantic HTML, form labels, color contrast AA. *Notas: skip-to-content e aria-labels em icon buttons pendentes.

Findings (5)

SeveridadeCategoriaDescrição
lowTest Coverage5 módulos (transactions, cards, users, notifications, dashboard) sem test files dedicados. Os 4 módulos testados cobrem funcionalidade de maior risco.
infoAccessibilityFalta skip-to-content link, focus management em route changes, e aria-label em icon buttons.
infoPerformanceFetch wrapper sem caching/deduplication. Considerar React Query ou SWR em iteração futura.
lowSecurityJWT em localStorage (vs. httpOnly cookies). Aceitável para MVP sem scripts terceiros.
infoObservabilityLogging via console sem formato estruturado. Integrar pino (nativo Fastify) na Fase 04.

HITLs da Fase 03

HITLEscopoAgenteDecisão
#7Arquitetura DDD (5 BCs, 7 ADRs, linguagem ubíqua, agregados)Software ArchitectAprovado
#8Backend (9 módulos, 27 endpoints, 10/10 RNs, 9 tabelas, seed)Backend DeveloperAprovado
#9Frontend (10 páginas, 9 componentes, design system compliance)Frontend DeveloperAprovado
#10QA (29 test cases, 10/10 quality gates, 5 findings info/low)QAAprovado

Artefatos Gerados

03-product-delivery/architecture/bounded-contexts.json 03-product-delivery/architecture/ubiquitous-language.json 03-product-delivery/architecture/aggregates.json 03-product-delivery/architecture/adrs.json 03-product-delivery/architect-output.json 03-product-delivery/backend-output.json 03-product-delivery/frontend-output.json 03-product-delivery/qa-report.json 03-product-delivery/phase-03-output.json