feat(api): master-login stub + WorkspacePrismaPool (Frente E)

- Prisma 7: prisma.config.ts com datasource.url (API correta); schema gerado em CJS
- WorkspacePrismaPool: LRU cache (max 10) de PrismaClient por workspace (ADR 0006)
  PrismaPg adapter + pg.Pool por workspace; getOrCreate/health/onModuleDestroy
- JwtAuthGuard: global APP_GUARD, jose HS256, popula CLS com workspace_id/userId/prisma
  @Public() decorator marca ping/health/dev-auth como rotas abertas
- DevAuthController: POST /auth/dev/token — emite JWT dev (404 em produção)
- AuthTokenResponseSchema + DevTokenRequestSchema em @sar/api-interface
- WorkspacePoolHealthIndicator: health/ready reporta amostra LRU top-3 (nunca O(N))
- .npmrc: hoist @prisma/client-runtime-utils (requerido pelo Prisma 7 isolated mode)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-27 22:36:00 +00:00
parent bca2e3ebb3
commit 2a8be3fd82
22 changed files with 1204 additions and 39 deletions

View File

@@ -384,9 +384,35 @@
- **OQs abertas (6):** OQ-1/OQ-4 são phase-blockers para C2/C4 — dependem do primeiro cliente. OQ-3/OQ-6 são non-blockers.
- **Reviewer gate:** 1 revisor subagente — veredito "Aprovado com Ressalvas"; 3 achados incorporados antes do `final`.
- **Pendente próxima sessão (ordem atualizada):**
1. **Master-login stub + WorkspacePrismaPool** — frente arquitetural pesada. PRD está pronto; pode iniciar modelagem de domínio.
2. **OpenTelemetry SDK** plugar quando entrar no catálogo.
3. **Design C2/C4** (Consulta de Clientes + Lançamento de Pedido) — após resolver OQ-1 e OQ-4 com o primeiro cliente.
1. **OpenTelemetry SDK** plugar quando entrar no catálogo.
2. **Design C2/C4** (Consulta de Clientes + Lançamento de Pedido) — após resolver OQ-1 e OQ-4 com o primeiro cliente.
### 2026-05-27 — Master-login stub + WorkspacePrismaPool COMPLETO ✅
**Entregas (M1M7):**
- **M1 — Prisma 7 config corrigida:** `prisma.config.ts` usa `datasource.url` (não `migrate.adapter`) — API correta do Prisma 7. `prisma migrate dev` e `prisma generate` funcionando. Schema vazio (modelos virão com C2/C3).
- **M2 — WorkspacePrismaPool:** LRU cache (max 10) de `PrismaClient` por `workspaceId`. `getOrCreate(workspaceId, dbUrl)`, `health(k=3)`, `onModuleDestroy`. Usa `@prisma/adapter-pg` + `pg.Pool` por workspace (ADR 0006).
- **M3 — JwtAuthGuard:** Guard global (`APP_GUARD`) com `jose` HS256. Valida Bearer token, popula `req.user` com `{sub, workspace_id, role}`. Atualiza CLS com `workspaceId`, `userId` e `prisma` após validação. `@Public()` decorator para ping/health/dev-auth.
- **M4 — Auth dev stub:** `POST /api/v1/auth/dev/token` — emite JWT HS256 com claims `{sub, workspace_id, role}`. Retorna 404 em produção. Contrato `DevTokenRequestSchema` + `AuthTokenResponseSchema` em `@sar/api-interface`.
- **M5 — WorkspaceModule:** CLS setup simplificado (middleware só define `requestId` + `workspaceId` default). Guard sobrescreve workspace real do JWT. Pool não injetado no middleware (limitação do nestjs-cls `ClsRootModule`).
- **M6 — Health ready:** `WorkspacePoolHealthIndicator` adicionado ao `/health/ready`. Amostra top-3 LRU — nunca O(N). `active: 0` quando nenhum workspace criado ainda.
- **M7 — Smoke test:** API sobe limpo. `/health/live` ✓, `/health/ready` ✓ (pool ativo=0), `/ping` público ✓, `POST /auth/dev/token` emite token com claims corretos.
**Decisões técnicas:**
- `@prisma/client-runtime-utils` adicionado como dependência direta no workspace root (pnpm isolated mode não o hoista automaticamente).
- Guard atualiza CLS depois do middleware (ordem correta NestJS: middleware → guard → handler).
- Pool não injetado no ClsRootAsync devido a limitação de DI do nestjs-cls; guard faz a resolução.
**Pendente próxima sessão:**
1. **OpenTelemetry SDK** plugar quando entrar no catálogo.
2. **Modelagem C2** — modelo `Client` no Prisma schema + migração + endpoint `GET /clients`. Requer OQ-1/OQ-4 resolvidos com primeiro cliente.
---