108 lines
19 KiB
Python
108 lines
19 KiB
Python
"""Add current C43/C44 evidence without replacing historical audit sections."""
|
||
import json
|
||
import re
|
||
from pathlib import Path
|
||
|
||
root = Path(__file__).resolve().parent.parent
|
||
docs = root / 'docs/investmoz/v2/auditoria-portal'
|
||
private = root / 'storage/app/private/investmoz-v2/portal-audit'
|
||
runtime = json.loads((private / 'investor-path-qa-runtime.json').read_text())
|
||
projection = json.loads((private / 'pedidos-abertos-projection.json').read_text())
|
||
marker = 'qa-dashboard-20261010'
|
||
|
||
|
||
def readable(body):
|
||
# Preserve exact identifiers/URLs while spacing numerical evidence and prose.
|
||
tokens = []
|
||
pattern = r'`[^`]+`|https?://[^\s;),]+|[0-9a-f]{64}|[\w./-]+\.(?:json|php|xml|tsx|ts|md)|AUD-[A-Z]+-\d+|C\d+|\bI[0-3]\b|\bP[0-2]\b|realEstatePatch|Opportunity[A-Za-z]+'
|
||
def keep(match):
|
||
tokens.append(match.group())
|
||
return '\x00'+str(len(tokens)-1)+'\x00'
|
||
body = re.sub(pattern, keep, body)
|
||
body = re.sub(r'(?<=[A-Za-zÀ-ÿ])(?=\d)|(?<=\d)(?=[A-Za-zÀ-ÿ])', ' ', body)
|
||
body = re.sub(r'([,;:])(?=[A-Za-zÀ-ÿ\d])', r'\1 ', body)
|
||
body = re.sub(r'([,;:])(?=\x00|\()', r'\1 ', body)
|
||
body = re.sub(r'(?<=[A-Za-zÀ-ÿ])(?=\x00)', ' ', body)
|
||
body = re.sub(r'\.([A-ZÀ-Ÿ])', r'. \1', body)
|
||
for old, new in {'QA e': 'QA e', 'QAflag': 'QA flag', 'QA/backend': 'QA/backend', 'sótrue': 'só true', 'porformulário': 'por formulário', 'empreparação': 'em preparação', 'schemaíntegro': 'schema íntegro', 'àgestão': 'à gestão', 'daQA': 'da QA', 'noativo': 'no ativo', 'doativo': 'do ativo', 'semduplicar': 'sem duplicar', 'seativo': 'se ativo', 'MFA em': 'MFA em', 'flagfalse': 'flag false', 'codeQA': 'código QA', 'workflow completo': 'workflow completo', 'statusarchived': 'status archived', 'volta adraft': 'volta a draft', 'labelCriar': 'label Criar', 'dossiersprivados': 'dossiers privados', 'tipos/enums': 'tipos/enums', 'sem publicação': 'sem publicação', 'no management_draft': 'no management_draft', 'MFAprévia': 'MFA: prévia', 'antes deaceitação': 'antes de aceitação', 'provas porversão/perfil': 'provas por versão/perfil', 'Dow nsomente': 'Down somente', 'Downsomente': 'Down somente', 'Não há hotfile/cacheconfig': 'Não há hotfile/cache de configuração', 'capturas sanitizadas': 'capturas sanitizadas'}.items():
|
||
body = body.replace(old, new)
|
||
for old, new in {'transaçãoSQL': 'transação SQL', 'GestoresQA': 'Gestores QA', 'InvestidoresQA': 'Investidores QA', 'emailverificado': 'email verificado', 'possuiMFA': 'possui MFA', 'títuloGestão': 'título Gestão', 'antigaCriar': 'antiga Criar', 'menuPainel': 'menu Painel', 'nofim': 'no fim', 'comoCriar': 'como Criar', 'rótuloNova': 'rótulo Nova', 'emportal.managers': 'em portal.managers', 'CorreçãoQA': 'Correção QA', 'atalhosGestão': 'atalhos Gestão', 'açãoarchive': 'ação archive', 'emstatus': 'em status', 'usaflagsfalse': 'usa flags false', 'usaassets': 'usa assets', 'versãoInertia': 'versão Inertia', 'dessemanifesto': 'desse manifesto', 'bootHTTP': 'boot HTTP', 'filtroarchived': 'filtro archived', 'OportunidadeQA': 'Oportunidade QA', 'oportunidadeQA': 'oportunidade QA', 'IDestável': 'ID estável', 'draftexistente': 'draft existente', 'patchmerge': 'patch merge', 'nomeadosDashboard': 'nomeados Dashboard', 'buildQA': 'build QA', 'ePHPStan': 'e PHPStan', 'novoPDF': 'novo PDF', 'ProvaClamD': 'Prova ClamD', 'porID': 'por ID', 'apenasAPI': 'apenas API', 'eativação': 'e ativação', 'tarefasQA': 'tarefas QA', 'antes de': 'antes de', 'code/assets': 'código/assets', 'no/dashboard': 'no /dashboard', 'apontava/investidor': 'apontava /investidor', 'emportal': 'em portal', 'Lista integral legível': 'Lista integral legível', 'gestorautenticado': 'gestor autenticado', 'configuração ativa': 'configuração ativa', 'somente se': 'somente se', 'PORTAL': 'PORTAL', 'code_hash': 'code_hash'}.items():
|
||
body = body.replace(old, new)
|
||
return re.sub(r'\x00(\d+)\x00', lambda m: tokens[int(m[1])], body)
|
||
|
||
|
||
def insert(path, body):
|
||
text = path.read_text(encoding='utf-8-sig')
|
||
text = re.sub(r'\n<!-- '+marker+r':begin -->.*?<!-- '+marker+r':end -->\n', '\n', text, flags=re.S)
|
||
headline, rest = text.split('\n', 1)
|
||
block = '\n<!-- '+marker+':begin -->\n'+readable(body.strip())+'\n\n**Histórico preservado:** os blocos anteriores a C43/C44 abaixo conservam as suas fontes e provas. Os seus hashes/ready/contagens não certificam a revisão atual; a primeira adaptação imobiliária não equivale ao schema integral nem ao workflow.\n<!-- '+marker+':end -->\n'
|
||
path.write_text(headline+'\n'+block+'\n'+rest.lstrip('\n'), encoding='utf-8')
|
||
|
||
|
||
facts = '''QA exclusiva:http://127.0.0.1:18097, alvo real `desk_restore_20261009_174726_test:55441`. Ativo consultado por transaçãoSQL READ ONLY;0escritas/instalações/publicações ativas. Cinco fases/19etapas,5dossiers/95etapas e393geometrias QA preservados. C37 e aceitação visual permanecem abertos.
|
||
|
||
GestoresQA14/17 têm emailverificado+`manage-portal`; gestor17 possuiMFA normal. InvestidoresQA13/18 não têm gestão. No ativo, a leitura confirmou contas2/13 autorizadas,020000instalada e030000ausente; o dashboard ativo contém títuloGestão de Oportunidades e ação antigaCriar oportunidade. Não há hotfile/cacheconfig/cache de rotas a explicar a ausência. URL configurado ativo:http://portal-investidor.test; **URL/conta da sessão reportada ainda desconhecidos**, sem atribuição especulativa de causa a essa conta.'''
|
||
evidence = '''- `dashboard-active-readonly.json`:configuração/contas elegíveis/instalação/manifesto ativo, sem bootHTTP/escrita de sessão no ativo.
|
||
- `dashboard-opportunities-http-qa.json`:links obtidos do dashboard→gestão→create→201→GET→logout/nova sessão→GET→PUT→archive→filtroarchived→restore→GET. OportunidadeQA13,IDestável/quatro eventos,12originais e relações/documentos/dossiers preservados;6publicadas mantidas;outra conta403.
|
||
- `dashboard-manager-mfa-http-qa.json`:gestor17,MFA em duas sessões→dashboard→gestão→recuperação/reload→logout;0alterações de registos. `dashboard-navigation-catalogue-qa.json`:menuPainel da gestão→/dashboard,dossiers privados→/investidor,atalhos únicos e ausência de gestão para investidor.
|
||
- `real-estate-draft-http-qa.json`:outra oportunidadeQA14,rascunho imobiliário parcial no draftexistente→nova sessão→patchmerge→cinco422sem mutação→outsider403;schema normativo SHA9ce0acfa5df1f81a3357dee9e5a9a1c4e77e4eefc8bce294497d18f4caa8e5c0.
|
||
- `dashboard-real-estate-qa.xml`:casos nomeadosDashboardOpportunityAccessTest/OpportunityManagementTest/OpportunityRealEstateDraftTest,8ensaios/201asserções. Typecheck,buildQA ePHPStan dirigidos passaram; contagem não substitui os critérios visuais.
|
||
- `resource-originals-preservation-http-qa.json`:cinco binários anteriores preservados e novoPDF válido recuperado/parseado,0novos recursos. ProvaClamD real anterior mantida; não afirma novo scan das derivadas nem renderização.
|
||
- `dashboard-matrix-reconciliation-qa.json` e `pedidos-abertos-projection.json`:fontes/trechos/IDs/versões preservados,3354requisitos/linhas e5830ocorrências;3349abertos apresentados uma vez cada. EstadoAUD-OP-04 passa de não implementado a parcial; nenhum requisito global encerrado.'''
|
||
causes = '''**C43 — causas encontradas no código/compilação:**(1)AppSidebar mostrava só o primeiro filho de cada grupo, descartando oportunidades;(2)menuPainel apontava/investidor mesmo para gestor;(3)dashboard de gestão colocava criação nofim comoCriar oportunidade, sem rótuloNova oportunidade. A secção de gestão só é devolvida pelo backend a contas verificadas emportal.managers; o seu ocultamento para investidor é autorização esperada, não motivo para conceder perfil administrativo.
|
||
|
||
CorreçãoQA:atalhosGestão de Oportunidades/Nova oportunidade no início do dashboard,sidebar/menu agrupado;Painel da gestão→/dashboard,dossiers→/investidor. Nova açãoarchive conserva o rascunho emstatusarchived/deleted_at=null;delete/exclusão lógica mantém o contrato anterior. Restauro volta adraft,ID/histórico intactos,sem publicação. Código usaflagsfalse por omissão; QA usaassets `public/build-qa-opportunities`, versãoInertia dessemanifesto. **`public/build` ativo manteve SHA75352185c2a85c34ab726613db864a598e301a5b342ebbc80ac8e678eed17a94.** Recursos030000não são requisito para navegar/criar rascunho básico.
|
||
|
||
**C44 — progresso específico:**primeiro adaptador imobiliário aceita campos fornecidos nas24propriedadesrealEstatePatch,validando tipos/enums/limites/UUID e recusando campos desconhecidos/de resposta. Guarda/merge privadamente no management_draft atual. Ainda faltam formulário especializado,vínculos canónicos,condições finais/Create/Response,DUAT/transação e workflow. Nenhuma coleção/tabela paralela,renumeração ou decisão externa criada. O.source.json conserva o retrato histórico da extração, não certifica o estado runtime atual.'''
|
||
groups = '''| Grupo de trabalho dos abertos | Requisitos | O que falta / próxima ação |
|
||
| --- | ---: | --- |
|
||
| Não implementados |145|Workflow integral segregado;rascunhos incompletos procura/capacidade e jornadas educativas ainda por fazer;demais critérios específicos não implementados no relatório porID. Implementar workflow sobre draft/auditoria após contratos/gates;educação não começa enquanto prioridades abertas.|
|
||
| Parciais |3183|Contrato imobiliário apenasAPI;DUAT/transações/campos/regras finais e vínculos;cartografia31distritos/157postos/mapas por consumidor;relações/citações;acervo/PDFs/partilhas/derivadas;parâmetros fiscais;negócios/direitos/mandatos;reconciliação documental/UX eativação. Inclui4decisões com estado original,sem bloquear tarefasQA independentes.|
|
||
| Preparados emQA |19|Escopos concretos de rascunhos/recursos/maturidade,países/origem/estatísticas,seletor provincial,Balcão/percurso/CRM/orientação/simulador/parceria/fundiário/importação privada com provasQA. Completar critérios restantes na interface e operações/tipos ainda abertos;ativação permanece separada. Não são19requisitos globais concluídos.|
|
||
| Instalados com falha de acesso |2|AUD-DASH-01(C43) eAUD-UI-01(C37/inspeção). Código/backendQA corrigidos nos escopos descritos;identificar sessão reportada e demonstrar dashboard/cliques e loginA/B completos. Confirmar visualmente sem conceder gestão ao investidor.|
|
||
|
||
**Lista integral legível:**http://127.0.0.1:18097/qa-auditoria/pedidos-abertos,gestorQA14/17.3349cartões,um porID,com pedido,lacuna,próxima ação,critério,fontes/versões/evidências e filtros de grupo/módulo. Vista derivada da [matriz única](matriz-requisitos.csv),sem edição nem estados paralelos;investidor403. Os grupos são editoriais,distintos dos estados canónicos:3199parciais,145não implementados,4decisões,1implementado não ativado,5concluídos de âmbito restrito.
|
||
|
||
Decisões humanas preservadas:pares exatos das6oportunidades com âncoras/clusters;identidade/termos/contactos do operador;URLs/serviços/responsáveis institucionais;modelo/indicadores/baseline de sucesso. Não reabrir aceitação das fontes oficiais;não inventar pares,parâmetros ou score.'''
|
||
insert(docs / 'relatorio-executivo.md', '## Acesso à Gestão de Oportunidades — loteC43/C44,10/10/2026\n\n'+facts+'\n\n'+causes+'\n\n'+evidence+'\n\n'+groups+'\n\nVisual pendente:[roteiro curto](demonstracao-dashboard-oportunidades.md). API/persistência/assets são provas separadas de interface;nenhum clique automatizado/cenárioA/B visual foi alegado.')
|
||
insert(docs / 'backlog.md', '## Prioridade corrente:Gestão de OportunidadesC43 —10/10/2026\n\n'+groups+'''
|
||
|
||
Ordem executável restante:1)incorporar ensaio visualC43 e corrigir reprodução;2)formulário/bindings/condições finais imobiliárias;3)adaptadoresDUAT/transação;4)gates e workflow segregado,sem autoaprovação;5)continuar correspondências/cadastros/mapas,países/origem porformulário e operações documentais independentes. C37 continua pendente,sem repetir login do investidor neste lote;não iniciar jornadas educativas novas. Detalhes/ações por cadaID estão na vista integral.
|
||
|
||
AceitaçãoC43:gestor17/MFA parte de/dashboard→cliques→rascunho→guarda→outra sessão→recupera→edita→arquiva→restaura;feedback/ID/filtro/histórico visíveis;outra conta403;dossier privado e público intactos. CritériosAPI satisfeitos não encerram o critério de interface.''')
|
||
insert(docs / 'casos-reproducao.md', '## Casos adicionaisC43/C44 —10/10/2026\n\n'+causes+'''
|
||
|
||
C43,reprodução de código/assets:seguirPainel do catálogo com gestor→/investidor;na sidebar,grupoGestão→primeiro filho/interests apenas;no/dashboard a criação está nofim e tem labelCriar oportunidade. Esperado:gestor chega ao seu dashboard e encontra Gestão/Nova sem URL decorado;investidor conserva área privada. Observado:links omitidos/destino partilhado/nome diferente. Evidência do utilizador ainda sem URL/conta;não se afirma que o seu perfil é o motivo. Também havia somenteExcluir rascunho no rascunho inicial,com delete→deleted_at em vez dearchive→statusarchived;corrigido separadamente sem alterardelete.
|
||
|
||
C44,reprodução anterior por inspeção:categoriareal_estate disponível,mas payloadreal_estate não fazia parte dos campos validados/persistidos. Esperado:guardar dados parciais e recuperar privadamente. Correção limitada:adaptador24propriedadesPatch;cinco negativos HTTP reais422sem mutação. Não se inventou ensaioHTTP pré-correção nem se declarou o contrato integral concluído.
|
||
|
||
'''+evidence)
|
||
plan = f'''## Sequência adicionalC43/C44 —10/10/2026
|
||
|
||
Preparação apenas;nenhuma ativação autorizada/executada. Fingerprints correntes:percurso`{runtime['code_hash']}`,recursos`{runtime['resource_code_hash']}`,cartografia`{runtime['geometry_code_hash']}`. Provasready anteriores ficam históricas;nenhuma candidata final.
|
||
|
||
1. ConcluirC43/visuaisC37/A-B e consumidores;registar reprodução/correção,fixar revisão+manifestos. Renovar backupDB/ficheiros/chaves/originais e restauro numa novaQA guardada,conferindoIDs/relações/hashes/schema. Não forçar contagens históricas288tabelas/5ficheiros.
|
||
2. Disponibilizar código eassets ativos dessa revisão aprovada,configuração reconciliada e cache conferida. Atalhos/arquivo usam`PORTAL_OPPORTUNITY_DASHBOARD_ACCESS_ENABLED`;estáfalse no ativo e sótrue naQA. **Nenhuma migration nova paraC43 ou primeiro draft imobiliário.**020000já instalada:não repetir. Antes de habilitar,conferir gestor(emailverificado+allowlist),rotas e manifesto realmente servido. Rollback:flagfalse e código/assets compatíveis;preservar drafts/estadoarchived/auditoria.
|
||
3. Recursos:gestorautenticado GET/POST`/management/opportunity-resources-install`somente se030000ausente.3tabelas de associação+1coluna documents+função/3triggers;0recursos/originais criados automaticamente. ClamD/GD exigidos pelas operações binárias afetadas,sem bloquear rascunho/metadados. Downsomente vazio;após uso retirar disponibilidade sem eliminar originais/dados.
|
||
4. Percurso:GET/POST`/management/balcao-install`somente para migrationspendentes190000;2colunas+1definição imutável,0conversões/dossiers/etapas. Disponibilização`INVESTOR_PATH_ENABLED`separada,depois deaceitação/instalação;reversão porflagpreserva19etapas/5fases,IDs/resultados/documentos/consentimentos.
|
||
5. Cartografia:gestor/MFAprévia/crosswalk/hash→aplicar níveis1→2→3 semduplicar. Seativo continuar0 ecorrespondênciasiguais,previsão393limitesinternos=11províncias+128distritos+254postos;0territórios novos,31/157pendentes. Publicação dascamadasseparada. Reversão3→2→1somente novas intactas/não usadas,nem publicadas;guardar originais/hash/crosswalk/receipts e relações.
|
||
6. Contratos especializados:`PORTAL_OPPORTUNITY_SPECIALIZED_DRAFTS_ENABLED`ficafalse no ativo. **Não habilitar com este loteAPI parcial.**Completar formulário/bindings/condições finais/DUAT/transação/workflow e provas porversão/perfil;depois planopróprio na mesma auditoria. Desligarflag conservaJSON privado;rollback de código deve manter chave/payloads sem descartá-los. Instalar recursos ou importarcartografia não valida/submete/aprova/publica contrato nem ativa cálculo fiscal.
|
||
|
||
Plano detalhado anterior conservado abaixo;aplicação documental ativa autenticada,scan próprio dasderivadas e operação permanenteClamD continuam dependências específicas.
|
||
'''
|
||
insert(docs / 'plano-ativacao.md', plan)
|
||
insert(docs / 'cobertura-percursos-i0-i3.md', '## Cobertura adicional:dashboard e draft imobiliário —10/10/2026\n\n'+evidence+'\n\nGestão desde/dashboard:API/destinos reais/gravação/novasessão/recuperação/arquivo/restauro demonstrados;interfacepending. Formulário especializado imobiliário ausente;24campos dePatch são adaptaçãoAPI parcial. Nenhuma cobertura cartográfica/países/origem/documental anterior promovida por esses ensaios. Gestor17/MFA distinto do investidor18;C37 eA/B visuais permanecem abertos.')
|
||
insert(docs / 'execucao-percurso-i1-i3.md', '## Continuação independenteC43/C44 —10/10/2026\n\n'+facts+'\n\n'+evidence+'\n\nRevisão atual não candidata;nenhuma aceitação integralI1–I3 por contagem de testes. Cadastro básico de oportunidades não é dossier privado;operaçãoQA13 não criou dossier/etapa nem alterou as6oportunidades publicadas. Rascunho imobiliárioQA14 não é decisão externa nem contrato completo.')
|
||
insert(root / 'docs/investmoz/v2/gestao-oportunidades-dashboard.md', '## Estado corrente:acesso ao dashboardC43 —10/10/2026\n\n'+causes+'\n\n'+facts+'\n\n[Ensaio desde o dashboard](auditoria-portal/demonstracao-dashboard-oportunidades.md),[matriz única](auditoria-portal/matriz-requisitos.csv),[pedidos abertos/backlog](auditoria-portal/backlog.md),[evidências](auditoria-portal/relatorio-executivo.md). API/persistência/assetsQA demonstrados;visual eativação pendentes.393geometrias e schema110defs não encerram o cadastro funcional.')
|
||
path = private / 'investor-path-evidence.json'
|
||
evidence_json = json.loads(path.read_text())
|
||
evidence_json['code_hash'] = runtime['code_hash']
|
||
evidence_json['resource_code_hash'] = runtime['resource_code_hash']
|
||
evidence_json['geometry_code_hash'] = runtime['geometry_code_hash']
|
||
evidence_json['dashboard_increment'] = {'cases': ['C43', 'C44'], 'qa_proofs': ['dashboard-opportunities-http-qa.json', 'dashboard-manager-mfa-http-qa.json', 'dashboard-navigation-catalogue-qa.json', 'real-estate-draft-http-qa.json', 'dashboard-real-estate-qa.xml'], 'visual_passed': False, 'active_enabled': False, 'canonical_matrix_requirements': 3354, 'open_requirements': 3349}
|
||
for key in ['integrated_ui_ab_passed', 'candidate_revision_fixed', 'activation_ready', 'active_activation_authorized', 'c37_browser_acceptance_passed']:
|
||
evidence_json[key] = False
|
||
evidence_json['current_active_backup_compatibility_renewal_required'] = True
|
||
path.write_text(json.dumps(evidence_json, indent=2, ensure_ascii=False), encoding='utf-8')
|
||
print(json.dumps({'canonical_matrix_preserved': True, 'current_reports_updated': 7, 'open_requirements': projection['open_requirements'], 'active_writes': 0}))
|