"""Record verified destination results; no SQL, credential extraction or CSV authoring.""" from pathlib import Path import csv import hashlib import json import sys from collections import Counter from datetime import datetime, timezone csv.field_size_limit(10_000_000) ROOT = Path(__file__).resolve().parents[1] PRIVATE = ROOT / 'storage/app/private/investmoz-v2/portal-audit' OUT = ROOT / 'outputs/investmoz-workflow-activation-20261011' DOCS = ROOT / 'docs/investmoz/v2/auditoria-portal' CANDIDATE = ROOT / 'outputs/investmoz-workflow-consolidated-20261011' REV = '41caea0f900fe0705e84e065a65f9534ff3a585ee34098f860666f522875a3a5' ZIP_HASH = '1d6dece89817459f012909f309f688e85e40752e845469855b2dce101879c102' MANIFEST_HASH = '092ea57b5eeecef8ae1c44f4c1a8dd6c95d63af5e4448524c46a9e251b1d9b63' def read(name): return json.loads((PRIVATE / name).read_text(encoding='utf-8-sig')) def write(path, value): path.write_text(json.dumps(value, ensure_ascii=False, indent=2) + '\n', encoding='utf-8') def digest(path): return hashlib.sha256(path.read_bytes()).hexdigest() def rows(): with (DOCS / 'matriz-requisitos.csv').open(encoding='utf-8-sig', newline='') as f: return list(csv.reader(f)) mode = sys.argv[1] if len(sys.argv) > 1 else 'prepare' assert mode in ('prepare', 'finalize') assert digest(CANDIDATE / 'investmoz-workflow-41caea0f900f.zip') == ZIP_HASH assert digest(CANDIDATE / 'manifesto.json') == MANIFEST_HASH schema = read('workflow-activation-bootstrap-verified.json') web = read('workflow-activation-web-proof.json') browser = read('workflow-activation-browser-completed-proof.json') prior_browser = read('workflow-activation-browser-before-controller-recovery.json') services = read('workflow-activation-services-resumed.json') backup = read('workflow-execution-target-backup.json') queue = read('workflow-execution-active-queue.json') ls = json.loads((ROOT / 'storage/logs/workflow-localservice-preflight.json').read_text()) assert schema['result'] == web['result'] == ls['result'] == 'passed' assert schema['revision'] == web['revision'] == browser['revision'] == services['revision'] == REV assert schema['superuser_pair'] == dict(id=1, first_user_id=13, second_user_id=2, approved_by=2, version=1) assert schema['sequences_compared'] == 31 and schema['new_sequences'] == 0 assert browser['criteria']['second_holder_confirmed_with_own_MFA'] assert browser['criteria']['first_holder_cannot_confirm'] assert services['worker_enabled'] and services['worker_first_run_result'] == 0 assert queue['pending_by_class'] == [] and queue['failed_jobs'] == 0 assert not queue['effective_notifications_enabled'] and queue['configured_notification_recipient_count'] == 0 assert not schema['operational_flags_enabled'] and schema['COUNTRY02_enabled'] assert backup['restore_verified'] and backup['files_verified'] and backup['file_count'] == 867 OUT.mkdir(exist_ok=True) if mode == 'prepare': evidence = dict( at=schema['at'], revision=REV, target='https://portal-investidor.test / investemoz:5432', technical_execution='completed', operational_flows='disabled_pending_designation', package=dict(sha256=ZIP_HASH, manifest_sha256=MANIFEST_HASH, code_files=22, build_assets=159), backup=dict(verified_at=backup['verified_at'], source_database='investemoz', source_port=5432, restored_target=backup['restored_target'], tables_before=288, sequences=31, files=867, original_files=4, restore_and_bytes_verified=True, Windows_DACL_restore_applied=False), destination_schema=schema, scanner_and_permissions=ls, worker=dict(principal='S-1-5-19', enabled=True, first_run_result=0, queue='default', interval_seconds=60, execution_limit_seconds=180, lease_seconds=210, memory='256M', commands=services['commands'], actual_documentary_jobs_processed=0, actual_documentary_pipeline='pending_legitimate_activity'), browser=dict(criteria=browser['criteria'], holder_order=browser['holder_order'], navigation=prior_browser['navigation'] + browser['navigation'], cookie_attributes=browser['cookie_attributes'], secure_context=True, TLS_bypass=False, mixed_content=browser['mixed'], application_page_errors=browser['errors'], loaded_asset_count=len(browser['assets']), loaded_assets_match_candidate=True, credentials_or_codes_recorded=False), web=web, final_queue=dict(at=queue['at'], pending_by_class=[], failed_jobs=0, external_notifications_enabled=False, configured_recipients=0), qa_evidence_reused=['outputs/investmoz-workflow-consolidated-20261011/relatorio-consolidacao.md', 'outputs/investmoz-service-followup-20261011/relatorio.md'], excluded=['190000', '050000 reapplication', 'operational role grants', 'organizations or representations', 'cartography or library imports', 'publications', 'individual sharing', 'restoration', 'experimental modules and offers', 'SLA'], reversal='Containment only; preserve HTTPS, COUNTRY02, schema, data and history. Full restore requires separate decision.' ) assert evidence['browser']['mixed_content'] == [] and evidence['browser']['application_page_errors'] == [] write(OUT / 'evidencias-destino.json', evidence) report = f'''# Resultado técnico da intervenção autorizada **Candidata 41caea0f900f disponibilizada no destino. B1/B2, 030000 → 040000 e bootstrap cruzado concluídos. Fluxos operacionais desabilitados. COUNTRY02 preservado ativo.** Verificação final: {schema['at']}. Código 117d2d889701 e pacote imutáveis: 22 ficheiros de código / 159 assets. ZIP SHA-256 `{ZIP_HASH}`. Manifesto SHA-256 `{MANIFEST_HASH}`. Nenhuma alteração adicional ao produto nem recompilação nesta execução. Os ajustes efetuados nos controladores de ensaio não integram o payload. ## Resultado por ação | Ação | Resultado efetivo no destino | Evidência / limite | | --- | --- | --- | | Backup/restauro | Backup da base real renovado às 17:12:20 UTC, fisicamente restaurado e comparado no clone 55441. 288 tabelas, 31 sequências, 867 ficheiros e 4 originais | Válido antes das ações HTTP. O restauro ocorreu no clone, sem substituir a base ativa. Metadados de ACL/tarefas recuperados; DACLs restauradas não foram aplicadas no Windows | | Código/bundle | 181 ficheiros correspondem ao manifesto fixo; .env, dependências, chave/cifra, TLS e cookie preservados | Recursos realmente carregados pelo Chromium também conferidos por hash | | B1 ClamD | ClamAV 1.5.4 x64, 127.0.0.1:3310, LocalService, assinaturas oficiais 28150 de 11/10/2026 | Atualização e recarga reais; scan limpo e malware detetado em memória. Nenhuma importação/publicação | | B2 permissões | Leitura da configuração e dos 4 originais, acesso ao scanner e escrita nas áreas autorizadas | Sob LocalService: escrita recusada em código/vendor/config/.env e leitura recusada em controlos privados alheios. Outros titulares/owners preservados | | B2 PHP/HTTPS | Apache PHP 8.5.11, upload 20M / POST 24M / memória 256M / execução 180s; GD/WebP presentes | Chromium com certificado reconhecido, sem ignorar TLS. Upload temporário de 3 MiB e 20 MiB aceite; 21 MiB recusado por PHP com 422; nova tentativa 3 MiB aceite. Nenhum registo de utilizador criado | | Apache/vhosts | Configuração validada e recarga graciosa observada; HTTPS do portal 200, HTTP → HTTPS 308, localhost HTTP 200 | Controlo Laragon não recarregou a instância iniciada fora dele. O responsável autorizou expressamente o mecanismo próprio de recarga graciosa; nenhum término forçado | | 030000 | Aplicada uma vez pela conta 2, pela interface autenticada | 3 tabelas e 1 coluna. Auditoria `opportunity_resources_installed` | | 040000 | Aplicada uma vez pela conta 13, após 030000, pela interface autenticada | 4 tabelas e 4 colunas. Auditoria `install`. Prévias/backup/fingerprints correspondiam; sem migrate geral | | Worker | LocalService, fila default, cadência 60s, IgnoreNew, PT3M, lease 210s, memória 256M; primeira execução 0 | Fila relida imediatamente antes: vazia, destinatários 0, notificações OFF. Nenhum job ativo consumido. O ensaio completo documental e a recuperação após interrupção permanecem provas distintas do clone | | Bootstrap | Pedido pela conta 13; confirmação pela conta 2 com sessão/MFA próprios; uma dupla versão 1 | Prévia do primeiro titular não permite confirmar. Interface apresentou o sucesso. Pedido consumido e três auditorias próprias, sem novo utilizador/grant operacional | [Evidências sanitizadas por critério](evidencias-destino.json). [Procedimento executado e contenção](procedimento-executado.md). [Designações operacionais pendentes](designacoes-operacionais.md). [Manifesto de execução](manifesto-execucao.json). ## Preservação e correspondência da base Resultado aditivo: **288 → 291 → 295 tabelas, 5 colunas, zero novas sequências**. As 288 tabelas anteriores foram comparadas com o restauro: 283 sem alteração de dados, cache/sessões com mudanças normais de autenticação e migrations/audit_events com apenas acréscimos autorizados. As 31 sequências foram conferidas; só a sequência de migrations avançou pelas duas instalações. Os 4 originais e os 2 envelopes MFA permanecem iguais por bytes. Mantidos 13 utilizadores, 0 organizações, 0 representações/memberships, 4 documentos e 6 oportunidades. Acrescentados apenas o schema autorizado, um pedido de segurança consumido, uma dupla de titulares e cinco eventos de auditoria. 050000 não foi reaplicada; 190000 permanece ausente. Fila final: 0 jobs / 0 failed_jobs. Não se registaram credenciais, códigos ou valores de cookies nas evidências. ## Pendências que condicionam a utilização operacional 1. Designar Promotores, Validadores e Publicadores em contas existentes, com organização/representação legítima, tipos, âmbito e responsabilidade. Os Superutilizadores 2/13 não recebem esses papéis automaticamente nem leitura universal de anexos. 2. Executar a primeira atividade documental legítima quando houver atores/âmbitos: envio → fila → scan → derivadas → recuperação autorizada. A recuperação após falha e ausência de duplicações já foram demonstradas no clone; não atribuir essa prova ao destino vazio nem inserir dados fictícios no ativo. 3. COUNTRY02 continua instalado/ON. A gravação real do país mestre permanece dependente de uma organização legítima e de representação autorizada. A falta dessas entidades não impediu a instalação técnica. 4. Restauração e partilha individual continuam desabilitadas. 190000, cartografia/acervo, legado, ofertas, competências modulares e SLA não foram ativados. Dispositivos reais/acessibilidade integral mantêm os critérios próprios. Esta intervenção não reabre nem repete A/B, C37 ou os percursos QA sem alteração relevante. Não declara a auditoria global nem a Gestão de Oportunidades operacionais concluídas. Mantém cinco fases/19 etapas e as decisões aprovadas. As propostas e relatórios anteriores permanecem referências históricas. ## Ocorrências técnicas durante a execução O controlador antigo não lia o payload DOM do Inertia 3 e perdeu o controlo do primeiro Chromium. Foi corrigida a leitura do controlador de ensaio, sem mudança no produto. 030000 já instalada foi recuperada por ledger/auditoria, sem repetição. A nova sessão foi identificada efetivamente como conta 13 e aproveitada para 040000/pedido; a conta 2 confirmou separadamente. Um comando JSON com BOM interrompeu apenas a continuação do controlador; o comando foi normalizado e a mesma sessão recuperada, sem repetir login ou instalação. Esses erros de instrumentação não foram classificados como falhas da autenticação do portal. ## Reversão Contenção preserva HTTPS/cookie, chave/cifra, COUNTRY02, originais, colunas e histórico. Desabilitar apenas a supervisão/fluxos deste pacote pelos controlos próprios, conservando jobs/quarentena para diagnóstico. Existem o backup pré-intervenção de 867 ficheiros, suplemento de 10 ficheiros e exportações das ACLs exatamente afetadas (21 árvores e 27 raízes/owners). Não repor leitura excessiva de LocalService nem regredir assinaturas válidas. Depois do bootstrap não executar down/drop nem regressar automaticamente ao código com cerimónia antiga. Não executar key:generate, purge, retry all ou restauro completo. **Restauro completo requer decisão separada e reconciliação de escritas posteriores.** ''' (OUT / 'resultado.md').write_text(report, encoding='utf-8') procedure = '''# Procedimento executado e recuperação disponível 1. Conferidos candidata 41caea0f900f, ZIP/manifesto, investemoz:5432 e backup/restauro do destino de 17:12:20 UTC. Exportados objetos de serviço/ACL antes das mudanças. 2. Disponibilizados exclusivamente 22 ficheiros de código e 159 assets autorizados; COUNTRY02 ON, restantes fluxos OFF; chave/cifra/.env/dependências/TLS preservados. 3. Atualizados scanner 3310 e assinaturas 28150. Alinhadas tarefas LocalService; verificados direitos positivos e negativos com a identidade real. Worker inicialmente OFF. 4. Aplicados limites só ao vhost HTTPS; sintaxe validada. Como Laragon não recarregou a instância existente, o responsável autorizou a recarga graciosa própria do Apache. Filho substituído sem término forçado; três vhosts e PHP web conferidos no Chromium com TLS reconhecido. 5. 030000: prévia correspondente e ação HTTP autenticada da conta 2. Ledger e auditoria confirmados. Não repetir a instalação. 6. 040000: nova prévia com dependência 030000 e backup correspondentes; ação HTTP autenticada da conta 13. Ledger e auditoria confirmados. Não executar migrate geral. 7. Leitura imediatamente antes do worker: zero jobs/falhas, notificações OFF e zero destinatários. Habilitada a tarefa própria supervisionada; execução inicial terminada com 0. Não enfileirados ensaios sintéticos no ativo. 8. Conta 13 apresentou pedido de bootstrap com MFA. Conta 2 entrou em contexto de navegador separado e confirmou com o seu MFA. Conferidos IDs/alvo/hash/validade, uma dupla, pedido consumido e auditoria. Conta 13 não podia confirmar o próprio pedido. 9. Comparados novamente schema/linhas/sequências/4 originais/2 envelopes MFA contra o restauro. Encerrados Chromium e controladores temporários. Serviços autorizados permanecem supervisionados; fluxos operacionais OFF, COUNTRY02 ON. ## Contenção em caso de falha Desabilitar a tarefa **InvestMoz Portal Documentary Worker** pelo Agendador, preservando fila e originais. Manter flags operacionais OFF. Corrigir somente o consumidor afetado e recuperar o job específico após diagnóstico; não usar purge/retry all. Scanner e HTTPS mantêm a proteção. A tarefa worker está protegida contra alteração por utilizador sem administração do Windows. Repor configurações/tarefas/ACLs apenas nos objetos exportados e com o processo próprio preparado. Conferir sintaxe e vhosts antes de recarga. Conservar COUNTRY02 e o novo schema/histórico; o bootstrap já usado impede tratar down vazio do clone como reversão ativa. O backup anterior é a referência preservada de recuperação, não uma ordem de restaurar o ativo. Restauro completo e regressão de código incompatível exigem decisão separada. ## Abertura operacional separada Preencher designações-operacionais.md com contas/organizações/representações/tipos/âmbitos reais. As concessões e a habilitação dos fluxos exigem o mecanismo e a decisão próprios. Nenhum dado ou responsável foi inventado para demonstração. 190000 só entra na entrega do percurso integrado; não bloqueou o schema deste workflow isolado. ''' (OUT / 'procedimento-executado.md').write_text(procedure, encoding='utf-8') designations = '''# Titulares e designações operacionais | Conta existente | Papel | Organização/âmbito | Responsabilidade | Estado | | --- | --- | --- | --- | --- | | 13 — onala@me.com | Superutilizador titular | Administração de segurança | Apresentou o pedido com MFA; não confirmou o próprio pedido | Inicializado no destino | | 2 — nala@tempo.co.mz | Superutilizador titular | Administração de segurança | Confirmou independentemente com MFA em sessão separada | Inicializado no destino | | A preencher | Promotor | Organização/representação legítima, tipos e âmbito | Criar/coeditar/corrigir/submeter conforme autorização | Pendente; fluxo OFF | | A preencher | Validador | Organização/âmbito e tipos | Revisão independente, correção/rejeição/aprovação fundamentadas | Pendente; fluxo OFF | | A preencher | Publicador | Organização/âmbito, tipos e visibilidade | Publicar/suspender no âmbito autorizado | Pendente; fluxo OFF | O responsável confirmou que os dois titulares são pessoas diferentes. Para os papéis operacionais indicar apenas conta existente, organização/representação legítima, tipos, âmbito e responsabilidade. Não são necessárias passwords ou informações MFA. Não acumular papéis de forma a contornar a revisão independente. A administração de segurança não concede acesso universal aos anexos nem atribui automaticamente papéis operacionais. O destino permanece com zero organizações/memberships. A criação legítima e representação devem seguir o fluxo autorizado próprio. A configuração técnica está instalada; a abertura dos fluxos continua separada. Restauração, partilha individual, modulares/ofertas/SLA e 190000 permanecem fora. ''' (OUT / 'designacoes-operacionais.md').write_text(designations, encoding='utf-8') current = rows() headers = current[0] idx = headers.index('Evidência funcional') addition = { 'AUD-OPS-01': 'Intervenção autorizada 41caea0f900f concluída no destino em 11/10/2026: backup/restauro real 17:12:20 UTC (288 tabelas/31 sequências/867 ficheiros/4 originais) conferido; ClamD3310/LocalService/assinaturas28150, permissões efetivas e PHP web20M/24M/256M/GD/WebP demonstrados. Worker supervisionado habilitado após nova leitura da default vazia/notificações OFF, primeira execução0. Processamento documental legítimo no destino permanece pendente; provas completas/falha/repetição do clone conservadas. Evidência: outputs/investmoz-workflow-activation-20261011/resultado.md e evidencias-destino.json.', 'AUD-PROFILE-15': 'Bootstrap cruzado efetivamente executado no destino: titular13 apresenta e titular2 confirma, pessoas independentes designadas, sessões/MFA próprios; prévia do autor não permite confirmar, uma dupla versão1 e pedido consumido com auditoria. Nenhuma conta/organização/representação/grant operacional criado. Papéis operacionais por designar com organização/tipos/âmbito; fluxos OFF. Evidência: outputs/investmoz-workflow-activation-20261011/designacoes-operacionais.md e evidencias-destino.json.', 'AUD-PROFILE-31': 'Candidata41caea0f900f e payload181 imutáveis disponibilizados no destino:030000 autenticada por2 e040000 autenticada por13, uma vez e na ordem, com prévias/hash/backup correspondentes e auditoria. Schema288→291→295,7tabelas/5colunas/0novas sequências, dados/originais/cifra/histórico preservados; COUNTRY02/050000 preservados,190000 ausente. Bootstrap13→2 concluído; restauração/partilha individual e fluxos operacionais OFF. Contenção preserva schema/dados/HTTPS; restauro completo separado. Evidência: outputs/investmoz-workflow-activation-20261011/resultado.md e procedimento-executado.md.' } updates = {} for row in current[1:]: if row[0] in addition: assert '[Execução no destino 41caea0f900f]' not in row[idx] updates[row[0]] = {'Evidência funcional': row[idx] + '\n\n[Execução no destino 41caea0f900f] ' + addition[row[0]]} assert len(updates) == 3 write(PRIVATE / 'workflow-activation-matrix-baseline.json', dict(rows=current, updates=updates)) block = ''' ## Execução técnica autorizada no destino — 41caea0f900f **Código/bundle, B1/B2, 030000 → 040000 e bootstrap cruzado concluídos no destino. COUNTRY02 preservado ON; fluxos operacionais OFF.** [Resultado e limites](../../../../outputs/investmoz-workflow-activation-20261011/resultado.md), [provas sanitizadas](../../../../outputs/investmoz-workflow-activation-20261011/evidencias-destino.json), [procedimento executado/reversão](../../../../outputs/investmoz-workflow-activation-20261011/procedimento-executado.md) e [designações](../../../../outputs/investmoz-workflow-activation-20261011/designacoes-operacionais.md). Pacote/code/manifesto41caea0f900f/117d2d889701 preservados. Backup do destino de17:12:20UTC restaurado/verificado no clone:288 tabelas/31sequências/867ficheiros/4originais. No destino, somente030000 pela conta2 e040000 pela conta13, por ações HTTP autenticadas:288→291→295tabelas/5colunas/0novas sequências. Auditoria sem duplicações. Bootstrap:pedido13/confirmação2, sessões/MFA próprios, uma dupla/um pedido consumido. Zero novas identidades/organizações/representações ou concessões operacionais. ClamD3310/LocalService/assinaturas28150 e ACLs positivas/negativas demonstrados. PHPweb20M/24M/256M/180s/GD/WebP e trêsvhosts verificados no Chromium com TLS reconhecido. Recarga própria graciosa do Apache expressamente autorizada após Laragon não recarregar a instância fora dele. Worker supervisionado habilitado após releitura da default vazia/notificações OFF; primeira execução0. O processamento documental completo/falha/repetição continua prova distinta do clone; no destino falta atividade documental legítima. Dados das288tabelas anteriores,4originais/2envelopesMFA eCOUNTRY02 preservados. **Pendências operacionais:** designarPromotor/Validador/Publicador com contaexistente,organização/representação legítima,tipos/âmbito/responsabilidade; abertura dos fluxos separada. País mestre real aguardará organização legítima. Restauração/partilha individual,190000,cartografia/acervo/legado,modulares/ofertas/SLA continuam fora. A/B/C37 e provas QA válidas preservadas, sem repetição. Contenção preservaHTTPS/cifra/COUNTRY02/schema/histórico; restauro completo exige decisão separada. Mesma matriz:3401requisitos/linhas,7739ocorrências, apenas3evidências complementadas; zero novosIDs/fontes e estados gerais preservados. Os blocos seguintes são históricos; as instalações e o bootstrap neles referidos como pendentes foram concluídos neste âmbito técnico. ''' for name in ['relatorio-executivo.md', 'backlog.md', 'plano-ativacao.md', 'workflow-criterios-saida-20261011.md']: file = DOCS / name text = file.read_text(encoding='utf-8') assert '' not in text file.write_text(block + text, encoding='utf-8') print(json.dumps(dict(result='records_prepared', matrix_authoring_pending=True, revision=REV))) else: baseline = read('workflow-activation-matrix-baseline.json') current = rows() assert len(current) == len(baseline['rows']) == 3402 differences = [] for before, after in zip(baseline['rows'], current): assert len(before) == len(after) for col, (old, new) in enumerate(zip(before, after)): if old != new: assert before[0] in baseline['updates'] and current[0][col] == 'Evidência funcional' assert new == baseline['updates'][before[0]]['Evidência funcional'] differences.append(dict(id=before[0], column=current[0][col])) assert len(differences) == 3 proof = read('workflow-activation-matrix-proof.json') assert proof['states_unchanged'] and proof['sources_and_versions_unchanged'] state_column = current[0].index('Estado') states = dict(Counter(row[state_column] for row in current[1:])) files = {name: digest(OUT / name) for name in ['resultado.md', 'evidencias-destino.json', 'procedimento-executado.md', 'designacoes-operacionais.md']} manifest = dict(at=datetime.now(timezone.utc).isoformat(), revision=REV, code='117d2d8897012e25bf2efc7a6c589dfb47c58b4a52a1e28331512b935ca00d44', candidate_zip_sha256=ZIP_HASH, immutable_candidate_manifest_sha256=MANIFEST_HASH, product_delta_this_execution=False, product_files=181, target='investemoz:5432', technical_execution='completed', operational_flows_enabled=False, COUNTRY02_enabled=True, resources_installed=True, profiles_installed=True, bootstrap_holder_ids=[13, 2], artifacts=files, matrix=dict(rows=3401, source_occurrences=7739, states=states, changes=differences, new_ids=0, source_and_version_changes=0, sha256=digest(DOCS / 'matriz-requisitos.csv'))) write(OUT / 'manifesto-execucao.json', manifest) print(json.dumps(dict(result='execution_recorded', revision=REV, states=states, changed_cells=3, operational_flows_enabled=False), ensure_ascii=False))