| name | nova-migracao |
| description | Escreve uma migração SQL versionada, progressiva e reversível, com o cuidado redobrado que o banco PostgreSQL exige em produção. Use ao adicionar tabela, evoluir schema, criar política RLS, ou semear dado de taxonomia. |
Procedimento
- Nome do arquivo:
db/migracoes/<NNNN>_<dominio>_<descricao_curta>.sql — ex.: 0042_execucao_add_prestacao_conta.sql. O número é sequencial, sem buracos.
- Cabeçalho com metadado:
- Seção
-- UP: as instruções aplicadas.
- Seção
-- DOWN: a reversão correspondente. Quando irreversível (drop de coluna com dado, eliminação física), marcar Reversivel: nao e exigir aprovação humana explícita.
- Progressividade: mudança incompatível sempre em passos compatíveis:
- Migração N: adiciona coluna nova (nullable).
- Migração N+1: backfill do dado.
- Migração N+2: torna NOT NULL.
- Migração N+3 (futuro): remove coluna antiga.
Nunca uma única migração que quebra a versão anterior em execução.
- Índices em tabela grande:
CREATE INDEX CONCURRENTLY (fora de transação) — incluir nota no cabeçalho que a migração roda fora do bloco transacional padrão.
- Seeds de taxonomia: usar
INSERT ... ON CONFLICT DO NOTHING para idempotência (a migração pode ser reaplicada em homologação).
- Verificar contra homologação via conector
postgres-hml antes de propor merge: a migração roda? produz o estado esperado? a RLS efetivamente filtra?
- Cobertura de teste: incremento que toca migração inclui teste de integração que confirma o estado pós-migração.
Modelo de referência
BEGIN;
CREATE TABLE execucao.prestacao_conta (
id bigserial PRIMARY KEY,
uuid uuid NOT NULL DEFAULT gen_random_uuid() UNIQUE,
ator_id bigint NOT NULL REFERENCES atores.ator(id),
microrregiao_id bigint NOT NULL REFERENCES territorio.microrregiao(id),
periodo text NOT NULL,
valor_total numeric(14,2) NOT NULL,
status text NOT NULL,
criado_em timestamptz NOT NULL DEFAULT now(),
atualizado_em timestamptz NOT NULL DEFAULT now(),
excluido_em timestamptz NULL,
CHECK (valor_total >= 0)
);
CREATE INDEX prestacao_conta_microrregiao_idx ON execucao.prestacao_conta(microrregiao_id);
CREATE INDEX prestacao_conta_ator_idx ON execucao.prestacao_conta(ator_id);
ALTER TABLE execucao.prestacao_conta ENABLE ROW LEVEL SECURITY;
CREATE POLICY prestacao_conta_por_territorio ON execucao.prestacao_conta
USING (
microrregiao_id IN (
SELECT microrregiao_id FROM acesso.escopo_territorial
WHERE identidade_id = corrente_identidade()
)
OR corrente_tem_papel('coordenacao_geral')
OR corrente_tem_papel('administracao_sistema')
);
COMMIT;
BEGIN;
DROP TABLE IF EXISTS execucao.prestacao_conta;
COMMIT;
Risco e cuidado
Migração é o ponto mais perigoso da Parte V. Código com defeito é revertido; migração que destrói ou corrompe dado pode ser irreversível. Por isso:
- Toda migração passa por revisão humana reforçada.
- Roda primeiro em homologação sobre dado representativo.
- Nunca é promovida sem backup verificado quando a flag
Requer backup é sim.
- O pipeline rejeita migração sem
-- DOWN (exceto quando explicitamente marcada como irreversível com aprovação registrada).
Saída
Arquivo db/migracoes/NNNN_*.sql com cabeçalho, UP, DOWN, e — quando aplicável — política RLS e índices. Atualização do catálogo se introduz tabela nova. Nota de decisão se a migração é irreversível.