# Grade nominal de e-mails CCS - design

Decisão do dono (19/07): transporte real fica para depois (SMTP vs SES em aberto); a grade nasce com transporte abstraído e fail-safe Logger, pronta para ligar.

## Evidência do estado atual (file:line)

- Notificador por EVENTO já existe: `core/backend/lib/monetarie/use_cases/ccs/notifications.ex` (7 eventos + digest; destinatários via env `CCS_NOTIFICATION_EMAILS` :252; fail-safe `Swoosh.Adapters.Logger` :24). Worker `workers/cadoc/ccs_email_notifier.ex`.
- Disparos: `:generated`/`:generation_failed` (`ccs_accs001_daily_job.ex:73/:100`), `:submitted` (`sta_submission.ex:84`), `:accs002_verdict` (`sta_inbound.ex:130`), `:accs003_received` (:674), `:accs009_received` (:692), `:daily_digest` (`ccs_daily_digest_worker.ex:32`).
- Crons existentes: ACCS001 01:00 BRT, poller 5min, digest 09:30 BRT (`runtime.exs:649-657`). Grade nova se registra nesses crontabs.

## Grade nominal do cliente vs estado

| Horário BRT | Item da grade | Estado |
|---|---|---|
| 09:00 | ACCS003 (validação linha a linha) | evento existe (reativo); virar resumo AGENDADO das ocorrências do dia anterior |
| 09:21 | ACCS009 (ocorrências) | idem |
| 10:00 | abertura/fechamento do sistema CCS | NÃO existe evento; criar (fonte: grade oficial 20h-08h provada em 16/07 + estado do ciclo) |
| 10:20 | CC importado | NÃO existe; criar (fonte: ingestão de arquivos CCS materializados) |
| 10:40 | consolidação clientes/procuradores | NÃO existe; criar (fonte: contadores do cadastro do dia no ccs.ex) |
| 11:00 | geração | evento `:generated` existe (01:00); e-mail nominal às 11:00 re-reporta o resultado do dia |
| 20:10 | envio | evento `:submitted` existe; e-mail nominal confirma o envio dentro da grade 20h+ |
| 20:42 | baixa (veredito ACCS002) | evento `:accs002_verdict` existe; e-mail nominal reporta o veredito |

## Desenho

1. **`CcsScheduleNotifier`** (worker Oban único, cron por horário nominal nos crontabs existentes): a cada slot, monta o e-mail NOMINAL daquele item consultando o estado real (submissões, vereditos, ocorrências, cadastro) e envia via `Notifications` existente. Reaproveita template/recipients; zero duplicação de transporte.
2. **Eventos novos** em `Notifications`: `:ccs_system_window` (abertura/fechamento), `:cc_imported`, `:consolidation` - cada um com a consulta de estado correspondente (não inventar dado: se não houver movimento, o e-mail diz explicitamente "sem movimento").
3. **Idempotência**: tabela leve `ccs_schedule_notifications (slot, date, sent_at)` unique por (slot, date) - retry do cron não duplica e-mail.
4. **Transporte**: continua atrás do adapter Swoosh; quando o dono decidir SMTP/SES, muda só o adapter + secrets (zero mudança na grade). Destinatários seguem `CCS_NOTIFICATION_EMAILS` até o dono definir a lista nominal.
5. Config de horários por env (`CCS_SCHEDULE_*`) com defaults da grade do cliente, para ajuste sem deploy.

## Testes (TDD)

Cada slot com estado real e com estado vazio; idempotência por (slot, date); fuso BRT nos crons (converter para UTC no crontab como os existentes); fail-safe sem SMTP. Validação viva: rodar um dia de grade em HML com inbox de teste antes de ligar transporte real.
