196 lines
27 KiB
Python
196 lines
27 KiB
Python
"""Publish sanitized QA evidence into the existing audit; never reads actor credentials."""
|
||
import json
|
||
import hashlib
|
||
import re
|
||
import sys
|
||
import xml.etree.ElementTree as ET
|
||
from datetime import datetime, timezone
|
||
from pathlib import Path
|
||
|
||
sys.stdout.reconfigure(encoding='utf-8')
|
||
ROOT = Path(__file__).resolve().parent.parent
|
||
DOCS = ROOT / 'docs/investmoz/v2/auditoria-portal'
|
||
PRIVATE = ROOT / 'storage/app/private/investmoz-v2/portal-audit'
|
||
|
||
def read(name):
|
||
return json.loads((PRIVATE / name).read_text(encoding='utf-8-sig'))
|
||
|
||
proof = read('opportunity-workflow-http-qa.json')
|
||
extended = read('opportunity-workflow-extended-http-qa.json')
|
||
multiple = read('opportunity-workflow-multirole-http-qa.json')
|
||
territory_tasks = read('opportunity-workflow-territory-tasks-http-qa.json')
|
||
verification = read('opportunity-workflow-verification-qa.json')
|
||
preserved = read('profiles-v1-preservation-qa.json')
|
||
counts = read('contagens-requisitos.json')
|
||
projection = read('pedidos-abertos-projection.json')
|
||
assert all(p['result'] == 'passed' and p['active_writes'] == 0 for p in [proof, extended, multiple, territory_tasks])
|
||
assert counts['requisitos'] == projection['canonical_requirements'] == 3386
|
||
assert counts['linhas_origem'] == projection['source_occurrences'] == 6838
|
||
assert all(preserved['previous_rows_preserved_by_id_and_original_columns'].values())
|
||
assert preserved['active_manifest_preserved'] and preserved['mfa18_unchanged']
|
||
test = ET.parse(PRIVATE / 'opportunity-workflow-final-tests-qa.xml').getroot().find('testsuite').attrib
|
||
assert test['errors'] == test['failures'] == '0'
|
||
manifest = hashlib.sha256((ROOT / 'public/build-qa-opportunities/manifest.json').read_bytes()).hexdigest()
|
||
stamp = datetime.now(timezone.utc).isoformat(timespec='seconds')
|
||
|
||
def prepend(path, content):
|
||
begin = '<!-- qa-workflow-20261010:begin -->'
|
||
end = '<!-- qa-workflow-20261010:end -->'
|
||
text = path.read_text(encoding='utf-8')
|
||
text = re.sub(re.escape(begin) + r'.*?' + re.escape(end) + r'\s*', '', text, flags=re.S)
|
||
title, _, rest = text.partition('\n')
|
||
block = '\n\n' + begin + '\n' + content.strip() + '\n\n'
|
||
block += '**Leitura temporal:** as secções seguintes preservam relatórios anteriores e respetivas evidências. Afirmações antigas sobre submissão sempre bloqueada, Validador 24 revogado, conta 29 apenas de bootstrap, contagens ou fingerprints não descrevem este incremento. O estado atual está acima e em [workflow-oportunidades-qa.md](workflow-oportunidades-qa.md).\n' + end + '\n\n'
|
||
if path.parent != DOCS:
|
||
for target in ['workflow-oportunidades-qa.md', 'matriz-requisitos.csv']:
|
||
block = block.replace('](' + target + ')', '](auditoria-portal/' + target + ')')
|
||
path.write_text(title + block + rest.lstrip('\n'), encoding='utf-8')
|
||
|
||
states = '\n'.join(f'| {state} | {value["requisitos"]} | {value["linhas_origem"]} |' for state, value in counts['por_estado'].items())
|
||
groups = '\n'.join(f'| {name} | {value} |' for name, value in projection['group_counts'].items())
|
||
evidence = f'''## Incremento canónico e workflow em QA — 10/10/2026
|
||
|
||
Servidor **http://127.0.0.1:18097**; destino guardado **desk_restore_20261009_174726_test:55441**. Zero escritas na base ativa. **C37 e toda a aceitação visual deste incremento permanecem pendentes.** Props da interface, API e persistência foram verificadas; nenhum clique ou renderização no navegador foi observado.
|
||
|
||
| Requisito na matriz única | Funciona / prova concreta em QA | Falta para fechar |
|
||
| --- | --- | --- |
|
||
| AUD-OP-04; AUD-PROFILE-28 | Dez categorias guardam rascunhos incompletos e recuperam noutra sessão MFA. Seis passam o contrato estrutural: investimento, imobiliário, DUAT, venda, parceria e franquia. Adapter do mesmo schema de 110 definições; condições `allOf` originais recuperadas, IDs existentes mantidos. | Semântica e editores dos objetos incompletos do §25; contrato Response integral; quatro perfis modulares aprovados; demonstração visual por categoria. |
|
||
| AUD-OP-03; PROFILE-08/11/12 | Promotor 21 criou a oportunidade **18**, submeteu; Validador 24 solicitou correção; 21 corrigiu/resubmeteu; 24 reviu gates e aprovou; Publicador 25 publicou com visibilidade interna. O número 18 identifica a oportunidade, não a conta do investidor C37. | Visual integral, todas as categorias, pareceres/incidentes e coordenação editorial completa. |
|
||
| PROFILE-09/10/12/21 | Imobiliário **19**: rejeição fundamentada por 24 → recurso reaberto pelo revisor independente 29 → nova aprovação 24 → publicação pública 25 → alteração privada sem alterar a ficha pública → suspensão com GET público 404. Autor Prom+Val+Pub e aprovador Val+Pub receberam 403. | Visual, filas institucionais e competências reais; suspensão/retoma e demais ações editoriais por todos os perfis. |
|
||
| PROFILE-19/21/22 | Tarefas existentes em `tasks`, vínculo à oportunidade por origem/ID/correlação; atribuição explícita, motivos e decisões recuperáveis. Correção/rejeição concluem revisão; resubmissão não herda atribuição; suspensão conclui tarefas pendentes. Recurso do próprio rejeitor e membro da organização negados. SLA `unconfigured`, responsável e prazo iniciais nulos. | Filas completas, reatribuição/disponibilidade, coordenação editorial e política SLA aprovada. Não foram inventados responsáveis nem prazos. |
|
||
| COUNTRY-01; GEO-03; OP-02 | Localização MZ/Cabo Delgado/distrito e documentos ligados ao mesmo contrato recuperados nas seis categorias. Oportunidade **28** publicou usando a localização principal mesmo em segundo lugar na lista. Documentos e imagem/duas derivadas verificados com ClamD real e hashes correspondentes. DUAT **20** aprovado internamente não publicou: 422 por autorização externa pendente. | Outros países/formulários, origem/filtros/estatísticas transversais, mapas renderizados, 188 correspondências cartográficas e operações documentais restantes. |
|
||
| PROFILE-30; DASH-01 | Conta **Promotor QA — conta sintética 21**, MFA normal confirmado, organização e tipos autorizados. Dashboard devolve navegação do Promotor. Permissões temporárias dos testes foram revogadas e uma nova sessão 21 recuperou o dashboard. | Dashboard → formulário → guardar → nova sessão → workflow e resultado visíveis. Auditor ou Superutilizador não substituem este ensaio. |
|
||
|
||
Os requisitos acima continuam **parciais**: nenhum passou a concluído pelo incremento. O detalhe está no [relatório do workflow](workflow-oportunidades-qa.md); fontes, versões, critérios e percursos permanecem na [mesma matriz](matriz-requisitos.csv).
|
||
|
||
| Estado canónico | Requisitos / linhas da matriz | Ocorrências de origem |
|
||
| --- | ---: | ---: |
|
||
{states}
|
||
|
||
Total: **3.386 requisitos = 3.386 linhas**, **6.838 ocorrências**, **3.380 requisitos abertos**. As referências e versões anteriores foram preservadas.
|
||
'''
|
||
|
||
backlog = f'''## Próximo trabalho executável — incremento de 10/10/2026
|
||
|
||
| Prioridade / requisito | Correção concreta seguinte | Critério de fecho e dependência |
|
||
| --- | --- | --- |
|
||
| P0 — UI-01/C37; DASH-01/C43 | Incorporar ensaio visual com Promotor 21 e, separadamente, investidor 18; registar falhas com URL, ação, estado e resposta sanitizada. | Login/MFA → dashboard → guardar → logout → nova sessão → recuperar, sem loop, perda ou acesso indevido; não substituível por HTTP. |
|
||
| P1 — OP-04; PROFILE-28 | Completar editores e validações semânticas §25: grelhas de serviços/ónus, avaliação/documento, ocupação/título/cadastro, comunidades/consulta/benfeitorias, financeiros/beneficiário efetivo, NDA, governação e franquia; completar Response. Reutilizar contrato e entidades atuais. | Rascunho parcial recuperável; cada condição aplicável recusa dados inválidos e aceita dados/evidências completos; interface por categoria. Confirmar correspondências de objetos opacos do schema, sem alterar os significados legados silenciosamente. |
|
||
| P1 — OP-03; PROFILE-11/12/19/21 | Completar filas/revisões e editoriais, reatribuição, pareceres, incidentes e recurso; manter hash da versão e independência. | Atores distintos e responsáveis explicitamente designados, motivos/evidência e histórico; revogação reavaliada. Ciclo principal já demonstrado por HTTP, não repetir o inventário. |
|
||
| P1 — COUNTRY/STATS/GEO | Completar cobertura por formulário/consumidor, mapas e nomes cartográficos pendentes. | País/origem persistidos → recuperação → filtros/estatísticas; território cadastrado ≠ geometria ≠ mapa apresentado. 393 limites privados não encerram integração visual; faltam 31 distritos e 157 postos. |
|
||
| P1 — OP-02/LIB/PROFILE-23 | Verificar tipos/partilhas/PDFs e derivadas ainda sem prova específica e autorizações do original. | ClamD real separado por operação; hashes/originais preservados; acesso permitido/negado e resultado visível. PNG/documentos do ciclo e duas derivadas já demonstrados. |
|
||
| P1 — PROFILE-23 (achado adicional) | Composer audit apontou dois avisos preexistentes em `league/commonmark`: GHSA-97jj-33gv-5xf9 e GHSA-3q6v-r5mr-hxv8. Identificar consumidores/configuração e preparar correção compatível em QA. | Prova local `workflow-composer-audit.json`; avaliar aplicação dos avisos e validar os consumidores afetados. Não atribuir aos três pacotes Opis nem declarar exploração demonstrada. |
|
||
| P2 — PROFILE-22/31 | Configuração SLA versionada, instalaçao autenticada de perfis/dupla e preparação de ativação. | Decisões reais explícitas; ensaio backup/restauro da candidata posterior à visual; nenhum prazo ou titular real escolhido por QA. |
|
||
|
||
**Decisões concretas:** (1) quais versões imutáveis de perfil, campos, documentos e gates são aprovadas para concessão, financiamento, fornecimento e outros? (2) qual política versionada fixa prazos, tolerância, ciclos e escalamento? (3) quem assume formalmente as responsabilidades institucionais e os exatamente dois superutilizadores ativos? Não bloqueiam as correções independentes, nem foram inferidas dos atores sintéticos.
|
||
|
||
| Grupo dos pedidos abertos (projeção da mesma matriz) | Requisitos |
|
||
| --- | ---: |
|
||
{groups}
|
||
|
||
Lista integral: **http://127.0.0.1:18097/qa-auditoria/pedidos-abertos**, sob MFA de gestor/Auditor/Superutilizador QA. Cada cartão conserva o estado canónico, fontes, lacuna e próxima ação. “Preparado em QA” indica um escopo provado, não conclusão total.
|
||
'''
|
||
|
||
activation = '''## Sequência reconciliada de disponibilização futura — não executada
|
||
|
||
Leitura ativa de 10/10: PostgreSQL `investemoz:5432`, transação READ ONLY, seis oportunidades publicadas; 020000 instalada, 030000/040000/percurso ausentes, flags desativadas, zero geometrias. Build ativo preservado. A revisão candidata **não está fixada**; `ready=true` e fingerprints anteriores não autorizam nem demonstram instalação.
|
||
|
||
| Ordem | Ação e efeito previsto | Dependência / reversão |
|
||
| --- | --- | --- |
|
||
| 0 | Incorporar visual C37/C43/A/B e workflow, corrigir falhas; fixar revisão, configuração e manifestos. Renovar backup DB + ficheiros privados/originais + chave estável e provar restauro numa nova QA isolada. | Provas anteriores preservadas, sem as apresentar como restauro desta revisão. Não gerar nova chave. |
|
||
| 1 | Disponibilizar código e dependências compatíveis, flags desligadas. Composer adiciona `opis/json-schema 2.4.1`, `opis/string 2.1.0`, `opis/uri 1.1.0`; zero atualizações/remoções preexistentes. | Não importar contas, classificações, contactos ou documentos sintéticos QA. Reverter código/assets compatíveis, preservando payloads/histórico. |
|
||
| 2 | Não repetir 020000. Se 030000 continuar ausente, usar prévia/aplicação autenticada `/management/opportunity-resources-install`: três tabelas, uma coluna documental, uma função e três triggers previstos. | Backup/restauro confirmado; hashes/contagens verificados no estado real; não publica nem habilita o percurso. |
|
||
| 3 | Preparar e testar o mecanismo autenticado 040000: quatro tabelas, uma coluna de utilizador, três de oportunidade, uma função e dois triggers previstos; dupla inicial/substituição independente. | Aplicação atual demonstrada exclusivamente QA. Instalação/bootstrap ativo autenticado ainda pendente; titulares reais não definidos. Não remover privilégios ativos automaticamente. |
|
||
| 4 | Configurar referências/contactos/hierarquia, perfis/tipos/representação, responsabilidades e MFA; quatro contratos modulares apenas após aprovação da versão. | Reutilizar dados mestres reais. As referências sintéticas de ensaio não resolvem cadastros ativos vazios. SLA permanece indeterminado até política aprovada. |
|
||
| 5 | Importação cartográfica autenticada, privada e idempotente; se ativo permanecer zero e correspondências iguais, até **393 = 11 províncias + 128 distritos + 254 postos**. Esperados 581 = 11/159/411; pendentes 188 = 0/31/157, nomes no relatório de correspondências. | Prévia → correspondências inequívocas → scan/hash → aplicar → auditoria; nenhuma localização/conta/perímetro de projeto inventado. Reversão pelo lote preserva origem/uso/histórico. **Publicação de camadas é ação separada.** |
|
||
| 6 | Disponibilizar flags/assets/navegação aprovados e o percurso I1–I3 pela instalação existente, sem repetir ações já presentes. Publicar cada oportunidade separadamente, com aprovação/hash/prévia/âmbito. | Cinco fases/19 etapas preservadas, dossier privado separado. Voltar flags a false limita disponibilização; manter guardas de confidencialidade para novos dados. Não executar down destrutivo após uso. |
|
||
|
||
Após uso, reverter por configuração compatível, suspensão/arquivo autorizado ou compensação auditada; não eliminar decisões, documentos, consentimentos, relações ou originais. Restauro global exige reconciliar alterações posteriores ao backup. Este plano não contém aprovação de ativação nem declaração de instalação ativa.
|
||
'''
|
||
|
||
manual = '''## Ensaio manual atual — Promotor QA e workflow
|
||
|
||
**URL inicial exato: http://127.0.0.1:18097/dashboard. Conta: Promotor QA — conta sintética 21.** Se necessário, o login normal é `/login`, com MFA Fortify. Credenciais e códigos permanecem exclusivamente no ficheiro privado local; não os copiar para a conversa. Conferir identificação QA/porta 18097; não usar `portal-investidor.test`.
|
||
|
||
1. Entrar como Promotor 21, concluir MFA e atualizar dashboard. Esperado: “Minhas oportunidades” e “Nova oportunidade”, sessão mantida. Um retorno a login entra como reprodução pendente, não como sucesso.
|
||
2. Pelo dashboard, clicar “Nova oportunidade”, escolher organização QA representada e categoria imobiliária; criar e guardar **rascunho incompleto**, incluindo um campo opcional limpo. Esperado: ID, estado rascunho e ausência de bloqueio por campos ainda não preenchidos.
|
||
3. Anotar o ID sem copiar informação privada; logout, nova sessão/MFA, dashboard → “Minhas oportunidades” → mesmo ID. Esperado: recuperação exata, organização/autor preservados. Submeter incompleto deve mostrar campos pendentes e manter o rascunho.
|
||
4. Abrir recursos pelo formulário: MZ → Cabo Delgado → distrito válido → principal; guardar/reabrir. Esperado: mesmos IDs/nome, filhos coerentes; mapa administrativo quando disponível. Não usar limite administrativo como geometria de parcela. Carregar documento sintético permitido; confirmar scan/recuperação e vínculo ao mesmo registo.
|
||
5. Completar núcleo e módulo imobiliário com dados explicitamente sintéticos. O catálogo de ensaio possui sector/subsector/atividade QA; contacto é da organização QA. Usar `sale`, `warehouse`, `completed`, condição `good`, áreas positivas, moeda/preço positivo, ocupação/título/ónus/avaliação e licença aplicável; documento e localização selecionados no contrato. Preencher resumo/pedido/evidências e declaração de verdade. Para este primeiro ciclo usar visibilidade **internal**. Os editores de objetos/grelhas ainda incompletos devem ser registados como falhas: não contornar pela consola nem fingir visual concluída.
|
||
6. Guardar com motivo → submeter. Esperado: `/view`, estado submetido, formulário bloqueado, snapshot/versionamento e tarefa de revisão sem responsável/prazo inventado. A rota `/edit` fechada não deve ser usada para continuar revisão.
|
||
7. Noutra sessão QA entrar como **Validador 24**; abrir o mesmo ID autorizado, atribuir/iniciar revisão, solicitar correção com motivo e campo identificado. Esperado: necessidades de informação, motivo recuperável e tarefa de correção.
|
||
8. Voltar como 21: abrir mesma oportunidade, corrigir, guardar com motivo e resubmeter. Logout/nova sessão deve recuperar a versão corrigida sem perder a decisão anterior.
|
||
9. Como 24: iniciar a revisão dessa versão, registar os gates aplicáveis com decisão/evidência/fundamento; aprovar. Esperado: versão/hash aprovados, aprovação prematura recusada.
|
||
10. Como **Publicador 25**: abrir `/view`, rever prévia, confirmar âmbito e publicar. Esperado: publicado interno, sem exposição na API pública. Para o ensaio público separado, preparar capa, legenda/alt/direitos e duas derivadas analisadas; confirmar prévia/hash e publicar explicitamente.
|
||
11. Como 21, solicitar alteração material com fundamento, editar a proposta privada. Esperado: nova revisão sem aprovação reutilizável; ficha pública anterior permanece intacta. Como 25 suspender com motivo; esperado GET público 404 e história preservada.
|
||
12. Em registo separado, como 24 rejeitar com fundamento; como 21 pedir recurso; como **revisor independente 29** reabrir. Esperado: rejeição original conservada. Rejeitor e membro da organização devem ser recusados. Conta 31 com papéis acumulados/Auditor continua sem escrita. Não atribuir responsabilidades reais às contas sintéticas.
|
||
|
||
Recolher por passo apenas hora UTC, perfil/ID, URL sem tokens, ação, resultado visível e referência do registo. Omitir Cookie, X-XSRF-TOKEN, passwords, segredo/código MFA e documentos privados de capturas. C37/investidor 18 e cenários A/B continuam no roteiro existente, separados deste ensaio. Sucesso HTTP abaixo não certifica nenhum dos passos visuais.
|
||
'''
|
||
|
||
cases = '''## Reproduções adicionais do incremento — 10/10/2026
|
||
|
||
| Caso / requisito | Reprodução e esperado | Falha ou risco encontrado / causa | Correção e evidência separada |
|
||
| --- | --- | --- | --- |
|
||
| C44 (complemento) — OP-04/PROFILE-28 | Guardar rascunho especializado parcial → completar → submeter; condições da categoria devem ser verificadas. | Submit permanecia bloqueado pelo contrato não integrado; a extração dos Create não conservava as condições `allOf` do schema original. | Adapter recupera condições, usa validação Draft2020-12 e recursos existentes. Dez rascunhos recuperados; seis submissões aceites/ quatro recusadas por perfil. Semântica integral e visual pendentes. |
|
||
| C50 — OP-04 | Imobiliário `sale`, `price:null`: guardar rascunho permitido, submeter recusado. | Campo nullable e `required` não garantiam preço positivo para venda. | Regra explícita positive; oportunidade19: draft aceite, submit422, preço corrigido e submit200. |
|
||
| C51 — PROFILE-25 | Após submissão, continuar pela visualização; edição deve ficar fechada. | Código da ação recarregava `/edit`, que passa corretamente a403 após submissão; o primeiro acesso HTTP Validador a essa rota confirmou a restrição, não uma falha de autorização. | Ações navegam `/view`; edição privada tem link apenas autorizado. API/props/build verificados; transição visível ainda pendente. |
|
||
| C52 — PROFILE-08/12/25 | Publicada → pedido de alteração → pesquisar título privado/estado → recuperar; ficha pública não pode mudar antes de aprovação. | Consulta/contagens usavam só título e estado públicos, ocultando a posição da proposta privada. | Consulta já autorizada usa estado/título de trabalho, preservando publicação. Teste específico do filtro/contagem e HTTP público19 original até suspensão. Visual pendente. |
|
||
| C53 — GEO-03/PROFILE-12 | Duas localizações, principal em segundo lugar → aprovar/publicar; território apresentado deve ser o principal. | Revisão de código encontrou uso da primeira posição da lista, que não define a principal. | Filtra `is_primary`; HTTP oportunidade28 apresenta ID/distrito principal correto. Teste específico isolado; mapa visual pendente. |
|
||
| C54 — PROFILE-19 | Revisão → correção → resubmeter; ou revisão → rejeitar. Esperado: tarefa anterior concluída, nova tarefa sem atribuição presumida. | Código mantinha revisão antiga aberta e podia herdar atribuição numa nova versão. | Conclui tarefas com motivo/histórico; limpa atribuição na submissão. HTTP28: correção/resubmissão/publicação/suspensão, nenhuma tarefa aberta ao final; HTTP29: rejeição fecha revisão. |
|
||
| C37 / C43 | Login investidor18; dashboard Promotor21 e ciclo de ações. | Não houve demonstração visual atual no navegador. | Mantidos pendentes, roteiro e conta preparados; não fechar por HTTP, props ou total de testes. |
|
||
|
||
Rejeições esperadas adicionais: motivo curto422, confirmação de publicação falsa422, hash de prévia errado409, self/multirole403, recurso pelo rejeitor/organização403, publicação fundiária com autorização externa pendente422. Provas privadas específicas preservam sequência/estado, sem segredos.
|
||
'''
|
||
|
||
for name, body in [('relatorio-executivo.md', evidence), ('backlog.md', backlog), ('plano-ativacao.md', activation), ('casos-reproducao.md', cases),
|
||
('roteiro-manual-perfis-v1.md', manual), ('perfis-v1-reconciliacao.md', evidence),
|
||
('cobertura-percursos-i0-i3.md', evidence), ('execucao-percurso-i1-i3.md', evidence)]:
|
||
prepend(DOCS / name, body)
|
||
prepend(ROOT / 'docs/investmoz/v2/gestao-oportunidades-dashboard.md', manual + '\n\n' + evidence)
|
||
|
||
details = f'''# InvestMoz — contratos e workflow de oportunidades em QA
|
||
|
||
Atualizado em **{stamp}**. Incremento da mesma auditoria e matriz; não cria inventário paralelo. Este relatório discrimina **código preparado**, **HTTP/persistência demonstrados em QA** e **funcionalidade ativa**.
|
||
|
||
{evidence}
|
||
|
||
## Provas reproduzíveis e limites
|
||
|
||
| Prova privada local (sem credenciais) | Percurso / camada |
|
||
| --- | --- |
|
||
| `opportunity-workflow-http-qa.json` | {len(proof['events'])} pedidos ao servidor 18097, Fortify/MFA normal; dez categorias, gravação/recuperação noutra sessão, ciclo investimento18, correção/gates/aprovação/publicação interna; rejeição/negativas iniciais. |
|
||
| `opportunity-workflow-extended-http-qa.json` | {len(extended['events'])} pedidos; recurso29, imobiliário19 público com ClamD/derivadas, confirmação/hash, proposta privada preserva público, suspensão404; fundiário20 autorizado internamente mas publicação422. |
|
||
| `opportunity-workflow-multirole-http-qa.json` | {len(multiple['events'])} pedidos; autor Prom+Val+Pub403, aprovador Val+Pub403, Auditor acumulado403, três atribuições temporárias revogadas; nova sessão Promotor21 normal. |
|
||
| `opportunity-workflow-territory-tasks-http-qa.json` | {len(territory_tasks['events'])} pedidos; oportunidade28 localiza principal em segundo lugar, conclui revisão por correção, resubmete sem atribuição herdada e suspende sem tarefas abertas; oportunidade29 conclui tarefa com rejeição. |
|
||
| `opportunity-workflow-verification-qa.json` | Releitura atual do contrato e referências: seis passam, quatro sem perfil; país/localização e hashes documentais. O total territorial inclui fixture QA isolada e não prova cobertura real. |
|
||
| `opportunity-workflow-final-tests-qa.xml` | {test['tests']} testes / {test['assertions']} asserções, zero erros/falhas; testes específicos de estados, binding estrangeiro, integridade de bytes, draft/null, filtros privados e independência. Fixtures de política não são prova de ClamD real. |
|
||
| `profiles-v1-preservation-qa.json` | Registos anteriores de 18 conjuntos conservados por ID/colunas originais; MFA18 e build ativo preservados. Captura {preserved['captured_at']}. |
|
||
|
||
PHPStan dos componentes alterados, TypeScript e compilação QA passaram. Manifesto QA **`{manifest}`**; ativo **`75352185c2a85c34ab726613db864a598e301a5b342ebbc80ac8e678eed17a94`**. Nenhuma página foi renderizada/clicada no navegador deste ensaio. A extensão de fonte `source.json` mantém flags false como fotografia histórica da extração, não como configuração do runtime atual.
|
||
|
||
## Compatibilidade e contratos restantes
|
||
|
||
Fonte integral: especificação do cadastro, SHA256 `9f173ed3024d2beddef7888b692d8b81fc5e4700249955f2bae9bdd2eb2be504`; §25 campos/semântica, §26 schema, §27 gates. Artefacto normativo de 110 definições preservado, SHA256 `9ce0acfa5df1f81a3357dee9e5a9a1c4e77e4eefc8bce294497d18f4caa8e5c0`. O adapter distingue entrada parcial e submissão, liga documentos/localizações/imagens pelos IDs existentes e valida relações/scan/bytes. Snapshots, decisões, motivos e hashes usam `management_draft`, `workflow_context` e auditoria existentes.
|
||
|
||
IDs bigint de oportunidades/sectors não foram convertidos aos UUID de exemplos; não foram criados cadastros paralelos. Tarefas reutilizam `tasks`; a sua coluna `opportunity_id` aponta a oportunidades CRM UUID e não recebe o bigint do portal: a relação é explícita por source_system/external_id/correlation_id. Contactos e subsector/atividade reutilizam `contacts`, `investors`, `investor_contacts`, `economic_activities` e versões existentes. As referências acrescentadas para o ensaio são marcadas QA-synthetic, não oficiais, e não devem ser importadas no ativo.
|
||
|
||
Este incremento **não implementa integralmente** os objetos normativos descritos apenas como object, as relações SQL adicionais do §27 nem o Response integral. Validação estrutural aceita parte desses objetos sem detalhamento: exige continuação semântica antes de ativar os contratos. Aprovação interna é uma decisão identificada de QA; não confirma atos externos, autenticidade ou situação jurídica. DUAT pendente foi recusado na publicação mesmo após todos os gates internos.
|
||
|
||
O rascunho admite ausência, vazio e null nos campos ainda não preenchidos, preservando as restrições de valores fornecidos e impedindo campos readonly/verified do cliente. Contratos de concessão/financiamento/fornecimento/outros ficam em rascunho até existir perfil versionado aprovado e imutável; não foi fabricada configuração para os submeter.
|
||
|
||
{manual}
|
||
|
||
{backlog}
|
||
|
||
{activation}
|
||
'''
|
||
(DOCS / 'workflow-oportunidades-qa.md').write_text(details, encoding='utf-8')
|
||
print(json.dumps({'updated_documents': 10, 'requirements': 3386, 'source_occurrences': 6838, 'qa_visual_pending': True, 'active_writes': 0}, ensure_ascii=False))
|
||
|
||
# Preserve the latest per-category evidence when rebuilding the historical report.
|
||
semantic = PRIVATE / 'opportunity-semantic-publication-http-qa.json'
|
||
if semantic.exists() and json.loads(semantic.read_text()).get('result') == 'passed':
|
||
import runpy
|
||
runpy.run_path(str(ROOT / 'tools/portal-audit-semantic-docs.py'), run_name='__main__')
|