Files
Investidor-V2/tools/portal-consolidated-delivery.py
T
nala 287e991486
tests / ci (push) Waiting to run
oportunidades 7
2026-10-13 11:40:29 +02:00

252 lines
32 KiB
Python

"""Seal a new consolidated QA candidate, preserving every previous delivery."""
from pathlib import Path
from datetime import datetime, timezone
from collections import Counter
import json,hashlib,zipfile,shutil,csv
R=Path(__file__).resolve().parent.parent; P=R/'storage/app/private/investmoz-v2/portal-audit'
O=R/'outputs/investmoz-workflow-consolidated-20261011'
assert not O.exists(), 'Preserve a sealed candidate; never overwrite it'
O.mkdir()
load=lambda p:json.loads(p.read_text(encoding='utf-8-sig'))
sha=lambda p:hashlib.sha256(p.read_bytes()).hexdigest()
write=lambda p,obj:p.write_text(json.dumps(obj,indent=2,ensure_ascii=False),encoding='utf-8')
prior=load(R/'outputs/investmoz-workflow-upgrade-20261011/manifesto.json')
delta=load(R/'outputs/investmoz-service-followup-20261011/manifesto-delta-qa.json')
code=load(P/'service-followup-code.json'); build=load(P/'service-followup-production-build.json')
plan=load(P/'service-followup-latest.json'); S=Path(plan['source'])
backup=load(P/'consolidated-backup-restoration-qa.json'); local=load(P/'consolidated-localservice-proof.json')
accounts=load(P/'consolidated-designations-readonly.json'); reconciliation=load(P/'consolidated-191-reconciliation.json')
queue=load(P/'service-followup-active-queue-readonly.json')
assert code['code_revision'].startswith('117d2d889701') and len(code['code_files'])==22 and len(build['assets'])==159
assert backup['code_revision']==code['code_revision'] and backup['file_count']==191 and backup['restore_verified']
assert local['result']=='passed' and local['principal_sid']=='S-1-5-19' and local['own_task_removed']
assert [(r['id'],r['email']) for r in accounts['accounts']]==[(2,'nala@tempo.co.mz'),(13,'onala@me.com')]
assert all(r['exists_in_destination'] and r['email_verified'] and r['mfa_confirmed'] and r['current_legacy_manager_authorized'] for r in accounts['accounts'])
payload=dict(code['code_files'])
payload.update({'public/build/'+key:value for key,value in build['assets'].items()})
for key,value in payload.items(): assert sha(S/key)==value, key
assert len(payload)==181
services=O/'servicos'; services.mkdir()
old_services=R/'outputs/investmoz-workflow-service-plan-20261011'
for name in ['InvestMoz-ClamAV-Loopback-Scanner.xml','InvestMoz-ClamAV-Signature-Update.xml',
'InvestMoz-Portal-Documentary-Worker.xml','freshclam.conf','portal-documentary-vhost-limits.conf']:
# Resolve only existing names in the immutable plan; no invented configuration.
matches=list(old_services.glob(name))
if not matches:
patterns={'freshclam.conf':'*freshclam*','portal-documentary-vhost-limits.conf':'*vhost*'}
matches=list(old_services.glob(patterns.get(name,name)))
assert len(matches)==1, name
shutil.copyfile(matches[0], services/matches[0].name)
changes=load(old_services/'alteracoes-servicos.json')
changes['status']='consolidated_proposal_not_authorized_not_executed'
changes['application_code_delta']=list(code['delta_files'])
changes['production_rebuild_required']=True
changes['production_rebuild_status']='Already completed in isolated QA; exact 159-asset bundle included'
changes['candidate_unchanged']={'historical_reference':prior['revision'],'preserved':True}
changes['planned_changes']['acl']['neutralize_inherited_excess_rights_required']=True
changes['planned_changes']['acl']['negative_acceptance']=['LocalService cannot write code/vendor/config/.env',
'LocalService cannot read unrelated private controls', 'Preserve all other authorized principals and export ACLs for scoped reversal']
changes['planned_changes']['acl']['scope']='Protect the targeted runtime DACLs from excess inherited LocalService rights; grant Modify only to operational runtime and scanner data/logs, never the whole project'
changes['planned_changes']['acl']['modify']=['Operational document/quarantine/scan temporary directories and storage framework/logs only; exclude private audit controls/backups/runtime binaries', 'bootstrap/cache', 'ClamAV database and logs of the installation serving3310']
changes['planned_changes']['notifications']={'enabled':False,'recipients':0,'must_remain_disabled':True}
changes['planned_changes']['worker']['fresh_queue_read_immediately_before_enable']=True
changes['planned_changes']['worker']['stop_on_classes']=['unknown','App\\Jobs\\NotifyInterestReceived']
changes['tests']['performed'] += ['Real LocalService SID S-1-5-19: configuration read, QA scanner13310, four queued scans, fifth empty repetition, positive/negative ACLs', 'Crossed bootstrap Chromium/MFA and pending-request new-session recovery; proof reused with exact code/build hashes', 'QA physical restoration renewed:295tables31sequences191files9MFA']
changes['tests']['pending_before_destination']=[]
changes['tests']['coverage_limit']='180-second hard deadline and210-second recovery proved under interactive QA; service identity processing/ACLs now proved separately. No claim of target installation.'
changes['bootstrap']={'approved_rule':'Exactly two active holders; independent replacement and operational elevation',
'third_initial_actor_explicitly_required_by_specification':False,
'historical_destination_code_requires_three_distinct_accounts':True,
'consolidated_candidate_requires_third_initializer':False,
'QA_ceremony':'First holder requests; second holder confirms separately with MFA, atomic receipt and audit',
'pre_initialization_authority':'Verified existing legacy manager for request; purpose-scoped confirmed-MFA access for designated second holder',
'user_designated_existing_destination_accounts':[{'id':2,'email':'nala@tempo.co.mz'},{'id':13,'email':'onala@me.com'}],
'names_designated':True,'activation_authorized':False,'destination_privileges_changed':0}
write(services/'alteracoes-servicos.json',changes)
acl='''# ACL de LocalService: alteração proposta, não aplicada no destino
Exportar as DACLs dos objetos afetados, respetivos proprietários e ACLs dos ancestrais antes da intervenção. O ensaio QA aplicou proteção de herança na árvore própria: S-1-5-19 com RX; proprietário, Administradores e SYSTEM mantiveram os direitos de controlo. Modify foi concedido apenas a storage, bootstrap/cache e diretório de dados/logs do scanner. Código, vendor, configuração e .env recusaram escrita; uma sentinela sintética de controlo recusou leitura.
No destino preservar também os direitos existentes do Apache e dos operadores autorizados. Adicionar apenas uma ACE RX não é suficiente se um grupo herdado já conceder escrita: a prévia deve calcular os direitos efetivos de LocalService e neutralizar as concessões excessivas nesse âmbito, sem retirar direitos aos restantes principais. Não aplicar uma ACL QA indiscriminadamente ao projeto ativo.
| Objeto | Direito efetivo máximo de LocalService |
| --- | --- |
| app, vendor, config, routes, resources, database, public/build e binários PHP/ClamAV | Leitura/execução; sem escrita, remoção, alteração de ACL ou posse |
| .env e configuração necessária do scanner | Leitura; sem alteração; chave estável preservada |
| storage operacional: documentos/quarentena, temporários de scan, cache, views e logs | Modify apenas nos diretórios necessários, sem conceder leitura aos controlos privados de contas, backups, MFA ou evidências alheias |
| bootstrap/cache | Modify, preservando as regras do restante bootstrap |
| base de assinaturas e logs da instalação ClamAV que serve 3310 | Modify; runtime/binários e configurações permanecem RX |
| controlos privados, ficheiros de credenciais QA, backups e acervo alheio ao processamento | Nenhuma concessão adicional; negar acesso efetivo excessivo no âmbito da prévia |
O projeto guarda atualmente o runtime ClamAV e controlos de auditoria sob storage/app/private/investmoz-v2/portal-audit. Não conceder Modify recursivo a todo storage: isso abrangeria esses binários, configurações e ficheiros de controlo. Separar a prévia por diretório real, incluindo os diretórios de temporários na raiz privada, e testar direitos positivos/negativos sob S-1-5-19 antes de habilitar o worker. Se os direitos efetivos não coincidirem com esta tabela, manter a tarefa OFF e corrigir a ACL proposta antes de executar.
A conta é um principal Windows partilhado entre serviços. O teste demonstra o âmbito QA e não certifica as ACLs atuais do destino. A futura intervenção requer revisão e aplicação desta prévia específica; nenhum direito foi concedido no ativo.
'''
(services/'acl-localservice-proposta.md').write_text(acl,encoding='utf-8')
service_hashes={p.relative_to(O).as_posix():sha(p) for p in sorted(services.iterdir())}
basis={'previous_candidate':prior['revision'],'integrated_delta':code['code_revision'], 'payload':payload,
'service_proposal':service_hashes,'categories':prior['included_categories'],
'unavailable':prior['unavailable'], 'holders_designated':[{'id':r['id'],'email':r['email']} for r in accounts['accounts']],
'install_order':['030000','040000'],'country050000_preserved':True,'external_notifications':False,
'activation_authorized':False}
revision=hashlib.sha256(json.dumps(basis,sort_keys=True,separators=(',',':'),ensure_ascii=False).encode()).hexdigest()
name='investmoz-workflow-'+revision[:12]+'.zip'
with zipfile.ZipFile(O/name,'w',zipfile.ZIP_DEFLATED) as z:
for key in sorted(payload): z.write(S/key,key)
with zipfile.ZipFile(O/name) as z:
assert len(z.namelist())==181 and not any('.env' in k or '/private/' in k for k in z.namelist())
for key,value in payload.items(): assert hashlib.sha256(z.read(key)).hexdigest()==value
designation=f'''# B3 — titulares indicados pelo responsável
O responsável confirmou os emails nala@tempo.co.mz e onala@me.com depois de a leitura do destino contrariar os IDs iniciais 3/18. Correspondência por leitura em {accounts['at']}, investemoz:5432, sem providers e em transação READ ONLY:
| Conta existente | Papel designado | Organização/âmbito | Condições verificadas |
| --- | --- | --- | --- |
| ID 2 — nala@tempo.co.mz | Titular Superutilizador | Administração do portal; não implica âmbito operacional | Email verificado, MFA confirmado, autorização legada de gestor |
| ID 13 — onala@me.com | Titular Superutilizador | Administração do portal; não implica âmbito operacional | Email verificado, MFA confirmado, autorização legada de gestor |
**Designação registada; nenhum privilégio ou dupla foi criado no ativo.** O titular que iniciar o pedido será A; o outro confirma como B, em sessão própria com MFA recente. Sem terceiro inicializador, sem autoaprovação por conta e sem poderes gerais antecipados. Instalação 040000, pedido, confirmação e concessões operacionais são ações distintas.
Histórico preservado: no destino ID 3 é gestor01@example.test, sem email verificado nem MFA; ID 18 não existe. A confirmação dos emails resolve a identificação, sem mover contas QA ou escolher novas pessoas. A compatibilidade de cifra foi demonstrada no clone com a chave estável; não foram pedidos segredos.
| Conta existente a designar | Papel | Organização/representação | Tipos e âmbito | Responsabilidade |
| --- | --- | --- | --- | --- |
| A preencher pelo responsável | Promotor | Organização legítima + representação, ou atuação individual legítima | Categorias base concretas | Criar/coeditar/submeter/corrigir; não aprovar autoria própria |
| A preencher pelo responsável | Validador | Âmbito funcional real | Tipos e processos autorizados | Revisão independente; conflitos verificados pelo servidor |
| A preencher pelo responsável | Publicador | Âmbito real | Tipos e visibilidade interna/restrita ou pública autorizada | Publicação independente da aprovação; sem republicação automática |
| A preencher quando necessário | Auditor/coordenação/parecer/recurso | Competência, fila ou processo concreto | Âmbito e validade | Respeitar as responsabilidades já reconciliadas; sem sistema de identidades paralelo |
| A preencher pelo responsável | Operador de serviços | Serviços Windows desta intervenção | Scanner/fila/PHP | Responsabilidade técnica; não confere acesso operacional universal |
Não criar organizações, representações ou documentos para demonstrar a ativação. Dois administradores não substituem a designação dos perfis operacionais. O papel de Superutilizador isolado continua sem consulta universal dos anexos; a elevação exige âmbito e aprovação independente. Ofertas, competências modulares e SLA mantêm decisões separadas.
'''
(O/'designacoes-b3.md').write_text(designation,encoding='utf-8')
procedure=f'''# Procedimento único proposto — candidata {revision[:12]}
**Preparado e ensaiado em QA; intervenção e ativação no destino não autorizadas.** Referência preservada 98a8e0b70892. Integração do delta 117d2d889701 em 22 ficheiros de código e 159 recursos de produção (181 entradas no ZIP). Não repetir A/B, C37 ou coedição; verificar somente efeitos da atualização e divergências concretas.
## 1. Pré-condições e uma janela de intervenção
1. Obter decisão sobre esta revisão completa e os serviços B1/B2. Conferir SHA-256 do ZIP **{sha(O/name)}**, manifesto e ficheiros. Comparar os hashes de base; parar perante alteração inesperada. Confirmar alvo investemoz:5432, origem https://portal-investidor.test e COUNTRY02 ON/050000 instalada. Só 030000 e 040000 podem ser instaladas; 190000 fica fora do workflow isolado.
2. Renovar antes da intervenção o backup/restauro **do destino real**, com dump em transação consistente, originais referenciados, chaves/configuração privada, código/bundle, TLS/vhosts, tarefas, ACLs e assinaturas ClamAV. Restaurar somente numa nova base QA e comparar tabelas/seq/hashes/cifra. Associar o resultado a esta revisão/ZIP e aos fingerprints abaixo. Restauro QA de 191 ficheiros não substitui esse passo.
3. Exportar as duas tarefas ClamAV atuais e DACLs. Manter o novo worker OFF. Conferir instalação x64/3310 e consumidores default; notificações externas devem continuar OFF, sem destinatários. Não consumir jobs durante preparação. Não iniciar worker perante classe desconhecida ou NotifyInterestReceived pendente. Resolver o caso específico antes de prosseguir, preservando o job.
## 2. Intervenção B1/B2 agrupada
4. Disponibilizar os 22 ficheiros e bundle de 159 recursos, mantendo as flags do workflow OFF e COUNTRY02 ON. Preservar TLS, cookie, APP_KEY e restantes dados. Não copiar .env, contas, documentos sintéticos ou vendor QA.
5. Pelos controlos normais do Agendador, suspender só as duas tarefas ClamAV identificadas. Confirmar PID/executável/configuração de 3310; se necessário usar SHUTDOWN próprio dessa instância. Alinhar freshclam x64, base e NotifyClamd conforme os ficheiros em servicos. Atualizar assinaturas oficiais; verificar PING/VERSION, recarga, data <48h e scan real. Manter quarentena se falhar. Não atuar sobre 13310/QA.
6. Aplicar a prévia de ACLs específica do destino descrita em servicos/acl-localservice-proposta.md. Neutralizar escrita herdada excessiva de LocalService, preservando Apache/operadores. RX no código/vendor/config/.env/binários; Modify só nos diretórios operacionais e base/logs do scanner. Não conceder Modify a toda a árvore privada de auditoria. Registar tarefas sob S-1-5-19. Provar direitos positivos e negativos antes de habilitar o worker.
7. Aplicar apenas ao vhost HTTPS do portal upload20M, POST24M, memória256M e execução180s. Validar sintaxe e mapa de vhosts; realizar um único reinício pelo Laragon. Verificar portal e vhosts afetados. O ini global e demais vhosts mantêm limites anteriores.
8. Registar o worker **desabilitado**: PHP 8.5.11, `-c php.ini -d memory_limit=256M`, `queue:work database --queue=default --once --tries=3 --timeout=150 --memory=256 --no-interaction`, cadência60s, IgnoreNew e PT3M. PCNTL ausente; o limite externo180s fica abaixo do lease210s. Não omitir o override de memória PHP.
## 3. Somente instalações autenticadas 030000 → 040000
9. Gestor existente, email verificado e MFA normal: GET **https://portal-investidor.test/management/opportunity-resources-install**. Conferir alvo, schema, backup, hash e fingerprint **{backup['resource_fingerprint']}**. POST na mesma rota com hash/confirm; aplicar somente030000 se ausente. Esperado: três tabelas de recursos e documents.storage_encryption. Se já íntegra, recuperar prévia atual e não repetir instalação. Prévia divergente409: interromper antes de qualquer DDL.
10. GET **https://portal-investidor.test/management/profile-install**. Conferir 020000/030000 íntegras, backup e fingerprint atualizado **{backup['profile_fingerprint']}**. POST hash/confirm/idempotency_key/reason; conservar a chave UUID criptográfica na repetição da mesma tentativa. Esperado040000: quatro tabelas de perfis, users.portal_access_revision e três colunas de opportunities. Zero contas/organizações/representações/grants automáticos. Confirmar ledger e auditoria uma vez. Não reaplicar050000 nem instalar190000.
11. Revalidar configuração sem notificações, scanner e direitos de serviço. **Imediatamente antes de habilitar o worker**, renovar a leitura READ ONLY de jobs/failed_jobs, classes/reservas/tentativas e efeitos, sem desserializar comandos. Registar instante/contagens. Parar perante divergência, consumidor desconhecido, NotifyInterestReceived pendente ou notificações habilitadas. Só então habilitar a supervisão. Confirmar processamento normal e recuperar apenas o job identificado em falha; nunca queue:retry all, DELETE ou reenvio com nova identidade.
## 4. Designação cruzada e habilitação dos fluxos
12. Após autorização própria do bootstrap, qualquer um dos titulares indicados ID2/ID13 pode iniciar. POST /management/profile-install/bootstrap com prévia atual/hash/confirm/idempotency_key/first_user_id=autor/second_user_id=outro/reason. O pedido não concede privilégio. Recuperar o pedido pelo link do painel; prazo15min.
13. O outro titular abre **/management/profile-install/bootstrap/{{uuid}}** em sessão própria e MFA recente; confirma por POST **/management/profile-install/bootstrap/{{uuid}}/confirm** com hash/chave estável/confirm/motivo. Dupla, consumo do pedido e auditoria são atómicos. Autor não confirma; não há terceiro gestor exclusivo. Em expiração/código diferente, recuperar uma nova prévia e tratar o conflito, sem contornar MFA.
14. Atribuir perfis operacionais só a contas e âmbitos legitimamente designados, pelo fluxo existente e com auditoria. Preservar representação, tipos e segregação criação/revisão/publicação. Habilitar PORTAL_PROFILE_ACCESS_ENABLED, PORTAL_OPPORTUNITY_DASHBOARD_ACCESS_ENABLED e PORTAL_OPPORTUNITY_SPECIALIZED_DRAFTS_ENABLED apenas no âmbito futuro autorizado e operacionalmente completo. Administração instalada pode existir sem disponibilizar um fluxo sem os seus atores.
15. Confirmar dashboard e atividade autorizada com resultado recuperável, anexos/scan/derivadas e recusa de acesso indevido. Aproveitar provas válidas das seis categorias; no destino usar apenas dados legítimos existentes. Sem organização real/representação/ator correspondente, registar o critério específico pendente. Instalação não publica anúncios nem camadas. Notificações externas, restauração, partilha individual, modulares/ofertas/SLA, legado e percurso190000 continuam fora.
## Sucesso, condições de paragem e contenção
Sucesso: só sete tabelas/cinco colunas030000+040000, ledger/auditoria correspondentes, COUNTRY02 e cifra intactos; scanner3310 com assinaturas atuais, PHP web efetivo, LocalService sem escrita em código/config e worker supervisionado; fila/auditoria sem duplicações; bootstrap só com os dois titulares designados e confirmação independente. Fluxo só disponível após atores/âmbitos designados e atividade legítima recuperável.
Parar antes da aplicação em prévia/fingerprint/hash/base/backup divergente. Não declarar B1/B2 fechados por provas de13310/QA. Não habilitar fluxo sem a dependência necessária. Janela humana agrupada: operação administrativa de tarefas/ACLs, um reinício normal Laragon e autenticações locais dos titulares com MFA; não enviar segredos.
Contenção: desabilitar somente worker e flags deste pacote pelos controlos normais, preservar fila/quarentena, scanner seguro, HTTPS/cookie, COUNTRY02/050000, colunas/tabelas, cifra, IDs e auditoria. Recuperar configuração/vhost/ACLs somente nos objetos exportados e depois de parar os seus processos. Não rebaixar assinaturas válidas nem repor acesso universal aos anexos. Não repor automaticamente o código antigo de bootstrap sobre uma dupla já criada; manter o bundle/código consolidado desabilitado até uma correção compatível. Antes de DDL/uso pode voltar ao bundle/código de referência após verificação; depois de uso não executar down/drop, key:generate, purge de filas ou restauro completo sem decisão separada e reconciliação das escritas posteriores. Restauração de oportunidade continua OFF e nunca republica automaticamente.
'''
(O/'procedimento-unico.md').write_text(procedure,encoding='utf-8')
write(O/'reconciliacao-191-ficheiros.json',reconciliation)
write(O/'localservice-qa.json',local)
write(O/'designacoes-verificacao-readonly.json',accounts)
reused=load(R/'outputs/investmoz-service-followup-20261011/evidencias-por-criterio.json')
evidence={'integrated_delta':code['code_revision'], 'localservice':local,
'bootstrap_reused':reused['bootstrap'], 'scheduler_reused':reused['scheduler'],
'PHP_web_reused':reused['PHP_web'], 'uploads_reused':['PDF2.5MiB','PNG3.3MB + three WebP','PDF20MiB recovery with256M'],
'unchanged_functional_proofs':['A/B','C37','coediting','six base categories'],
'bootstrap_screenshots_location':'../investmoz-service-followup-20261011/',
'QA_restore':{k:backup[k] for k in ['verified_at','table_count','sequence_count','file_count','dump_sha256','files_sha256','MFA_envelopes_readable','original_non_transient_tables_preserved']},
'actual_destination_readonly':queue,'restoration_scope':reconciliation,
'destination_services_authorized_or_changed':False,'active_writes':0}
write(O/'evidencias-por-criterio.json',evidence)
manifest={**basis,'format':'investmoz-workflow-consolidated-v1','revision':revision,'code_revision':code['code_revision'],
'zip':name,'zip_sha256':sha(O/name),'code_files':22,'production_assets':159,'payload_files':181,
'delta_files':code['delta_files'],'production_manifest_sha256':build['manifest_sha256'],
'resources_fingerprint':backup['resource_fingerprint'],'profile_fingerprint':backup['profile_fingerprint'],
'base_hashes':{key:(sha(R/key) if (R/key).is_file() else None) for key in payload},
'unchanged_dependencies':{key: value for key,value in prior['unchanged_dependencies'].items() if key not in payload},
'included_scope':prior['included_scope'],'privacy_policy':prior['privacy_policy'],
'additional_changes_vs_98a8':['Normal Fortify serialized MFA envelope compatibility without re-encryption',
'Crossed bootstrap request/confirmation and pending-request session recovery',
'No third initializer; exactly two owner-designated holders',
'Production rebuild159assets', 'Consolidated services proposal with effective-ACL restrictions and fresh queue gate'],
'effects':{**prior['effects'],'code_files':22,'build_assets':159,
'additional_schema_vs_prior_candidate':0,'automatic_destination_accounts_or_organizations':0,
'bootstrap_data_if_later_authorized':'One existing pair entity; existing security approvals/receipts/audits. No parallel identities.',
'external_notifications':'OFF; zero recipients. Stop before worker if queued outbound notification.',
'services':'Only proposed B1/B2 intervention; QA permissions proved under LocalService, target services/ACLs not changed'},
'QA_backup':evidence['QA_restore'],
'destination_backup_reference':reconciliation['reports'][0],
'destination_backup_must_be_renewed_and_bound_before_intervention':True,
'activation_blocks':[
{'id':'B1','remaining':'Authorize and verify aligned scanner3310/update/tasks in destination'},
{'id':'B2','remaining':'Authorize/apply scoped effective ACLs, target worker and web limits; fresh target queue read before enable'},
{'id':'B3','resolved':'Holder accounts ID2 and13 identified/verified; crossed QA bootstrap proved',
'remaining':'Separate bootstrap authorization and ceremony; operational profile accounts/organizations/types/scopes still to designate'},
{'id':'BACKUP','remaining':'Renew actual destination backup/restoration bound to consolidated revision before intervention'}],
'activation_ready':False,'activation_authorized':False,'QA_fixtures_in_delivery':False,
'new_acervo_import_or_publication_included':False,'COUNTRY02_preserved':True,
'restoration_decisions_pending':prior['restoration_decisions_pending'], 'active_writes':0,
'sealed_at':datetime.now(timezone.utc).isoformat()}
write(O/'manifesto.json',manifest)
report=f'''# Candidata consolidada {revision[:12]} — QA e proposta final
O delta **117d2d889701** foi integrado sem alterar código adicional: nova candidata **{revision[:12]}**, código **{code['code_revision'][:12]}**, 22 ficheiros de código +159 recursos de produção. A referência **98a8e0b70892** e o delta separado permanecem intactos. ZIP SHA-256: **{manifest['zip_sha256']}**. Produção já recompilada no delta; a consolidação reaproveita exatamente esses bytes, com todos os hashes verificados. Não foi necessário recompilar novamente sem alteração de fonte.
## O que mudou e o que foi demonstrado
Seis ficheiros do delta substituem/acrescentam a cerimónia cruzada, suporte ao envelope MFA normal e recuperação do pedido pendente. Não há DDL adicional face a030000/040000 da candidata anterior. Fortify, contas, recibos e portal_security_approvals existentes foram reutilizados. Provas UI/MFA válidas do pedido15→confirmação16, autoaprovação negada, nova sessão/replay, expiração/hash e atomicidade foram ligadas; não repetidas. A/B, C37, coedição e categorias anteriores conservam os fechos.
**LocalService real S-1-5-19:** novo clone **{local['target']['database']}:55441**, cinco invocações pelo Agendador com PT3M/IgnoreNew. Quatro scans reais: PDF20MiB e três WebP sintéticos. Fila4→3→2→1→0 e repetição0→0, zero failed_jobs, zero documentos/recursos novos; cifra e hashes recuperados. CLI256M, pico148MiB, scanner13310/ClamAV1.5.4 com assinaturas11/10 às08:26UTC. Configuração guardada lida e acesso DBQA confirmado. Escrita em storage/cache/logs/dados scanner permitida; escrita em código/vendor/config/.env negada e leitura de sentinela alheia negada. Tarefa temporária removida. Não prova serviço/ACLs já instalados no destino3310. A expiração real180s/recuperação210s anterior permanece uma prova distinta de utilizador interativo; não foi injetada nova interrupção sob LocalService.
## Restauros e originais
| Prova | Tabelas/seq | Ficheiros | Âmbito |
| --- | --- | --- | --- |
| Destino,15:11:50UTC |288/31 |799 |4 originais privados +476 runtime/config/bundle +312 código ativo +2TLS +5Apache |
| QA anterior,15:11:55UTC |295/31 |188 |12 documentais +1env +17 código +158bundle; oito documentais sintéticos desse clone não pertencem ao clone atual |
| QA delta,16:29:27UTC |295/31 |191 |9 documentais +1env +22 código +159bundle |
| QA renovada,{backup['verified_at']} |295/31 |191 |Mesma composição; dump e bytes fisicamente restaurados,9 envelopes MFA legíveis |
Os quatro originais do destino estão nos191 com **mesmo nome e hash**, sem omissões. Os cinco adicionais são PNG sintético, três WebP e PDF20MiB; não vão para o ativo. Os oito ficheiros exclusivos do ensaio anterior continuam no seu backup preservado: não se afirmam perdidos ou incluídos nesta candidata. O aumento288→295 resulta das sete tabelas030000+040000. O ZIP de disponibilização contém181 ficheiros de código/bundle; não contém env, certificados, chaves, documentos privados, vendor ou fixtures.191 não é inventário integral do acervo histórico. Nenhuma importação/documento histórico novo integra esta entrega; acervo/biblioteca e backups anteriores permanecem frentes próprias.
## Designações e limitações restantes
Responsável indicou **nala@tempo.co.mz (ID2)** e **onala@me.com (ID13)**. Ambas existem no destino, com email verificado, MFA confirmado e autorização legada de gestor; os IDs3/18 iniciais não correspondiam. Identificação resolvida, privilégios não atribuídos. Pedido/confirmador são os dois titulares, sem terceiro inicializador. Os papéis operacionais ainda necessitam de contas, organização/representação legítima, tipos e âmbito; administradores não substituem essa designação.
Incluídas: seis categorias base investment_project,real_estate,land_rights,business_sale,business_partnership,franchise, no âmbito ensaiado anterior; venda/arrendamento de imóvel concluído/desocupado/sem ónus e workflow interno, não uma decisão de entidade externa. Permanecem indisponíveis as variantes não ensaiadas, restauração, partilha documental individual/NDA/revogação individual, Response/§27 normativo integral, modulares/ofertas/SLA, legado e190000, importação/publicação de geometrias, dispositivos reais/acessibilidade integral. Não se convertem estados ou classificações para disponibilizar variantes.
**B1/B2 ainda são bloqueios no destino:** scanner/tarefas atuais3310 precisam da intervenção; LocalService/ACLs efetivas, supervisão e limites PHP web têm de ser aplicados/verificados sob autorização própria. A leitura ACL existente mostra concessões herdadas amplas: adicionar somente RX não garante a restrição pretendida. A proposta passou a exigir neutralização da escrita herdada e proteção dos controlos privados, sem retirar direitos aos outros principais. Não conceder Modify a toda storage, que também contém runtime/config/backup de auditoria. O restauro QA renovado não substitui a renovação do destino após fixar a candidata.
Fila ativa lida em **{queue['at']}**: zero jobs/failed_jobs, notificações OFF e zero destinatários, nenhum job consumido. O procedimento exige **nova leitura imediatamente antes de habilitar o worker**, mantendo notificações externas OFF e parando perante classe desconhecida ou notificação enfileirada. A tarefa default partilhada pode processar simulações/comparações locais; estes efeitos estão enumerados no procedimento.
## Uma proposta de intervenção e contenção
[Procedimento único](procedimento-unico.md): backup/restauro do destino ligado à revisão → código/bundle com flagsOFF → alinhamento ClamD e ACLs restritas → limites do vhost/um reinício Laragon →030000→040000 autenticadas → nova leitura da fila/worker → confirmação cruzada autorizada → perfis/âmbitos legítimos → flags do workflow e atividade recuperável.050000 não se repete; COUNTRY02 permaneceON;190000 não bloqueia workflow isolado.
Contenção preserva HTTPS/cookie/chave, originais, filas, histórico/auditoria e schema. Desabilitar somente worker/flags do pacote; preservar correções de confidencialidade e scanner seguro. Não reverter automaticamente a cerimónia nova após criar a dupla; não executar down/drop/key:generate/purge/restauro completo. Config/ACL/XML/vhost só pelos objetos exportados, depois de parar processos próprios. Restauro completo exige decisão separada e reconciliação das escritas posteriores.
**Candidata preparada em QA; não pronta para ativação com B1/B2 e backup do destino por resolver.** Nenhuma alteração no ativo. [Manifesto](manifesto.json), [provasLocalService](localservice-qa.json), [reconciliação191](reconciliacao-191-ficheiros.json) e [tabelaB3](designacoes-b3.md).
'''
(O/'relatorio-consolidacao.md').write_text(report,encoding='utf-8')
write(P/'consolidated-candidate-latest.json',{'output':str(O),'revision':revision,'code_revision':code['code_revision'],
'zip':name,'zip_sha256':manifest['zip_sha256'],'manifest_sha256':sha(O/'manifesto.json')})
print(json.dumps({'result':'consolidated_QA_candidate_prepared','revision':revision,'code_revision':code['code_revision'],
'payload_files':181,'zip_sha256':manifest['zip_sha256'],'designated_destination_accounts':[2,13],
'LocalService_QA_passed':True,'activation_ready':False,'active_writes':0}))