Verificar integridade da cadeia de auditoria — API
Recalcula e confere a cadeia de hash de um ou mais escopos de auditoria (um tenant, ou o escopo
__system__ de eventos sem tenant), para provar que nenhuma entrada persistida foi alterada,
removida ou inserida fora de ordem desde que foi gravada. É a rota que responde "esta trilha ainda é
confiável?" — não lista entradas, só atesta a cadeia.
Funcionamento
JwtAuthenticationGuard+AuthorizationGuardexigemaudit:readno escopotenant-list(mesma exigência da rota geral de listagem — por isso um leitor restrito só a unidades, sem nenhum tenant concedido, é recusado aqui mesmo que consiga listar logs de sua unidade).- O parâmetro
scope(umtenantIdou__system__) é resolvido para a lista de escopos que o chamador pode verificar: sescopefor omitido ou*, verifica todos os escopos que existem e que o chamador pode acessar (com__system__sempre verificado primeiro, quando presente e acessível); se um escopo específico for pedido fora do que o chamador acessa, a verificação roda sobre uma lista vazia (sucesso vazio, não erro). - Para cada escopo, a cadeia inteira é percorrida em páginas de 1000 linhas, em ordem de
seqcrescente, recalculando o hash de cada linha a partir do seu conteúdo e do hash anterior. - Ao final da cadeia, o checkpoint assinado do escopo é conferido: a assinatura HMAC precisa bater, e o par (hash da última linha, contagem de entradas) do checkpoint precisa coincidir com o que foi recalculado.
- Se qualquer escopo verificado apresentar uma quebra, a chamada inteira falha com
409— a resposta de sucesso (200) só existe quando todos os escopos verificados estão íntegros.
Endpoints
| Método | Rota | Descrição |
|---|---|---|
| GET | /v1/audit-logs/integrity | Verifica a cadeia de hash de um escopo, ou de todos os escopos acessíveis |
Versão: v1
Swagger: Audit · Rota (Dev): http://localhost:3001/v1/audit-logs/integrity
Permissões
| Rota | Guards | Perfil / escopo exigido |
|---|---|---|
GET /audit-logs/integrity | JwtAuthenticationGuard, AuthorizationGuard | audit:read no escopo tenant-list (mesmo requisito da listagem geral); um administrador de plataforma pode verificar explicitamente o escopo __system__ |
Um leitor restrito a uma unidade específica (sem nenhum tenant concedido em nível de tenant-list) é
recusado com 403 FORBIDDEN_ACTION, mesmo tendo audit:read — a integridade é sempre uma operação
de tenant, nunca de unidade isolada.
Headers
| Header | Obrigatório | Descrição |
|---|---|---|
Authorization | Sim | Bearer <access_token> |
Path parameters
Nenhum.
Query parameters
| Nome | Tipo | Obrigatório | Default | Descrição |
|---|---|---|---|---|
scope | string (até 64) | Não | * | Um tenantId específico, __system__, ou * para verificar todos os escopos acessíveis. Parâmetro repetido é tratado como se tivesse sido omitido (default *). |
Body
Não se aplica — a rota é GET.
Response
200 — todos os escopos verificados estão íntegros (AuditIntegrityResponseDto):
json{"data": [{"scope": "02ea27af-05c0-4af6-be75-8cd17bdf6340","verified": true,"checkedCount": 587},{"scope": "__system__","verified": true,"checkedCount": 12}]}
Quando há quebra, a rota não devolve 200 com verified: false — ela lança um erro 409 (ver
Erros) assim que encontra o primeiro escopo quebrado, na ordem determinística
(__system__ primeiro, depois os demais em ordem alfabética). Escopos verificados com sucesso antes
do primeiro quebrado não aparecem na resposta de erro.
Erros
| Classe de erro | errorCode | Status | Quando ocorre |
|---|---|---|---|
UnauthenticatedError | UNAUTHENTICATED | 401 | Sem token ou token inválido |
ForbiddenAction | AUTHORIZATION_CLAIM_UNAVAILABLE | 403 | Ator sem claim de autorização |
ForbiddenAction | FORBIDDEN_ACTION | 403 | Sem audit:read no escopo tenant-list |
AuditChainForkError | AUDIT_CHAIN_FORK | 409 | O primeiro escopo quebrado tem um elo rompido (previousHash da linha não bate com o hash anterior — inclui o caso de uma linha no meio da cadeia ter sido removida, ou a primeira linha alegar um predecessor inexistente) |
AuditChainTamperedError | AUDIT_CHAIN_TAMPERED | 409 | O primeiro escopo quebrado tem qualquer outro tipo de violação: hash ausente, hash recalculado diferente do armazenado, checkpoint ausente para uma cadeia não vazia, checkpoint com assinatura forjada, ou checkpoint que diverge da cadeia recalculada (cauda apagada) |
Regras de negócio
| ID | Regra | Comportamento esperado |
|---|---|---|
| RN-01 | Verificação falha fechada (fail closed) | Qualquer quebra observável interrompe a resposta com 409; não existe um "meio-termo" de sucesso parcial |
| RN-02 | broken_link vira AUDIT_CHAIN_FORK; todo o resto vira AUDIT_CHAIN_TAMPERED | missing_hash, hash_mismatch, missing_checkpoint, forged_checkpoint e truncated são todos reportados como adulteração; só o elo rompido é reportado como fork |
| RN-03 | Escopo vazio sem checkpoint é considerado íntegro | Uma cadeia que nunca recebeu entradas (sem linhas e sem checkpoint) verifica como verified: true, checkedCount: 0 |
| RN-04 | Escopo com linhas mas sem checkpoint é uma quebra | Toda cadeia não vazia deve ter um checkpoint avançado; a ausência é missing_checkpoint |
| RN-05 | * nunca revela escopos fora do acesso do chamador | A verificação "todos os escopos" é sempre filtrada pelos tenants que o chamador acessa; um tenant não vê o escopo __system__ nem o de outro tenant |
| RN-06 | Pedir um escopo específico fora do acesso do chamador não é erro | A resposta é um sucesso vazio (data: []), não 403 nem 409 — evita confirmar/negar a existência do escopo para quem não tem acesso |
| RN-07 | A ordem de verificação é determinística | __system__ primeiro (quando presente), depois os demais escopos em ordem alfabética — importante porque só o primeiro breach encontrado é reportado |
Compliance
| Órgão / norma | Exigência | Como a rota atende |
|---|---|---|
| LGPD / HIPAA / ANVISA (trilha íntegra e auditável) | garantir que o histórico não foi adulterado retroativamente | cadeia de hash + checkpoint assinado por HMAC, verificável sob demanda; qualquer adulteração observável falha a chamada em vez de mascará-la |
Esta capacidade não existia no legado descrito nos cards de auditoria (trilha em Mongo, sem hash-chain, com entradas apagáveis) — é uma melhoria confirmada no código atual.
Variáveis de ambiente
| Variável | Uso | Obrigatória |
|---|---|---|
AUDIT_HMAC_ACTIVE_KEY_ID / AUDIT_HMAC_KEYS | anel de chaves HMAC usado para assinar e verificar os checkpoints | Sim em produção (há fallback de desenvolvimento apenas quando NODE_ENV é local/test) |
Tempo médio de resposta
A confirmar — responsável: time de Audit; data: 24/09/2026. O custo cresce com o tamanho da
cadeia verificada (paginação de 1000 linhas por vez); não há medição publicada.
Requisitos não funcionais
| Requisito | Definição |
|---|---|
| Idempotência | Sim — leitura pura, não altera estado |
| Paginação | Não se aplica à resposta (um item por escopo verificado); internamente a cadeia é lida em páginas de 1000 linhas |
| Rate limit | Aplicado no nível do microsserviço; sem limite específico documentado para esta rota |
| Cache | Não |
| Auditoria | Não se aplica |
Relacionado
- 📂 Módulo: Audit
- 🔎 Ver também: Consultar logs
- 🔗 Fluxo de gravação que produz a cadeia verificada aqui: Registrar evento