# P18 — Câmara municipal (perfil de produto)

| Campo | Valor |
|---|---|
| Programa | F7+ — operação, estrutura e conteúdo |
| Status | `planejado` (condicionado a produto/contrato; **D11: implantação posterior**) |
| Depende de | P14, P15, P17 |
| Habilita | P19 (agenda/transmissões compartilhadas) |
| Tamanho | **G** (4–6 sessões) |
| ADRs | ADR-001/002/009/010, ADR-017/019, ADR-026/027, ADR-033/035, ADR-043 |

## 1. Objetivo

Implementar o **perfil Câmara** — sessões, pauta, vereadores/mandatos, requerimentos, atas,
pontos de frequência e vídeos — para clientes cuja estrutura é legislativa. O V7 é um CMS
municipal; este perfil só entra com decisão de produto (`structure_type=camara`) e contrato.
**D11:** a implantação fica posterior; o desenho A (perfil + grupo ativável) é mantido. Se o
escopo se mostrar simples, tratar como backlog; se complexo, executar A quando o gate abrir.

**Resultado observável:** o cidadão consulta a sessão, a pauta, os vereadores, os requerimentos e a
ata; o vídeo é um **link** externo (sem embed de terceiro); o CMS mantém tudo com permissões e
auditoria; o portal executivo continua funcionando com os módulos desativados.

## 2. Gate de produto (não começar sem)

- `structure_type=camara` (config/settings) **ou** contrato explícito; sem isso, a fase fica
  `PODE` e não inicia.
- Nenhum módulo do perfil pode ser necessário para o portal executivo; ativação por ADR-034
  (`modules_activation`) permite desligar o grupo inteiro.
- Grupo de módulos `Camara` (ou `Legislativo`) no manifesto; navegação e permissões separadas.
- Se o cliente for câmara, os módulos executivos (Obras, Licitações, etc.) permanecem disponíveis
  por ativação, mas o menu deve refletir o perfil.

## 3. Escopo fechado

### S1 — Sessões + Pauta do Dia

- Módulo `Legislativo/Sessoes` (token `sessoes`), grupo `Legislativo`.
- `sessoes`: `id`, `numero`, `ano`, `tipo` enum (`ordinaria|extraordinaria|especial|solene`),
  `data_hora`, `titulo` jsonb, `resumo` (AST), `status` enum (`agendada|realizada|cancelada`),
  `video_url` (link externo validado) nullable, `metadata` jsonb, timestamps;
  `UNIQUE (numero, ano, tipo)`.
- `sessao_anexos`: `media_id`, `titulo` jsonb, `tipo` enum (`edital|pauta|ata|outro`), `position`.
- Módulo `Legislativo/Pauta` (token `pauta`):
  - `pauta_itens`: `id`, `sessao_id` FK cascade, `ordem`, `titulo` jsonb, `descricao` AST,
    `tipo` enum (`projeto|requerimento|indicacao|outro`), `status` enum
    (`pendente|aprovado|rejeitado|retirado`), timestamps; `UNIQUE (sessao_id, ordem)`.
- Portal `/sessoes` (lista por ano/tipo) e detalhe com pauta; CMS CRUD/publicar; sitemap/busca.
- Regras: pauta só existe vinculada a sessão; reordenar renumerando; sessão realizada não apaga
  pauta; link de vídeo é `https` externo, sem iframe.

### S2 — Vereadores e Mandatos

- Módulo `Legislativo/Vereadores` (token `vereadores`).
- `vereadores`: `id`, `slug` único, `nome`, `nome_parlamentar`, `partido`, `photo_media_id`,
  `biografia` (AST), `email` (institucional), `telefone` (institucional), `active`, timestamps.
- `mandatos`: `id`, `vereador_id` FK cascade, `legislatura`, `inicio`, `fim`, `cargo` enum
  (`vereador|presidente|vice_presidente|secretario|outro`), `active`; `UNIQUE
  (vereador_id, legislatura, inicio)`.
- Portal `/vereadores` e detalhe com mandatos; CMS CRUD; sitemap/busca.
- Regras: sem CPF/endereço/dados pessoais; partido é texto curto; foto via Media; mandato não
  apaga histórico; 4 locales.

### S3 — Requerimentos + Atas/Pontos de Frequência

- `Legislativo/Requerimentos` (token `requerimentos`):
  - `requerimentos`: `id`, `numero`, `ano`, `autor_id` FK vereador, `assunto` (AST), `data`,
    `status` enum (`apresentado|aprovado|rejeitado|arquivado`), `anexo_media_id` nullable, timestamps;
    `UNIQUE (numero, ano)`.
  - Portal lista/detalhe/filtros; CMS CRUD; sitemap/busca.
- `Legislativo/Atas` (token `atas`):
  - `atas`: `id`, `sessao_id` FK, `titulo` jsonb, `data`, `resumo` (AST), `media_id` (PDF),
    `publicada_em`, timestamps; `UNIQUE (sessao_id)`.
  - `pontos_frequencia`: `id`, `sessao_id`, `vereador_id`, `presenca` enum
    (`presente|ausente|justificado`), `justificativa` text null; `UNIQUE (sessao_id, vereador_id)`.
  - Portal ata + tabela de presença; CMS CRUD; sitemap/busca (ata).
- Regras: ata publicada imutável (correção = errata); presença só para sessão realizada; sem dados
  de saúde na justificativa.

### S4 — Transmissões e TV Câmara (link, sem embed)

- `Legislativo/Transmissoes` (token `transmissoes`):
  - `transmissoes`: `id`, `titulo` jsonb, `data_hora`, `live_url` (https validado), `status`
    enum (`agendada|ao_vivo|encerrada`), `sessao_id` nullable, timestamps.
  - Portal mostra “assistir” como link externo (`rel="noopener noreferrer"`), sem iframe; quando
    encerrada, link para gravação se houver.
- `Legislativo/TvCamara` (token `tv_camara`):
  - `tv_videos`: `id`, `titulo` jsonb, `descricao` (AST), `url` (https), `thumbnail_media_id`
    (Media local), `data`, `categoria`, `active`, timestamps.
  - Portal lista/detalhe com link; thumbnail local; **sem** hotlink de YouTube; sem player embutido.
- Regra dura: embed de YouTube/Vimeo é requisição de terceiro e a allowlist do ADR-002 não o
  permite. Se o cliente exigir player embutido, **parar e abrir ADR** (nova allowlist/CSP).
- 4 locales; axe; teclado.

### S5 — Integração e fechamento

- Cross-links: sessão ↔ pauta ↔ ata ↔ transmissão; vereador ↔ requerimentos/presença; VIAP (P17)
  no perfil Câmara.
- Cada módulo público registra `SitemapSource`/`SearchSource`.
- Ativação do grupo `Legislativo` por ADR-034; portal executivo não quebra com o grupo desligado.
- E2E: sessão/pauta/ata/presença; vereador/requerimento; transmissão/vídeo como link; busca; 4 locales.
- `make check` 2× + `E2E=1`; cobertura ≥90%; PHPStan max 0.

## 4. Fora de escopo

- **PNTP 20.3/20.5/20.7/20.8/20.10/20.11** (proposições/tramitação, comissões, votações nominais,
  contas do Executivo, cotas/verba e atividades) são **P28**. P18 entrega 20.1, 20.4, 20.6 e 20.9.
- Player embutido de YouTube/Vimeo (exige ADR/allowlist).
- Processo legislativo **em tempo real**; P28 cobre tramitação, comissões e votação nominal de forma assíncrona, sem apuração ao vivo.
- Assinatura digital de atas/leis (P13).
- Multi-tenant/regional (P20/NÃO).
- Portal executivo e portal legislativo no mesmo menu sem perfil definido.

## 5. Fatias de sessão

| Sessão | Entrega | Prova | Depende |
|---|---|---|---|
| **P18.S1** | gate + Sessões + Pauta | unique número/ano/tipo; pauta vinculada; link de vídeo | P14/P15 |
| **P18.S2** | Vereadores + Mandatos | histórico; sem PII; foto Media | S1 |
| **P18.S3** | Requerimentos + Atas/Presença | unique; ata imutável; presença só realizada | S2 |
| **P18.S4** | Transmissões + TV Câmara | link externo; thumbnail local; sem embed | S3 |
| **P18.S5** | integração + E2E + docs | grupo ativável; 4 locales; axe; 2× check | S1–S4 |

## 6. DoD

- [ ] Gate `structure_type=camara`/contrato registrado; grupo ativável/desativável.
- [ ] Sessão/pauta/ata/presença coerentes; unique e imutabilidade.
- [ ] Vereador/mandato/requerimento sem PII desnecessária.
- [ ] Vídeo apenas por link; nenhum iframe/asset de terceiro; thumbnail local.
- [ ] Busca/sitemap/4 locales/axe; `make check` 2× + `E2E=1`; cobertura ≥90%.
- [ ] PNTP 20.1: foto/partido/biografia; 20.4: pauta; 20.6: ata + presença; 20.9: transmissão.
- [ ] PNTP 20.3/20.5/20.7/20.8/20.10/20.11: completados em P28 (link, não duplicar).

## Fechamento — ficha de revisão

> **Obrigatório antes de fechar:** criar `_to_revision/P18-camara.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.

## 7. Riscos

| Risco | Mitigação |
|---|---|
| Perfil Câmara contaminar o executivo | gate de produto + grupo ativável + testes de menu |
| Embed de YouTube violar ADR-002 | link only; nova ADR se o cliente exigir player |
| Presença/ata inconsistente | FK/unique; validação de sessão realizada |
| Dados de vereador sensíveis | allowlist; sem CPF/endereço |
| N+1 em sessão/pauta/presença | eager loading/`whereIn`; teste de query count |
| Histórico apagado | ata imutável; mandato/requerimento com soft archive, não delete |

## 8. Retomada

```bash
kd prime
kd ask "câmara sessões pauta vereadores requerimentos atas transmissões tv"
kd task list --ready
```

Ler: `dossie_modules/{sessoes,pauta-do-dia,vereadores,requerimentos,atas-e-pontos-de-frequencia,transmissoes,tv-camara}/**`
→ `MODULOS.md` §1/P18 → P14/P15/P17 → ADR-002/043.
