mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-14 17:43:04 +00:00
Drop the NOT NULL constraint on allocation_decision.rationale to align the DB schema with the Payload config (required: false since B134). Hand-written idempotent migration following the consent_text_to_jsonb precedent. Adds idempotency test in campaignMigrationReconciliation. Closes #371
3.8 KiB
3.8 KiB
Impl: Reconciliar drift — allocation_decision.rationale NOT NULL vs config
Status: rascunho Atualizado em: 2026-08-24 Issue: #371 Intenção: docs/plans/reconciliar-rationale-alocacao.md Appetite restante: ~0,25 dia eng
Leitura da intenção
- Outcome: O campo
rationalena collectionallocationDecisiondeve ser nullable no banco de dados, alinhando o schema real com a config (required: false). O drift que fazpnpm migrate:createre-emitirALTER TABLE allocation_decision ALTER COLUMN rationale DROP NOT NULLdeve desaparecer. - O que NÃO negociar: A config
required: falsejá está correta (B134). O hookvalidateAllocationDecisionjá permiterationalevazio/null paraoutcome: 'movimento'. A mudança é apenas de schema. - O que reavaliar: Nenhuma hipótese incerta — o problema é um drift factual documentado.
Abordagem recomendada
flowchart LR
A[Migration idempotente] --> B[Test idempotência]
B --> C[Verificar drift zero]
Opções consideradas:
- A: Migration hand-written idempotente — seguir o padrão
consent_text_to_jsonb.ts: checkinformation_schema.columnsantes de alterar. Seguro, idempotente, testado. - B:
pnpm migrate:creategerado — deixar o Payload gerar a migration. Rejeitado: o Payload pode gerar um diff mais amplo (drop/recreate de colunas relacionadas) e não garante idempotência. - C: Editar a migration inicial — Rejeitado: viola o contrato de que migrations são história congelada.
Recomendação: Opção A — porque é o padrão estabelecido no repo, idempotente, e mínima.
Componentes / mudanças
- Migration:
src/migrations/<timestamp>_reconcile_allocation_decision_rationale_nullable.ts— hand-written, idempotent, segue padrãoconsent_text_to_jsonb.ts - Registro:
src/migrations/index.ts— adicionar entrada após a última migration existente - Teste:
tests/int/campaignMigrationReconciliation.int.spec.ts— adicionar caso que verifica idempotência (executar duas vezes, segunda é no-op) - Access / Consent: Nenhuma mudança — o hook
validateAllocationDecisionjá valida corretamente - UI: Nenhuma mudança
Dados → forma
N/A — mudança de schema apenas.
Fases verificáveis
- Migration — criar arquivo hand-written com guard
is_nullable = 'NO'+DROP NOT NULL; registrar emindex.ts; aplicar em dev e test - Teste — adicionar caso em
campaignMigrationReconciliation.int.spec.tsque:- Executa a migration duas vezes
- Verifica que a segunda execução é no-op (schema inalterado)
- Verifica que
rationaleé nullable após a migration
- Verificação de drift — rodar
pnpm migrate:create <probe>e confirmar que não re-emite mais o ALTER; deletar o probe - Gates —
pnpm gate:fast; push viapnpm push
Rabbit holes / Não escopo (engenharia)
- Não alterar o fluxo E14 (motivo opcional do wizard/lista) — escopo do #288
- Não tocar
snapshot/reversalSignals(vivem só no JSON do snapshot; sem migration) - Não alterar o hook
validateAllocationDecision— já está correto - Não criar migration gerada pelo Payload — hand-written é mais seguro para drift reconciliation
Riscos e mitigação
- Risco: Migration falha em DB onde
rationalejá é nullable (fresh local DB). Mitigação: guard idempotente verificais_nullableantes de alterar. - Risco: Prod tem
NOT NULLcom dados existentes. Mitigação:DROP NOT NULLé seguro — não altera dados, apenas relaxa a restrição.
Aceite de engenharia
- Aceite de produto da intenção ainda coberto (rationale nullable, drift zero)
- Invariantes AGENTS/engineering-standards (migration idempotente, padrão estabelecido)
- Testes de domínio previstos (int spec de idempotência da migration)