Implementation Checklist — SafeStreets v0.1.0+
Referência de tudo que foi refinado na documentação e precisa ser implementado/validado no código
✅ Documentação Concluída (não requer mudança de código)
Core Documentation
- [x] CONTEXT.md — Glossário de domínio refinado com 19 termos
- [x] definir-fluxo-de-dados.md — Pipeline ETL detalhado com resilience patterns
- [x] API-Contract.md — Especificação de JSON request/response
- [x] requisitos.md — Requisitos alinhados com terminologia
- [x] definições-de-back.md — Stack backend com referências cruzadas
- [x] definicoes-front-end.md — Stack frontend com mapeamento Ocorrência→Notícia
Architecture Decisions
- [x] ADR-001-Gemini-Fallback-Strategy.md — 4 opções de fallback
- [x] ADRs-PENDENTES.md — Sumário de 4 ADRs requerendo consenso
⏳ Decisões Arquiteturais (Requer Team Consensus)
ADR-001: Gemini Fallback Strategy
Status: ⏳ Pendente
Questão: Como backend reage quando Google Gemini falha?
Opções Recomendadas:
- [ ] Opção A: Retorna card sem resumo (vazio)
- [ ] Opção B: Enfileira retry assíncrono
- [ ] Opção C: Usa resumo genérico padrão
- [x] Opção D: Circuit breaker + fallback híbrido ← RECOMENDADA
Ação: Team decision → Atualizar ADR-001 com decisão
ADR-002: Cache TTL Strategy
Status: ⏳ Pendente
Questão: Por quanto tempo dados devem ser válidos?
Opções: - [ ] A: TTL fixo 24h para todos - [ ] B: TTL variável por tipo de crime - [ ] C: TTL baseado em frequência de API - [ ] D: TTL adaptativo por trending
Ação: Team decision → Implementar em backend (historico_consultas.ttl_expiracao)
ADR-003: Redis Necessity
Status: ⏳ Pendente
Questão: Redis é obrigatório ou opcional?
Opções: - [ ] A: Obrigatório (distributed cache) - [ ] B: Opcional (in-memory only) - [ ] C: Estratificado (prod=Redis, dev=in-memory)
Ação: Team decision → Atualizar docker-compose.yml
ADR-004: Schema Versioning
Status: ⏳ Pendente
Questão: Responder a mudanças na estrutura XML do feed RSS do Correio Braziliense?
Opções: - [ ] A: Backward compat automática (Pydantic default) - [ ] B: Migration manual (fail-fast) - [ ] C: Versioning de endpoints (/v1 vs /v2)
Ação: Team decision → Implementar em models.py
🔴 Código: Deve Implementar/Validar
backend/app/models.py
Atual:
class Ocorrencia(Base):
__tablename__ = "ocorrencias"
id = Column(Integer, primary_key=True)
titulo_noticia = Column(String)
latitude = Column(Float)
longitude = Column(Float)
Deve ter:
- [x] Tabela: ocorrencias_criminais (conforme API-Contract.md)
- [ ] Campo: locais_pin_id (foreign key)
- [ ] Campo: tipo_crime (string, indexed)
- [ ] Campo: data_ocorrencia (datetime)
- [ ] Campo: descricao_detalhada (nullable)
- [ ] Campo: resumo_gemini (nullable)
- [ ] Campo: resumo_status enum("COMPLETO"|"PENDENTE"|"ERRO"|"FALLBACK_GENERICO")
- [ ] Campo: regiao_administrativa (RA code)
- [ ] Campo: criado_em (datetime default now)
- [ ] Campo: atualizado_em (datetime default now)
- [ ] Índice espacial: GiST em (latitude, longitude)
- [ ] Índice: em (regiao_administrativa, data_ocorrencia) para queries por filtro
Referência: API-Contract.md#1-modelo-de-dados-ocorrência
backend/app/services.py (Novo/Expandido)
Deve ter:
ServiçoGemini
- [ ]
sumarizar(texto: str) → str | Nonecom retry exponencial - [ ] Circuit breaker (abrir após 5 falhas)
- [ ] Timeout 30s
- [ ] Fallback: resumo genérico se falhar
- [ ] Log de tentativas (para monitoring)
Referência: ADR-001
ServiçoIngestão
- [ ] Rate limiter para feed RSS (Correio Braziliense)
- [ ] Retry exponencial: 1s → 2s → 4s → 8s
- [ ] Circuit breaker (abrir após 5 falhas)
- [ ] Parser XML/RSS (feedparser library)
- [ ] Extração de título, descrição, link, data, guid
- [ ] Tratamento de feeds malformados
- [ ] Extração de Localização (NLP ou regex)
- [ ] Mapeamento de nomes de RA → lat/long
- [ ] Fallback: geocodificação ou centroide do DF
- [ ] Classificação de Crime (keyword matching)
- [ ] Regex por tipo (roubo, homicídio, etc.)
- [ ] Fallback: "outro"
- [ ] Validação Pydantic (entrada)
- [ ] Transformação para ORM Ocorrencia
- [ ] Deduplicação por
id_externo_rss - [ ] Persistência dupla (PostgreSQL + Redis)
Referência: definir-fluxo-de-dados.md
backend/app/routers/ocorrencias.py (Novo)
Endpoints:
GET /ocorrencias
- [x] Query params: regiao, data_inicio, data_fim, limit, offset
- [ ] Response: 200 com paginação (conforme API-Contract.md)
- [ ] Response: 400 se data_inicio > data_fim
- [ ] Response: 429 se rate limit excedido
- [ ] Response: 503 se feed RSS indisponível
Referência: API-Contract.md#2-request-get-ocorrências-com-filtros
GET /ocorrencias/{id}
- [ ] Response: Ocorrência com resumo (ou status PENDENTE/FALLBACK)
- [ ] Consultar cache antes de BD
- [ ] TTL aplicado conforme ADR-002
Referência: API-Contract.md#3-endpoint-card-resumo
frontend/types/Noticia.ts
Deve ter:
interface Noticia {
id: string;
titulo: string;
descricao: string;
tipo_crime: string;
data: Date;
localizacao: {
latitude: number;
longitude: number;
endereco: string;
regiao: string;
};
resumo_ia: string | null;
status_resumo: "completo" | "pendente" | "erro" | "fallback_generico";
// ...
}
Referência: API-Contract.md#estrutura-no-frontend-typescript
frontend/hooks/useOcorrencias.ts (Novo)
Deve fazer:
- [ ] Fetch GET /ocorrencias com filtros
- [ ] Polling se resumo_ia === null && status_resumo === "PENDENTE" (máx 5 vezes)
- [ ] Mapeamento Ocorrência → Noticia
- [ ] Tratamento de erro 503 (mostrar fallback message)
Referência: API-Contract.md#cenário-1-gemini-indisponível-circuit-breaker-aberto
database.py (Validação)
Deve ter: - [x] Conexão PostgreSQL - [ ] Pool de conexões configurado - [ ] Suporte a GiST index (PostGIS? ou índice simples?)
Referência: CONTEXT.md#cache-espacial
Testes (Pytest)
Casos que devem passar:
test_ocorrencia_model.py
- [ ] Criar Ocorrencia com campos obrigatórios
- [ ] Validar latitude ∈ [-90, 90]
- [ ] Validar longitude ∈ [-180, 180]
- [ ] Validar precisão: 6 casas decimais (~0.11m)
test_gemini_fallback.py
- [ ] Mock Gemini timeout → volta com status "PENDENTE"
- [ ] Mock Gemini erro → volta com status "FALLBACK_GENERICO"
- [ ] Mock Gemini success → volta com status "COMPLETO"
- [ ] Verificar circuit breaker abre após 5 falhas
test_api_resilience.py
- [ ] Mock feed RSS timeout → retry 1s → 2s → 4s
- [ ] Mock feed RSS indisponível > 5min → circuit breaker abre
- [ ] Mock postgres indisponível → falha gracefully
- [ ] Testar parser RSS com feeds malformados
test_rss_processing.py (NOVO)
- [ ] Parse XML válido → extração correta de campos
- [ ] Extração de RA: "Taguatinga" → RA-026
- [ ] Classificação de crime: "homicídio" → "homicídio"
- [ ] Deduplicação: mesmo
id_externo_rssnão duplica - [ ] Geocodificação fallback: sem RA → centroide DF
test_api_contract.py
- [ ] GET /ocorrencias retorna schema conforme API-Contract.md
- [ ] GET /ocorrencias?regiao=RA-XXX retorna apenas aquela região
- [ ] GET /ocorrencias?data_inicio > data_fim retorna 400
📋 Documentação: Falta Completar
README.md (Top-Level)
- [ ] Adicionar link para CONTEXT.md
- [ ] Adicionar instrução: "Leia CONTEXT.md primeiro para entender termos"
docs/README.md (Arquitetura)
- [ ] Criar índice com links para:
- CONTEXT.md
- API-Contract.md
- definir-fluxo-de-dados.md
- ADRs-PENDENTES.md
backend/README.md
- [ ] Setup local (docker-compose up)
- [ ] Pytest:
pytest tests/ - [ ] Swagger: http://localhost:8000/docs
frontend/README.md
- [ ] Setup local (npm install)
- [ ] Dev server:
npm run dev - [ ] Referência ao API-Contract.md
🚀 Ordem de Prioridade
Phase 1: Team Alignment (Now)
- ⏳ Resolver ADR-001 (Gemini fallback)
- ⏳ Resolver ADR-002 (Cache TTL)
- ⏳ Resolver ADR-003 (Redis)
- ⏳ Resolver ADR-004 (Schema versioning)
Phase 2: Backend Implementation
- ✏️ Atualizar
models.pyconforme modelo refinado - ✏️ Implementar
services.pycom resilience - ✏️ Criar
routers/ocorrencias.pycom endpoints - ✏️ Adicionar testes Pytest
- ✏️ Validar Swagger docs
Phase 3: Frontend Implementation
- ✏️ Criar
types/Noticia.tscom mapeamento - ✏️ Implementar
hooks/useOcorrencias.ts - ✏️ Testar polling de resumo PENDENTE
- ✏️ Testar tratamento de erro 503
Phase 4: Integration & Deployment
- ✏️ E2E tests (cypress)
- ✏️ Validar cache TTL conforme ADR-002
- ✏️ Validar circuit breaker em carga
- ✏️ Deploy staging
📚 Referências Rápidas
| Documento | Propósito | Link |
|---|---|---|
| CONTEXT.md | Glossário de termos | docs/Arquitetura/CONTEXT.md |
| API-Contract.md | Estrutura de JSON | docs/Arquitetura/API-Contract.md |
| RSS-Integration.md | Parser RSS + Extração de Dados | docs/Arquitetura/RSS-Integration.md |
| definir-fluxo-de-dados.md | Pipeline e resilience | docs/Arquitetura/definir-fluxo-de-dados.md |
| ADRs-PENDENTES.md | Decisões a fazer | docs/Arquitetura/ADRs-PENDENTES.md |
| ADR-001 | Gemini Fallback | docs/Arquitetura/ADR-001-Gemini-Fallback-Strategy.md |
| requisitos.md | User stories | docs/Requisitos/requisitos.md |
Mantido por: Grill-with-Docs Analysis
Data da última atualização: 2026-06-06
Próxima revisão: Após resolução dos 4 ADRs