Health checks reais, cabeçalhos de segurança e Sentry por ambiente

- `/api/health/live` não toca dependência: distingue processo vivo de
  dependência fora do ar. `/api/health/ready` passou a tocar banco, migrations
  pendentes, Redis com PING, bucket com listagem, configuração e modo de job,
  e reporta em `reasons` só o nome do erro — nunca connection string.
- Configuração inválida encerra o processo. Antes o servidor ficava no ar
  respondendo 500 em todas as rotas, inclusive no liveness, enganando o
  orquestrador: pior que não subir.
- CSP, HSTS, Permissions-Policy e COOP, além dos três cabeçalhos que já
  existiam. `unsafe-inline` em script-src é exigência do bootstrap do App
  Router sem nonce; o resto é fechado e connect-src só aceita o próprio host,
  o Supabase do ambiente e o Sentry.
- `onRequestError` registrado: sem esse export os erros de rota e de render
  do servidor não chegavam ao Sentry. O ambiente do evento deriva de
  ADAPTER_ENV, então homologação e produção não se misturam.
- `withSentryConfig` só atua quando organização, projeto e token existem no
  build, para não quebrar build local nem CI.
- `output: "standalone"` para a imagem de runtime.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
camilafagundesandClaude Opus 5 committed 2026-10-15 20:38:58 -03:00
1 parent f5560cc4ac
commit d43f370359
20 files changed
+330 -47

No files matched your search

+6 -2
View File
@@ -1,3 +1,4 @@
import { adapterEnv } from "@/config/env";
import { scrubSentryEvent, sentrySafeError } from "./scrub";
export { scrubSentryEvent, sentrySafeError };
@@ -16,6 +17,7 @@ export function captureAdapterException(error: unknown, tags: Record<string, str
void import("@sentry/nextjs").then((Sentry) => {
Sentry.withScope((scope) => {
scope.setTag("module", "spreadsheet-adapter");
scope.setTag("environment_tier", adapterEnv());
for (const [key, value] of Object.entries(tags)) scope.setTag(key, value.slice(0, 120));
Sentry.captureException(sentrySafeError(error));
});
@@ -26,8 +28,10 @@ export function sentryInitOptions(dsn: string | undefined) {
if (!dsn) return null;
return {
dsn,
environment: process.env.SENTRY_ENVIRONMENT || process.env.NODE_ENV,
release: process.env.SENTRY_RELEASE,
// Ambiente lógico do Adaptador: homologação e produção nunca se misturam
// no mesmo grupo de eventos, mesmo com NODE_ENV=production nos dois.
environment: process.env.SENTRY_ENVIRONMENT || adapterEnv(),
release: process.env.SENTRY_RELEASE || process.env.NEXT_PUBLIC_SENTRY_RELEASE,
sendDefaultPii: false,
};
}