57 lines
6.3 KiB
Markdown
57 lines
6.3 KiB
Markdown
# Ponte de compatibilidade — 29/09/2026
|
||
|
||
Actualização: [reexecução dos anexos D/E](annex-de-execution.md), com migration 005 aplicada, dry-run, saída estrita de reconciliação e testes de privilégios numa conta isolada não-superuser. As limitações de activação abaixo mantêm-se.
|
||
|
||
## Estado da entrega
|
||
|
||
Incremento aplicado e testado localmente. **O anexo D ainda não está integralmente concluído.** `public` continua como autoridade de leitura e escrita dos formulários. Não há escrita dupla, migração de negócios, publicação nem activação de leitura canónica.
|
||
|
||
## Inventário confirmado
|
||
|
||
`public.users.id` e `public.sectors.id` são bigint; `public.existing_businesses.id`, `mne.parties.id` e `mne.existing_businesses.id` são UUID. O formulário privado não possui campo sectorial. A associação territorial de `mne.locations` continua a usar os identificadores inteiros de `investmoz`, sem nova taxonomia.
|
||
|
||
`004_mne_compatibility.sql` cria seis tabelas: identity_links, sector_links, business_links, compatibility_checkpoints, compatibility_rejections e compatibility_controls. Todas as novas FK têm cobertura por índices completos das constraints UNIQUE. O script verifica pré-condições, usa bloqueio consultivo, recusa tabelas de ponte com definição divergente e pode ser reaplicado. Não altera os ficheiros 001–003.
|
||
|
||
A coluna UUID `mne.parties.user_id` é mantida para reversibilidade, mas a nova constraint exige NULL. Contas autenticadas passam a ser resolvidas exclusivamente através de identity_links. A migration recusa dados antigos nesse campo em vez de tentar converter bigint em UUID. Pessoas podem existir sem conta; IdentityResolver só devolve uma ligação activa, vigente, a uma pessoa não arquivada. O resolver não autentica nem atribui permissões.
|
||
|
||
## Aplicação e backfill
|
||
|
||
BusinessRepository, LegacyBusinessRepository e CompatibleBusinessRepository estão ligados aos pontos de consulta dos controladores e dos quatro serviços privados. Políticas, bloqueios de escrita, versões e payloads HTTP existentes são preservados. Criação e gravação continuam nos modelos legados.
|
||
|
||
MneBusinessRepository é, por enquanto, um adaptador **apenas para comparação de cinco campos**: código, modalidade, estado, classificação e versão. Não implementa ainda a hidratação completa de um negócio nem substitui a autorização legada. SectorResolver v1 devolve UUIDs estáveis de ligação à taxonomia existente; não copia nomes ou cria sectores canónicos concorrentes.
|
||
|
||
```powershell
|
||
php artisan mne:backfill-compatibility --batch=100
|
||
php artisan mne:reconcile-compatibility
|
||
```
|
||
|
||
Usar um PHP com extensão pgsql. O backfill faz transacção por lote, bloqueio consultivo, IDs determinísticos, checksums e checkpoint do último lote não vazio. Cada nova execução percorre novamente a origem, para detectar também alterações anteriores ao checkpoint. Dados modificados invalidam a reconciliação. Vínculos sem destino canónico ficam pendentes, com código, causa e responsável `data-steward` na fila de excepções. A resolução não é aceite automaticamente. O backfill não cria pessoas ou negócios canónicos.
|
||
|
||
Resultado local: **1 vínculo de identidade pendente, 12 vínculos sectoriais activos, 0 negócios**, nenhuma chave em falta nem checksum divergente na execução. Há uma excepção de identidade não resolvida. A inexistência de negócios não conta como validação de uma migração real.
|
||
|
||
## Comparação sombra e reversão operacional
|
||
|
||
A comparação só é agendada após autorização de consulta da ficha. Requer `INVESTMOZ_MNE_COMPATIBILITY_SHADOW=true` e o controlo `shadow` em compatibility_controls activado com referência de evidência e percentagem. Ambos estão desligados na instalação local. O consumidor é `php artisan queue:work database --queue=mne-shadow`; filas síncronas são recusadas. O evento contém apenas resultado e latência, sem payload, identificador ou mensagem de excepção. Desligar o controlo interrompe novos agendamentos; trabalhos já enfileirados continuam somente de leitura.
|
||
|
||
Comparação parcial igual não abre o gate de leitura canónica. `canonical_read` está reservado, sem adaptador de resposta completo habilitado. Alterar a flag não transfere leitura ou escrita. Não se apresentam métricas de fallback canónico como se essa capacidade já existisse.
|
||
|
||
O DOWN 004 recusa qualquer vínculo, checkpoint, rejeição, controlo activo ou pessoa dependente. Esta é a situação local após backfill: para reverter a estrutura, é necessário arquivar/reconciliar primeiro essas dependências. Para continuar a operar pelo legado não é necessário executar DOWN. O script não remove dados de negócios nem históricos.
|
||
|
||
## Evidência
|
||
|
||
- Backup/restauro verificado de 204 tabelas antes de 004: `storage/app/private/mne-integrity-backup-20260929-191334/`.
|
||
- Aplicação: `storage/app/private/mne-compatibility-20260929-191400/`; contagens de 91 tabelas anteriores preservadas; schema mne passa de 70 para 76 tabelas.
|
||
- `tools/test-mne-compatibility.php`: 001–004 em base isolada, repetição, DOWN/reaplicação, backfill repetido, negócio sintético, acesso proprietário/terceiro, unicidade, FK, identidade revogada, sector desconhecido/alterado e recusa de estrutura divergente. Transacção integralmente revertida.
|
||
- Suite completa: 178 testes / 1820 verificações aprovados antes do teste adicional de isolamento da sombra. Esse teste adicional passou com 5 verificações.
|
||
- PHPStan aprovado. Contrato OpenAPI privado preservado. Sem alterações de interface; navegador não validado neste incremento.
|
||
|
||
## Gates ainda não satisfeitos
|
||
|
||
1. Correspondência canónica da identidade pendente e resolução formal das excepções.
|
||
2. Campo/relação sectorial nos negócios e reconciliação real de proprietários, estados e conteúdo completo.
|
||
3. Adaptador de leitura canónica completo, comparação integral, rollout e fallback testados.
|
||
4. Separação owner/migrator/runtime e testes de privilégios: a ligação local actual é superuser. Os triggers existem, mas esta conta pode desactivá-los. Nenhuma garantia de privilégio mínimo é declarada.
|
||
5. Concorrência com duas sessões, jornadas de navegador nos dois modos, notificações/SLA e deduplicação ponta a ponta.
|
||
|
||
Permanecem bloqueadas a transferência de escrita, a publicação e a produção. Não foi criado commit Git.
|