# ADR-029 — BLAKE3 como hash de integridade e auditoria

| Campo | Valor |
|---|---|
| **Status** | Aceito (2026-10-16) |
| **Data** | 2026-10-15 |
| **Plano de origem** | `wiki/plan/08-servicos-headless-persistencia.md` · `wiki/implementation/00-importacao-concordia.md` |
| **Relacionadas** | ADR-001, ADR-002, ADR-017, ADR-019, ADR-020, ADR-024, ADR-028 |

## Contexto

A auditoria do CMS precisa de um **hash de integridade determinístico** para selar cada registro
(`integrity_hash`) e para *blind index* de campos sensíveis, de modo que qualquer adulteração seja
detectável e que a trilha seja verificável a longo prazo (conformidade legal de 6–10 anos).

O `cms/` (Concordia) já usava **BLAKE3** (extensão PHP `blake3`) no `AuditService` e no
`HashingService`. O ADR-001 (nativo primeiro, mínimo de dependências) exige **justificar** uma
extensão não nativa. Havia o risco de "otimizar cedo demais"; ao mesmo tempo, a trilha de auditoria
é um caso de uso **real e permanente**, não experimental — diferente de YARA/WORM/crypto-shredding,
que ficaram no backlog.

## Decisão

1. **BLAKE3 é adotado** como o hash de **integridade de auditoria** e de *blind index* do projeto.
   É a escolha canônica para esses dois usos.
2. Fornecida pela **extensão PHP nativa `blake3`**, **pinada por digests/commit** na imagem de
   runtime (plano 04, ADR-005/ADR-031). **Não é PECL**: usa-se
   [`ExinOne/php-blake3-ext`](https://github.com/ExinOne/php-blake3-ext) (**Apache-2.0**), que
   vendoriza o **C oficial BLAKE3 1.8.2** (commit `df610ddc…`), compilada no Dockerfile a partir do
   commit `3d86cdaf9bcc52ebfd4c52120e987fc6a7fb2984`. A API exposta é **`blake3_hash()`**.
   O ambiente **deve** provê-la; a ausência é erro de build, não *fallback* silencioso.
3. `HashingService` expõe `hashString()`, `hashArray()` (ordenação determinística de chaves) e
   `verifyArray()` (`hash_equals`). `AuditService` usa BLAKE3 para `integrity_hash`.
4. **SHA-256 permanece apenas para usos não criptográficos de integridade** (ex.: anonimização de
   IP em telemetria). Não substitui BLAKE3 na auditoria.
5. **Não adotados** (backlog `cripto-auditoria-avancada.md`): YARA, WORM e crypto-shredding. BLAKE3
   é independente deles.
6. Determinismo (ADR-001): o payload é serializado com chaves ordenadas antes do hash, garantindo
   que o mesmo conteúdo produza sempre o mesmo `integrity_hash` (base de testes sem *flaky*).

## Justificativa (alternativas descartadas)

- **SHA-256 para auditoria** — descartada: BLAKE3 é substancialmente mais rápido em volume alto de
  logs, com segurança equivalente de 256 bits; auditoria é caminho quente.
- **SHA-3 / SHAKE** — descartada: sem ganho de desempenho frente a BLAKE3 e sem a extensão pronta.
- **HMAC-SHA-256 (chaveado)** — descartada: BLAKE3 já atende integridade; chaveamento não é
  requisito do selo de auditoria (o controle é o trigger de imutabilidade, ADR-017).
- **Extensão `blake3` (PECL)** — descartada: **não existe** `pecl.php.net/blake3`; adotou-se a
  extensão nativa Apache-2.0 (`ExinOne/php-blake3-ext`) com o C oficial vendorizado e commit pinado.
- **Só hashes nativos, remover BLAKE3** — descartada: em volume alto o custo aparece; a extensão é
  pequena, permissiva e pinável.

## Consequências

**Positivas**
- Selo de integridade rápido e verificável; *blind index* eficiente para PII (ADR-019).
- Uma primitiva só, canônica, testável e determinística.

**Custos / negativas**
- A imagem de runtime depende da extensão `blake3` (build/pin por digest) — falha de build se
  ausente.
- A extensão precisa ser mantida compatível com PHP 8.4 no upgrade do runtime.

## Exemplo mínimo (comparativo)

```php
// ✅ Adotado: BLAKE3 na auditoria (ordenação determinística antes do hash)
ksort($data);
$hash = blake3(json_encode($data, JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR));

// ⚠️ Permitido só para uso não criptográfico (ex.: anonimizar IP em telemetria)
$ipHash = hash('sha256', $request->ip());
```

## Verificação

- `php -m | grep -i blake3` presente no container de runtime (gate do plano 04).
- `HashingService`/`AuditService` usam `blake3()`; teste verifica `verifyArray()` e determinismo
  (mesmo input ⇒ mesmo hash).
- `tools/name-check`/grep não encontra `blake3` fora do escopo de hashing/auditoria.

## Referências

- `cms/core/Internal/Audit/Services/AuditService.php`; `cms/services/Security/HashingService.php`;
  `wiki/plan/04-runtime-containers.md`; `wiki/plan/08-servicos-headless-persistencia.md`;
  `wiki/backlog/cripto-auditoria-avancada.md`.
