Skip to content

feat: add summary moderation schema (migration 013)#189

Open
ODenteAzul wants to merge 1 commit into
mainfrom
feat/add-summary-moderation-schema
Open

feat: add summary moderation schema (migration 013)#189
ODenteAzul wants to merge 1 commit into
mainfrom
feat/add-summary-moderation-schema

Conversation

@ODenteAzul

Copy link
Copy Markdown

PR 2: data-platform (database schema)

Título

feat: add summary moderation schema (migration 013)

Body

Summary

Adiciona campos na tabela news para tracking de moderação de resumos gerados por LLM, suportando os guardrails de segurança implementados no data-science.

Changes

Migration 013: Summary Moderation Fields

ALTER TABLE news
  ADD COLUMN IF NOT EXISTS summary_blocked BOOLEAN DEFAULT FALSE,
  ADD COLUMN IF NOT EXISTS summary_blocked_reason TEXT,
  ADD COLUMN IF NOT EXISTS summary_blocked_at TIMESTAMP;

Campos:

  • summary_blocked: Flag indicando se resumo foi bloqueado (TRUE = bloqueado, FALSE = aprovado)
  • summary_blocked_reason: Motivo do bloqueio (ex: "regex: CPF detectado", "llm: linguagem ofensiva")
  • summary_blocked_at: Timestamp de quando foi bloqueado

Índices para Performance

-- Índice parcial (só registros bloqueados)
CREATE INDEX IF NOT EXISTS idx_news_summary_blocked
  ON news (summary_blocked)
  WHERE summary_blocked = TRUE;

-- Índice para ordenação por data
CREATE INDEX IF NOT EXISTS idx_news_summary_blocked_at
  ON news (summary_blocked_at DESC)
  WHERE summary_blocked = TRUE;

Benefícios:

  • Queries rápidas para "listar bloqueados" (usa índice parcial)
  • Ordenação eficiente por data de bloqueio
  • Índices pequenos (só bloqueados, esperado < 1% dos registros)

Views de Auditoria

1. news_moderation_log - Log completo de bloqueios

CREATE VIEW news_moderation_log AS
SELECT
  unique_id, title, summary_blocked_reason,
  summary_blocked_at, agency_name, category,
  EXTRACT(EPOCH FROM (summary_blocked_at - created_at)) / 60 AS minutes_to_block
FROM news
WHERE summary_blocked = TRUE
ORDER BY summary_blocked_at DESC;

Uso: Auditoria e investigação de bloqueios individuais

2. news_moderation_stats - Estatísticas diárias

CREATE VIEW news_moderation_stats AS
SELECT
  DATE(summary_blocked_at) AS date,
  COUNT(*) AS total_blocked,
  COUNT(DISTINCT agency_key) AS affected_agencies,
  ARRAY_AGG(DISTINCT SUBSTRING(summary_blocked_reason, 1, 50)) AS unique_reasons
FROM news
WHERE summary_blocked = TRUE
  AND summary_blocked_at >= CURRENT_DATE - INTERVAL '30 days'
GROUP BY DATE(summary_blocked_at)
ORDER BY date DESC;

Uso: Dashboard de moderação (taxa de bloqueio ao longo do tempo)

Rollback Incluído

Arquivo 013_add_summary_moderation_ROLLBACK.sql para reverter se necessário:

  • Remove views
  • Remove índices
  • Remove colunas (dados serão perdidos!)

Use Cases

1. Auditar bloqueios recentes

SELECT * FROM news_moderation_log
LIMIT 100;

2. Taxa de bloqueio por dia

SELECT date, total_blocked FROM news_moderation_stats;

3. Distribuição de motivos de bloqueio

SELECT 
  summary_blocked_reason,
  COUNT(*) as count
FROM news
WHERE summary_blocked = TRUE
GROUP BY summary_blocked_reason
ORDER BY count DESC;

4. Notícias bloqueadas de uma agência específica

SELECT * FROM news_moderation_log
WHERE agency_name = 'aneel'
ORDER BY summary_blocked_at DESC;

Migration Safety

Backward compatible:

  • IF NOT EXISTS evita erro se colunas já existirem
  • DEFAULT FALSE não afeta registros existentes
  • Novos campos são NULL ou FALSE por padrão (sem impacto)

No downtime:

  • ADD COLUMN é operação rápida (não reescreve tabela)
  • Índices parciais são pequenos (< 1% dos registros)
  • Views não impactam performance de writes

Rollback seguro:

  • Script de rollback incluído
  • Pode reverter a qualquer momento (dados de bloqueio serão perdidos)

Testing

  • Migration testada localmente em PostgreSQL 15
  • Rollback testado (revert + reapply funcionando)
  • Views retornam resultados corretos
  • Índices sendo usados (verificado com EXPLAIN)

Expected Impact

  • Taxa de bloqueio: < 1% dos resumos (notícias gov.br são confiáveis)
  • Storage overhead: ~20 bytes por registro (3 campos: bool + text + timestamp)
    • Para 500k notícias: ~10 MB adicional
  • Query performance: Sem impacto (índices parciais são pequenos)

Related Issues & PRs

How to Apply

Staging:

psql -h <staging-db> -U <user> -d <database> -f scripts/migrations/013_add_summary_moderation.sql

Production:

# Via workflow manual dispatch
gh workflow run db-migrate.yaml --field migration=013

Rollback (se necessário):

psql -h <db> -U <user> -d <database> -f scripts/migrations/013_add_summary_moderation_ROLLBACK.sql

Generated with Claude Code (https://claude.com/claude-code)

Add PostgreSQL schema for content safety guardrails tracking:
- summary_blocked (BOOLEAN): flag de bloqueio
- summary_blocked_reason (TEXT): razão do bloqueio
- summary_blocked_at (TIMESTAMP): quando foi bloqueado

Inclui:
- Índices otimizados para queries de auditoria
- View news_moderation_log: log de bloqueios
- View news_moderation_stats: estatísticas diárias
- Script de ROLLBACK para reverter se necessário

Issue: #187 (sub-issue de #176)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@ODenteAzul ODenteAzul requested a review from miguellsfilho June 23, 2026 18:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant