import { Module } from '@nestjs/common'; import { ClsModule } from 'nestjs-cls'; import { randomUUID } from 'node:crypto'; import type { Request, Response } from 'express'; import type { WorkspaceClsStore } from './workspace.types'; import { WorkspacePrismaPool } from './workspace-prisma-pool.service'; // CLS middleware roda ANTES dos guards (ordem NestJS). // Aqui: apenas requestId + idEmpresa default (0 = não autenticado). // JwtAuthGuard atualiza idEmpresa, userId e prisma após validar o token. // CODING-RULES PGD-DB-009: prisma via cls.get('prisma'), nunca singleton. // CODING-RULES PGD-AUTHZ-002: idEmpresa real vem do JWT (guard), não do env. // ADR 0006 revogado: workspaceId: string → idEmpresa: number @Module({ imports: [ ClsModule.forRootAsync({ global: true, useFactory: () => ({ middleware: { mount: true, generateId: true, idGenerator: (req: Request) => { const fromPino = (req as Request & { id?: unknown }).id; if (typeof fromPino === 'string' && fromPino.length > 0) return fromPino; const headerVal = req.headers['x-request-id']; return typeof headerVal === 'string' && headerVal.length > 0 ? headerVal : randomUUID(); }, setup: (cls, req: Request, res: Response) => { const store = cls as unknown as { set: (key: K, value: WorkspaceClsStore[K]) => void; getId: () => string; }; const requestId = store.getId(); res.setHeader('x-request-id', requestId); store.set('requestId', requestId); // Fallback para rotas públicas (ping, health). Guard sobrescreve em rotas protegidas. store.set('idEmpresa', 0); }, }, }), }), ], providers: [WorkspacePrismaPool], exports: [ClsModule, WorkspacePrismaPool], }) export class WorkspaceModule {}