# P12 — Transparência fiscal, dados abertos e estatísticas públicas

| Campo | Valor |
|---|---|
| Programa | F7+ — operação, estrutura e conteúdo |
| Status | `planejado` |
| Depende de | P4, P5.5, P9, P11 |
| Habilita | P13 |
| Tamanho | **G** (4–6 sessões) |
| ADRs | ADR-049 (emenda: `DadosAbertos` owner único), ADR-018, ADR-019, ADR-027, ADR-017, ADR-042; decisão C18 (estender `DadosAbertos` primeiro) |

## 1. Objetivo

Publicar dados fiscais e estatísticas públicas **sobre o que já existe** — `DadosAbertos` (dataset,
DCAT/INDA, CSV/JSON/XML, `ETag`) e as métricas de P4. **Decisão D9:** `Portal/DadosAbertos` é o
**único owner** da camada pública de dados; qualquer outra página/módulo que compile dado dessa
natureza é **view/curadoria**, nunca uma segunda tabela ou um segundo serializador.

**Resultado observável:** um dataset fiscal tem competência `YYYY-MM`, valores como string decimal,
filtros e export determinístico com `ETag`; `/transparencia` agrupa categorias e links; o relatório
público da Ouvidoria/e-SIC mostra volume/prazo agregados sem PII.

## 2. Estado atual

- `src/modules/Portal/DadosAbertos/**`: dataset, DCAT/INDA, CSV/JSON/XML, `ETag`/checksum, API
  `api.<base>/v1/datasets`, sitemap source.
- `Portal/Lgpd` (DSAR/retenção) e `P4` (métricas agregadas) existem.
- `P11` entrega Ouvidoria/e-SIC com prazos e status.
- O dossiê V2 mostra os riscos: `children` sem `active()` (N+1 e inativos), slug só na criação,
  sem CRUD de categorias, sem paginação, sem anexo/CSV/API, nenhum teste.

## 3. Escopo fechado

### S1 — Evolução do `DadosAbertos` (não um módulo irmão)

- Adicionar ao dataset: `categoria_id` (tabela `dados_abertos_categorias` com `slug`, `nome` jsonb,
  `parent_id`, `position`, `active`), `competencia` (`YYYY-MM` nullable), `orgao`, `tags`,
  `frequencia_atualizacao`, `licenca` (default CC-BY 4.0), `metadata` jsonb.
- CRUD de categorias no CMS (o dossiê legado não tinha); categoria inativa não aparece no portal;
  hierarquia com `active()` e sem N+1.
- Filtros server-side: categoria, competência, órgão, período, formato; paginação; ordenação
  determinística; slug imutável após publicação (redirecionar? decisão: slug é estável; edição de
  título não muda slug; se mudar, `301` curado em `seo.redirects`).
- Export CSV/JSON/XML determinístico **via `Services\OpenData` (P5.5)**: ordem explícita,
  `checksum` SHA-256, `ETag`/304, `Content-Disposition`; dinheiro como **string decimal** no JSON
  (nunca `float`); datas ISO. Não recriar `Export` nem serializador local.
- API read-only: filtros allowlist, paginação, rate limit, sem PII; documentação do contrato.
- Upload/carga: target do `Importador` (P9) para CSV/planilha fiscal, com dry-run e relatório;
  nenhum ETL de legado (ADR-042).

### S2 — Dataset fiscal e `/transparencia`

> **D9:** `/transparencia` não tem tabela de dados. É uma página de curadoria (blocos P5) que
> referencia datasets do `DadosAbertos`; P22–P24 são donos dos dados operacionais e publicam via
> `DatasetSource`, mas a camada pública é sempre do `DadosAbertos`.

- Dataset fiscal com `competencia` e valores monetários em string; validação de soma/consistência
  quando o schema permitir; nenhuma coluna `float`/`double` para dinheiro.
- `/transparencia`: página de curadoria (categorias, destaques, links para datasets e serviços),
  construída com os tipos de bloco de P5 (não HTML livre); conteúdo editável no CMS; SEO/sitemap.
- Se o recorte crescer, ele continua sendo **view**: novas páginas/blocos, sem tabela de dataset
  paralela. Um módulo próprio só de apresentação é aceitável; um dono de dado não.
- Acessibilidade: tabelas de dados com `caption`/cabeçalhos, filtros com label, export acessível,
  contraste; 4 locales.

### S3 — Estatísticas públicas

- Página pública `/transparencia/estatisticas` (ou `/estatisticas`) com agregados:
  - Ouvidoria: manifestações por tipo/status, tempo médio de resposta, dentro/fora do prazo;
  - e-SIC: pedidos, prazos, prorrogações, indeferimentos, recursos;
  - portal: requisições por módulo/página (P4), sem PII.
- Fonte: `Metrics`/consultas agregadas; nenhum texto de manifestação, nenhum protocolo individual,
  nenhum IP/hash; supressão de células pequenas quando necessário (ex.: <5) para evitar
  reidentificação — decisão da ADR-047/LGPD.
- Atualização diária (job), cache com `ETag`/304, `SitemapSource`; dados em tabela HTML + CSV
  agregado; sem gráfico obrigatório.
- Relatório público da Ouvidoria (dossiê) é esta página; sem PII.
- Testes: agregação, supressão, `ETag`, nenhuma PII, acessibilidade.

### S4 — Fechamento

- E2E: dataset fiscal (filtro/export/ETag), `/transparencia`, estatísticas públicas, import CSV.
- `make check` 2× + `E2E=1`; axe; cobertura ≥90%; query count (anti-N+1).
- Atualizar `INVENTARIO.md`, `modulo-transparencia-fiscal.md` e a decisão C18.

## 4. Fora de escopo

- Integração contábil externa (fonte oficial), ETL, conciliação automática.
- Portal de transparência **completo** (receita, despesa, convênios, contratos, planejamento,
  pessoal, diárias) — P22–P24 são os donos; P12 é a camada de dataset/export/estatística, não
  substitui os módulos.
- BI/warehouse, dashboards interativos, previsão.
- Dados pessoais em dataset público (nunca).

## 5. Fatias de sessão

| Sessão | Entrega | Prova | Depende |
|---|---|---|---|
| **P12.S1** | categorias/competência/filtros/export no `DadosAbertos` | categoria inativa fora; decimal string; ETag; query count | P9 |
| **P12.S2** | dataset fiscal + `/transparencia` por blocos | schema fiscal; curadoria; sitemap; axe | S1, P5 |
| **P12.S3** | agregações públicas (Ouvidoria/e-SIC/portal) | sem PII; supressão; ETag; a11y | S1, P11, P4 |
| **P12.S4** | import CSV fiscal + E2E + docs | dry-run; idempotência; 2× check | S2, P9 |

## 6. Contratos e dados

- **Módulo:** `Portal/DadosAbertos` (owner único da camada pública). `Portal/Transparencia`, se
  existir, é **view** (páginas/blocos), sem tabela de dados e sem serializador.
- **Tabelas:** `dados_abertos_categorias`, colunas novas no dataset; nenhuma duplicação de dados.
- **Rotas:** `dados-abertos.portal.*`, `transparencia.portal.*`, `api.datasets.*`.
- **Portas:** `SitemapSource`, `ImportTarget` (P9).
- **Permissões:** `dados-abertos.ver/editar/arquivar`, `transparencia.ver/editar`.
- **Eventos:** `dados_abertos.dataset_published`, `transparencia.page_updated`.

## 7. DoD

- [ ] `DadosAbertos` é o único owner da camada pública; nenhum módulo irmão duplica dataset/export.
- [ ] Categoria/competência/filtros/export com ordem determinística, checksum e `ETag`.
- [ ] Dinheiro como string decimal; nunca `float`; datas ISO.
- [ ] `/transparencia` por blocos (sem HTML livre), sitemap e a11y.
- [ ] Estatísticas públicas agregadas, sem PII, com supressão e cache.
- [ ] Carga CSV idempotente via importador; sem ETL.
- [ ] `make check` 2× + `E2E=1`; cobertura ≥90%; PHPStan max 0.
- [ ] PNTP 15.4/12.7: dataset legível por máquina, regras de uso, estatística agregada sem PII.
- [ ] P22–P24 são os donos dos dados fiscais; P12 não duplica página nem tabela.

## Fechamento — ficha de revisão

> **Obrigatório antes de fechar:** criar `_to_revision/P12-transparencia-dados.md` e seguir
> `_to_revision/README.md` + `_to_revision/PROTOCOLO.md` (v2.0). A ficha não é gate de build; é a
> entrada da fila de revisão profunda.

- Cabeçalho: fase, `kd` épico/tasks/slices, âncoras (este arquivo, ADRs e código) e status
  `⬜ pendente` → `🟡 em revisão` → `✅ revisado` / `🔧 com correções`.
- Conteúdo: o que foi implementado, arquivos/superfícies a revisar, checklist D1–D14 aplicável,
  riscos e observações.
- Fechamento: preencher “Notas da revisão” com data/revisor/resultado e achados (`kd write
  --anchor`), atualizar a fila em `_to_revision/README.md` e `_to_revision/_inventario.md`.
- Achado com correção exige teste vermelho→verde; a fase só é `closed` no `kd` com a ficha
  registrada.

## 8. Riscos

| Risco | Mitigação |
|---|---|
| Duplicar DadosAbertos | decisão C18: extensão primeiro; módulo só com recorte explícito |
| `float` em dinheiro | string decimal no JSON + validação; teste |
| PII em estatística pública | agregação + supressão + revisão LGPD; teste |
| Export não determinístico | ordem explícita + checksum + `ETag`; teste |
| Categoria inativa vazando | `active()` em todas as consultas; teste |
| Importador virar ETL | dry-run, operação manual, ADR-042 |

## 9. Retomada

```bash
kd prime
kd ask "dados abertos transparência fiscal export estatísticas públicas"
kd task list --ready
```

Ler: `src/modules/Portal/DadosAbertos/**` → `wiki/backlog/modulo-transparencia-fiscal.md` →
`lotep-v2/dadosabertos-transparenciafiscal/09-APROVEITAMENTO-V7.md` →
`dossie_modules/transparencia-fiscal/**` → `wiki/adr/ADR-018-dados-abertos.md` → P4/P11.
