Files
Investidor-V2/docs/investmoz/education/migration-proposal.md
T
nala 250ac35fd1
tests / ci (push) Canceled after 0s
first commit
2026-09-28 10:01:09 +02:00

8.2 KiB
Raw Blame History

Proposta de migração Education

Actualização: o repositório já contém a migration de recepção interna 2026_09_26_100000_education_intake.php, ensaiada numa base temporária nesta revisão. Ver relatório actual. O inventário abaixo é histórico e não comprova o esquema nem as contagens da base actual da aplicação.

Estado: Proposta — Pendente de validação. Este ficheiro não é uma migration executável. Não criar SQL activo para B02/B03 antes da decisão de modelo/identidade e autorização. Diagnóstico local read-only em 26/09/2026: as seis tabelas da migration Education existem e têm zero registos. Isso não prova ausência de fontes externas.

Inventário e mapeamento

Origem confirmada Destino lógico Transformação proposta Rejeição/quarentena
skills.code/name Skill canónica Preservar UUID/código; sinónimos e versão em extensão Código ambíguo, taxonomia desconhecida
occupations.code/name Occupation Preservar UUID; relacionar Skills por versão Equivalência de nível sem prova
training_needs.quantity Registo legado de necessidade Manter o valor e a semântica original; só ligar a LabourDemand após revisão Nunca assumir que quantity significa trabalhadores
training_needs.project_id/occupation_id/skill_id Relações contextuais Manter FKs; verificar consistência da cadeia Órfão, projecto eliminado, fonte ausente
training_providers.organization_id/name/status Provider canónico Conservar candidate/approved/inactive Nenhuma conversão approved → acreditada
courses.provider_id/code/title/status Curso canónico Manter UUID e vínculo; separar revisão curricular Nenhuma conversão published → certificado
education_opportunities.course_id/datas/capacity Oferta calendarizada existente Preservar contrato actual Não reutilizar como projecto de construção de centro
Documentos/fontes externos não inventariados Área de recepção proposta Fonte, proprietário, autorização, checksum, versão, unidade e data Sem autorização não importar

Vagas técnicas propostas

Vaga Conteúdo lógico aditivo Pré-condição Reconciliação Reversão
M0 Snapshot do catálogo, colunas, FKs, índices, triggers, consumidores e permissões Inventário aprovado; backup base/documentos/configuração verificado Contagens, hashes por conteúdo normalizado e manifesto Nenhuma escrita
M1 Extensões de fonte, validade e versão de taxonomia; relações ocupação–competência e curso–competência Taxonomia/Shared confirmados 100% UUID preservados, zero órfãos; decisão de unicidade Desactivar leitores novos; conservar histórico
M2 LabourDemand e relações contextuais, sem renomear training_needs B02/B03 resolvidos Quantidades/unidades/períodos iguais à fonte aprovada; rejeições explicadas Parar escritores novos; não dropar dados
M3 Capacidade por período/pool e snapshots SkillGap Regras e fonte de disponibilidade aprovadas Contagem de pools/alocações; zero dupla contagem Reverter exposição e workers; snapshots preservados
M4 Identidade de investimento educativo e vínculo a Opportunity Decisão formal B02 Cada oportunidade tem promotor, lacuna/versão e fonte; sem duplicação comercial Despublicar e suspender encaminhamento
M5 Projecções de leitura, contratos e eventos Idempotência e mandatos testados Reconciliar outbox/inbox e consumidor; zero estados oficiais promovidos Feature flag desligada; drenar ou reter fila conforme plano

Nomes físicos novos, índices, rotas e policies são propostas, não factos confirmados. Antes de converter para Laravel migrations: revisar catálogo real completo e tipos, validar envelope, constraints e impacto nas queries/consumidores. Não acrescentar estado oficial a enum editorial. Preferir extensões opcionais inicialmente; backfill separado e validado antes de NOT NULL. A idempotência da criação estrutural usa o ledger de migrations; não esconder divergência com IF NOT EXISTS indiscriminado.

Pseudocódigo do importador, não executável

exigir fonte autorizada + versão do mapeamento aprovada + feature flag de ensaio
para cada lote:
  verificar checksum, unidades, datas, direitos e chaves externas
  normalizar apenas segundo taxonomia aprovada
  rejeitar ambíguos para quarentena com motivo e referência, sem PII em logs
  numa transacção:
    procurar por sistema_origem + id_externo + versão
    se versão igual e checksum igual: no-op
    se versão igual e conteúdo diferente: conflito, não sobrescrever
    se versão menor: rejeitar regressão
    se versão maior: preservar snapshot e aplicar decisão de precedência
    nunca copiar acreditação/certificação como confirmada sem decisão externa verificada
    escrever auditoria e recibo do lote
  emitir relatório de aceites/rejeitados/conflitos e totais por unidade/período
aprovar reconciliação antes de activar leitores públicos

Ensaio, backup e aceitação

Usar ambiente PostgreSQL/PostGIS isolado, primeiro dados sintéticos e depois cópia anonimizada autorizada. Zero dados pessoais reais em fixtures. Comparar antes/depois: contagens, somas por unidade e moeda, chaves, hashes normalizados, versões, relações, geometrias válidas, classificações e estados. Relatório inclui rejeições; não forçar sucesso descartando linhas silenciosamente.

Backup consistente com manifestos de base/documentos/configuração; cifrado, acesso restrito, restauro verificado em ambiente separado. Critérios propostos: zero perda não autorizada, zero órfãos, zero duplicados de chaves, zero estados oficiais promovidos, totais reconciliados para cada lote aceite; divergências pendentes impedem activação do lote. Responsáveis e limites financeiros de reconciliação permanecem por aprovação.

Rollback de aplicação começa pela flag, exposição e produtores/consumidores; não remove tabelas. Restauro físico só em incidente aprovado e depois de avaliar escritas posteriores ao backup. Eventos já entregues requerem compensação/reconciliação, não fingir que restaurar a base os desenvia. Remoções futuras exigem inventário, período de transição, aprovação e restauro ensaiado, numa entrega distinta.