Ir para o conteúdo

Nota (PT-BR): este documento é uma referência normativa de engenharia e permanece temporariamente em inglês para preservar precisão técnica. A visão geral em português está em Decision Engine. A tradução completa está no backlog de documentação.

Backfill do ledger legado

Status: provisional. Migration: 20260821131000_brandvelia_decision_truth_legacy_backfill.sql.

Esta etapa copia brandvelia.transactions para brandvelia.performance_ledger_entries sem atualizar ou apagar a tabela legada. Ela nao troca as leituras da aplicacao, nao cria bridge publica e nao ativa views v2. O ledger resultante serve para reconciliacao e shadow comparison; nao autoriza cutover nem promove decisioning para advisory.

Identidade e replay

Cada linha usa:

  • source_system = LEGACY_TRANSACTION;
  • source_account_id = brandvelia.transactions;
  • source_event_id = transactions.id::text;
  • source_line_id = legacy-transaction/v1;
  • normalization_version = legacy-transaction/v1;
  • hash SHA-256 deterministico dos campos financeiros, dimensionais, FX e de proveniencia disponiveis na linha legada.

A identidade e verificada antes do insert e tambem pela unique key do ledger. brandvelia.backfill_legacy_transactions(workspace_id) usa advisory lock e ON CONFLICT DO NOTHING; uma segunda execucao limpa retorna inserted_count = 0.

Ao ser aplicada, a migration chama essa funcao uma vez com workspace nula para processar as linhas ja existentes em todas as workspaces. Linhas bloqueadas nao abortam o lote: permanecem visiveis no dry-run e como divergencia no report de paridade. Novas linhas legadas exigem replay service-side explicito.

Mapeamento financeiro

Somente os oito tipos admitidos pelo check atual de transactions.type sao tratados:

Tipo legado Tipo canonico Sinal
revenue, subtipo rebill ou recurring_commission REBILL positivo
demais revenue REVENUE positivo
refund com uma unica receita de mesmo external_ref REFUND negativo
chargeback com uma unica receita de mesmo external_ref CHARGEBACK negativo
refund/chargeback sem original inequivoco ADJUSTMENT + UNKNOWN negativo
fee FEE negativo
expense com subtipo ad_spend AD_SPEND negativo
demais expense OPEX negativo
payout PAYOUT positivo
fx FX + UNKNOWN positivo
adjustment ADJUSTMENT positivo

O fallback de reversao e necessario porque o ledger exige original_entry_id para REFUND e CHARGEBACK. Ele preserva a paridade financeira e o tipo legado no report, mas nao fabrica uma venda original.

amount, currency, tx_date e as dimensoes compativeis com o ledger sao preservados. Uma dimensao cross-workspace ou uma moeda que nao corresponda a ^[A-Z]{3}$ bloqueia somente a linha afetada e aparece no dry-run; ela nao e silenciosamente removida ou substituida.

Nulls, clocks, coorte e FX

O legado possui tx_date e created_at, mas nao separa event, observed e source ingestion clocks. O backfill usa meia-noite UTC de tx_date como event_at e greatest(created_at, event_at) como proxy de observed_at. Todas as linhas permanecem PROVISIONAL ou UNKNOWN e registram, no minimo:

  • LEGACY_EVENT_TIME_MISSING;
  • LEGACY_OBSERVED_AT_MISSING;
  • LEGACY_COHORT_MISSING;
  • reason codes independentes para as tres maturidades ausentes.

acquisition_cohort_id permanece nulo. Nenhuma coorte, clock de fonte ou maturidade e inferida.

Para moeda nativa USD, amount_usd recebe exatamente o signed amount porque nao existe conversao. Para qualquer outra moeda, inclusive quando colunas FX legadas estiverem preenchidas, amount_usd permanece nulo com NOT_RECONCILED. O backfill nao cria snapshot FX nem confia em taxa sem comprovante, settlement e reconciliacao.

Operacao service-only

As funcoes ficam no schema privado brandvelia, usam SECURITY DEFINER com search_path vazio e tem grants revogados de public, anon e authenticated. Somente service_role recebe EXECUTE nas tres funcoes operacionais; o helper de candidatos nao recebe grant direto.

Dry-run por workspace:

select *
from brandvelia.legacy_transaction_backfill_dry_run(
  '00000000-0000-0000-0000-000000000000'::uuid
);

Replay controlado:

select *
from brandvelia.backfill_legacy_transactions(
  '00000000-0000-0000-0000-000000000000'::uuid
);

Paridade diaria e mensal, sempre separada por workspace, tipo legado e moeda nativa:

select *
from brandvelia.legacy_transaction_parity_report(
  '00000000-0000-0000-0000-000000000000'::uuid,
  'DAY'
);

select *
from brandvelia.legacy_transaction_parity_report(
  '00000000-0000-0000-0000-000000000000'::uuid,
  'MONTH'
);

is_match exige igualdade de contagem e signed native amount, alem de moeda, data, dimensoes, economic type e source hash. Rows bloqueadas permanecem como divergencia ate correcao aprovada na origem; esta migration nunca as corrige na tabela transactions.