feat(api): foundation canon JCS — Pino+CLS+RFC9457+health+ping (Frente A)

Estabelece a fundação operacional de apps/api conforme STACK.md v2.2 e
CODING-RULES.md v2.0, substituindo o hello-world scaffolded.

- tracing.ts primeiro import (PGD-OBS-001) — stub OTel ativável por env
- EnvSchema Zod 4 com fail-fast (superRefine guarda prod) + EnvModule global
- nestjs-pino com redact LGPD (*.cpf|*.cardNumber|*.password|auth|cookie)
- main.ts hardenizado: helmet, CORS por env, compression, versionamento URI
  /api/v1, graceful shutdown
- ProblemDetailsFilter global (RFC 9457 application/problem+json), Zod -> 422
- Health endpoints /api/v1/health/{live,ready} com memory.checkHeap(350MB)
  (ready skeleton documenta K=3 LRU pool conforme PGD-OBS-003)
- WorkspaceModule via ClsModule.forRootAsync — requestId+workspaceId no CLS,
  idGenerator alinhado com pino-http para mesmo UUID em header e body
- GET /api/v1/ping retornando workspaceId+requestId (alvo de smoke test e
  futuro healthcheck do docker compose)
- ZodValidationPipe (nestjs-zod) como APP_PIPE global
- tsconfig.app.json target ES2023 (alinhado ao base)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-27 17:50:42 +00:00
parent 3a42723c71
commit 055f9f98f0
21 changed files with 1148 additions and 80 deletions

View File

@@ -0,0 +1,36 @@
import { Controller, Get } from '@nestjs/common';
import { ClsService } from 'nestjs-cls';
import type { WorkspaceClsStore } from '../workspace/workspace.types';
// Endpoint de verificação de fundação:
// - confirma que CLS está populando workspaceId + requestId;
// - serve como alvo do healthcheck do docker compose / smoke test;
// - usado pela Web (Frente B) para validar conectividade real.
interface PingResponse {
status: 'ok';
service: string;
version: string;
workspaceId: string;
requestId: string;
uptimeSeconds: number;
now: string;
}
@Controller({ path: 'ping' })
export class PingController {
constructor(private readonly cls: ClsService<WorkspaceClsStore>) {}
@Get()
ping(): PingResponse {
return {
status: 'ok',
service: 'sar-api',
version: process.env['npm_package_version'] ?? '0.1.0',
workspaceId: this.cls.get('workspaceId'),
requestId: this.cls.get('requestId'),
uptimeSeconds: Math.round(process.uptime()),
now: new Date().toISOString(),
};
}
}