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

123 lines
17 KiB
Python

from pathlib import Path
from datetime import datetime,timezone
import csv, json, hashlib, shutil, collections, zipfile
R=Path(__file__).resolve().parent.parent;P=R/'storage/app/private/investmoz-v2/portal-audit';O=R/'outputs/investmoz-operational-onboarding-20261011'
O.mkdir(exist_ok=True)
plan=json.loads((P/'onboarding-governance-plan.json').read_text());S=Path(plan['source'])
identity=json.loads((P/'onboarding-designations-readonly.json').read_text());public=json.loads((P/'onboarding-public-browser.json').read_text());smtp=json.loads((P/'onboarding-smtp-preflight.json').read_text())
browser=json.loads((P/'onboarding-governance-browser.json').read_text())
assert identity['active_writes']==0 and identity['COUNTRY02_enabled'] and public['result']=='passed'
assert browser['result']=='passed' and plan['production_build_passed'] and plan['target']['port']==55441
assert all(not row['existing_accounts'] for row in identity['designations'])
for row in plan['files']:
assert hashlib.sha256((S/row['path']).read_bytes()).hexdigest()==row['after_sha256']
if row['before_sha256']:assert hashlib.sha256((R/row['path']).read_bytes()).hexdigest()==row['before_sha256']
shutil.copyfile(P/'onboarding-public-browser.json',O/'registo-publico-destino.json')
shutil.copyfile(P/'onboarding-designations-readonly.json',O/'designacoes-leitura-destino.json')
shutil.copyfile(P/'onboarding-smtp-preflight.json',O/'email-preparacao-destino.json')
shutil.copyfile(P/'onboarding-governance-browser.json',O/'atribuicoes-qa-navegador.json')
shutil.copyfile(P/'onboarding-governance-tests.xml',O/'atribuicoes-qa-tests.xml')
shutil.copyfile(P/'onboarding-governance-administration-qa.png',O/'atribuicoes-qa.png')
shutil.copyfile(P/'onboarding-qa-tests.xml',O/'registo-email-qa-tests.xml')
revision=plan['delta_sha256'][:12]
text=f'''# Preparação operacional — Tempo, Lda — 11/10/2026
## Designações confirmadas pelo responsável
A Tempo, Lda é proprietária do Portal InvestMoz, segundo declaração expressa do responsável. O nome não representa um cadastro já criado: a consulta em leitura do destino encontrou zero organizações e zero representações.
| Pessoa e email indicados | Papel autorizado | Âmbito confirmado | Estado no destino |
| --- | --- | --- | --- |
| Aurora Chachuaio — Aurora.chachuaio@tempo.co.mz | Promotor | Representação da Tempo, Lda; seis categorias base | Conta ainda inexistente; organização/representação por cadastrar no mecanismo autenticado legítimo |
| Palmira Uamusse — Palmira.matsinhe@tempo.co.mz | Validador | Todas as organizações; seis categorias base; revisão independente | Conta ainda inexistente; contacto e MFA próprios pendentes |
| Mario Melembe — mario.melembe@tempo.co.mz | Publicador | Todas as organizações; seis categorias base; catálogo público após aprovação independente | Conta ainda inexistente; contacto e MFA próprios pendentes |
As seis categorias são projeto de investimento (`investment_project`), imobiliário (`real_estate`), direitos sobre terra (`land_rights`), venda de negócio (`business_sale`), parceria de negócio (`business_partnership`) e franquia (`franchise`). Não inclui concessão, financiamento, fornecimento, outros, ofertas ou SLA.
O vínculo profissional à Tempo não atribui a Palmira/Mario uma representação de Promotor. Cada processo mantém a proibição de rever autoria/coedição ou representação na entidade promotora, e o Publicador deve ser independente do autor e do Validador que aprovou a mesma versão. O âmbito transversal não elimina essas restrições. Nenhuma responsabilidade adicional de coordenação, recurso ou suplência foi atribuída por suposição.
## Cada pessoa prepara a sua conta
1. Abrir https://portal-investidor.test/register e usar o seu nome e email, de preferência em minúsculas. Escolher pessoalmente a password.
2. Confirmar o contacto pelo email de verificação. Se necessário, https://portal-investidor.test/email/verify permite solicitar novo envio depois do login.
3. Abrir https://portal-investidor.test/settings/security, confirmar a própria password, configurar e confirmar MFA no autenticador pessoal.
4. Voltar a entrar com o próprio MFA. Não partilhar passwords, QR, segredos, códigos ou cookies com o responsável ou com esta conversa.
O registo Fortify já é independente das flags do workflow. Não foi criada uma segunda via de identidades ou uma conta com password imposta. Não foi encontrado um fluxo administrativo existente de criação/convite de utilizadores. Os emails indicados foram pesquisados sem distinção entre maiúsculas/minúsculas; não existe correspondência prévia no destino.
## Evidência do destino, sem escrita
- Chromium: `/register` respondeu 200 por HTTPS reconhecido, formulário visível, contexto seguro, sem erros JS nem conteúdo misto. `/email/verify` e `/settings/security` encaminham visitantes para autenticação.
- SMTP: transporte configurado na porta 587 completou STARTTLS obrigatório e autenticação com resposta 235. Nenhuma mensagem foi enviada. A entrega real do email e confirmação de cada pessoa continuam pendentes.
- Leitura PostgreSQL `investemoz:5432` numa transação READ ONLY: 13 contas, zero atribuições operacionais, zero organizações, zero representações, fila vazia. COUNTRY02 ON; perfis/workflow, dashboard e rascunhos especializados OFF.
- Não foram criadas contas, organizações, representações, grants, migrations, importações ou publicações no destino nesta preparação.
## Correção preparada exclusivamente em QA
Delta de código `{revision}` sobre a candidata preservada `41caea0f900f`. Nove ficheiros de código/configuração/interface e bundle recompilado. Zero tabelas/colunas novas e nenhuma alteração de chave de cifragem.
O problema era a utilização de `EnsurePortalProfiles` tanto para a administração/pedidos como para operações de oportunidades. Foi preparada a flag independente `PORTAL_PROFILE_ADMINISTRATION_ENABLED`, desabilitada por defeito. Em QA fica ON com `PORTAL_PROFILE_ACCESS_ENABLED=false`: os titulares já inicializados e com MFA recente podem preparar/auditar as atribuições; os utilizadores verificados podem preparar e acompanhar o pedido de Promotor. As rotas de criação, edição, revisão, publicação e anexos das oportunidades continuam fechadas. Revogação de sessões, restrições de Auditor, proteção de MFA obrigatório e impedimento de autoatribuição continuam aplicáveis nesta preparação.
Os dois seletores de atribuição receberam nomes acessíveis explícitos, consistentes com os rótulos visíveis. Isso exigiu recompilação de produção, concluída apenas na árvore QA separada. A aplicação servida pelo Apache foi comparada com os hashes anteriores e não foi modificada.
### Critérios demonstrados em QA
- Seis ensaios HTTP/persistência: administração exige flag explícita, titular e MFA recente; rejeita conta sem contacto confirmado/MFA e autoatribuição; pedidos de Promotor exigem documentos próprios e representação; repetição do pedido conserva o mesmo ID; aprovação independente grava o grant; revogação invalida a sessão e mantém MFA protegido; preparar papéis não desbloqueia operações nem anexos.
- Chromium com conta sintética e MFA normal Fortify: login/MFA → dashboard → Gestão de perfis → atribuição de Validador nas seis categorias → resultado visível → atualização → nova sessão/login/MFA → recuperação. Uma atribuição e um evento `role_granted`, zero oportunidades; rota operacional 404 com flag OFF.
- Os oito testes anteriores de registo/email cobrem registo com workflow OFF, confirmação do email assinado e rejeição de ligações inválidas. Não são prova de entrega de email real.
- Os comprovativos/representações dos testes HTTP são fixtures sintéticas de autorização. Não constituem prova de legitimidade real nem um novo ensaio do scanner. C37 e A/B não foram reabertos ou repetidos.
QA isolada: `{plan['target']['database']}:55441`, código numa árvore privada separada, MAIL=array, notificações externas OFF, cookie próprio, chave sintética estável. O navegador deste ensaio usou HTTP loopback na porta 18117; a inspeção do registo no destino usou HTTPS reconhecido. A mudança de infraestrutura HTTPS não faz parte deste delta.
## Próximas ações autenticadas e condições de abertura
1. As três pessoas registam/confirmam os contactos e o próprio MFA. Uma nova leitura associará os IDs reais aos emails, preservando eventual conta criada entretanto.
2. Disponibilizar o delta de preparação de perfis somente após o procedimento de revisão/backup do destino; não reaplicar 030000, 040000 ou 050000. A candidata ativa e a autorização técnica anteriores ficam preservadas. Este pacote QA não foi ativado.
3. Reutilizar `organizations`/`memberships` para cadastrar legitimamente a Tempo, Lda e a representação de Aurora. A pesquisa das rotas atuais encontrou leitura/seleção e alteração de país mestre, mas não criação autenticada de organização/representação. Também falta uma via própria de envio de comprovativos antes da atribuição de Promotor: o pedido seleciona documentos próprios já analisados, mas o upload da biblioteca identificado exige `manage-portal`. Estas lacunas técnicas devem ser concluídas em QA; não usar SQL, organização fictícia, privilégio de gestor para Aurora ou atribuição de Promotor a Palmira/Mario como substitutos.
4. Aurora apresenta o pedido em `/perfil/promotor`, com representação e documentos próprios analisados. Um titular independente decide em `/perfis/gestao`. O pedido não ativa o papel automaticamente.
5. Um titular com MFA recente atribui a Palmira `validator` e a Mario `publisher`, com as seis categorias explícitas e âmbito transversal (`organization_id=null` nestes dois papéis). Os motivos devem citar estas designações; não conceder outros papéis ou representações.
6. Só habilitar os fluxos correspondentes depois de contacto/MFA, atribuições/representação e âmbito funcional efetivamente disponibilizado. Validar o primeiro processo legítimo e o processamento documental no destino separadamente dos ensaios QA. Restauração e partilha individual permanecem OFF.
## Contenção e reversão
O delta ainda está exclusivamente em QA. A disponibilização futura exige backup/restauro atualizado da base destino e do código/documentos que incluir. A preparação pode ser contida desligando apenas a nova flag e mantendo as flags operacionais OFF; COUNTRY02, os dados, as duas colunas, os documentos e a auditoria devem ser preservados. Revogar grants apenas por ação autenticada, motivo e auditoria. Não restaurar a base inteira nem apagar histórico automaticamente. O pacote contém hashes anteriores e posteriores de cada ficheiro; a reposição de código deve preservar HTTPS, cookie e infraestrutura já estabilizados.
## Correspondência com a matriz existente
`AUD-PROFILE-01`: designações e âmbitos clarificados; identidades e grants reais pendentes. `AUD-PROFILE-03/04`: pedido/aprovação independentes conservados e ensaiados com operações OFF; organização/representação/documentos reais pendentes. `AUD-PROFILE-31`: preparação segregada em QA; disponibilização do novo delta pendente. Todos continuam parciais no âmbito global. Não foram criados novos IDs ou matriz paralela.
'''
(O/'preparacao-operacional.md').write_text(text,encoding='utf-8')
package=O/('delta-preparacao-perfis-'+revision+'.zip')
with zipfile.ZipFile(package,'w',zipfile.ZIP_DEFLATED) as archive:
for row in plan['files']+plan['assets']:archive.write(S/row['path'],row['path'])
manifest={key:plan[key] for key in ['base_candidate','delta_sha256','files','frontend_changes','production_build_required','production_build_passed','production_manifest_sha256','assets','new_tables','new_columns','QA_only']}
manifest.update({'package':package.name,'package_sha256':hashlib.sha256(package.read_bytes()).hexdigest(),'active_application_changes':0,'active_database_writes':0,
'activation_state':'not_activated','real_accounts_designations':'pending_own_contact_MFA_and_representation','approved_scope_source':'owner_messages_20261011','portal_owner_declared':'Tempo, Lda'})
(O/'manifesto.json').write_text(json.dumps(manifest,indent=2,ensure_ascii=False),encoding='utf-8')
marker='<!-- onboarding-designations-20261011 -->'
block=f'''{marker}
## Preparação das pessoas e administração de perfis — 11/10/2026
Designações confirmadas: Aurora Chachuaio (Promotor da Tempo, Lda); Palmira Uamusse (Validador transversal); Mario Melembe (Publicador transversal, catálogo público após aprovação independente). Seis categorias base para os três. Tempo, Lda é a proprietária do portal por declaração do responsável. Consulta READ ONLY: os três emails ainda não existem; zero organizações/memberships e grants. Não atribuir representação de Promotor a Palmira/Mario. Os titulares 2/13 mantêm funções de segurança, sem novos papéis operacionais.
Registo disponível no destino em HTTPS com flags operacionais OFF. SMTP STARTTLS/AUTH235 conferido sem envio; entrega/confirmacão próprias ainda pendentes. Delta `{revision}` preparado numa árvore QA separada: administração/pedidos independentes das operações, preservando MFA, revogação e auditoria. Seis provas HTTP/persistência e percurso Chromium dashboard → atribuir → atualizar → nova sessão → recuperar, com operações 404 e zero oportunidades. Bundle recompilado apenas em QA; ativo não alterado.
Critérios restantes por requisito: `AUD-PROFILE-01` contas próprias verificadas/MFA e grants reais; `AUD-PROFILE-03/04` cadastro mestre legítimo da Tempo, Lda, representação de Aurora e comprovativos/revisão independente; `AUD-PROFILE-31` disponibilização autenticada do novo delta após backup correspondente e habilitação limitada após atribuições. Faltam criação autenticada de organização/representação e envio próprio de comprovativos antes de ser Promotor, reutilizando as tabelas e o processamento documental existentes. COUNTRY02 preservado, A/B e C37 fechados nos âmbitos anteriores, restauração/partilha/modulares/ofertas/SLA/190000 fora desta preparação.
Detalhes e hashes: `outputs/investmoz-operational-onboarding-20261011/preparacao-operacional.md` e `manifesto.json`. Os blocos seguintes mantêm a cronologia anterior.
'''
for file in ['docs/investmoz/v2/auditoria-portal/backlog.md','docs/investmoz/v2/auditoria-portal/perfis-v1-reconciliacao.md']:
dest=R/file;old=dest.read_text(encoding='utf-8');assert marker not in old;dest.write_text(block+old,encoding='utf-8')
csv.field_size_limit(10_000_000)
with (R/'docs/investmoz/v2/auditoria-portal/matriz-requisitos.csv').open(encoding='utf-8-sig',newline='') as handle:rows=list(csv.reader(handle))
headers=rows[0];e=headers.index('Evidência funcional')
summaries={
'AUD-PROFILE-01':f'Designações 11/10 confirmadas: Aurora/Tempo, Lda Promotor; Palmira Validador e Mario Publicador (catálogo público), ambos todas as organizações; seis categorias base para os três. Destino READ ONLY: emails ainda inexistentes, zero grants/organizações/representações. Preparação segregada em QA delta {revision}; seis critérios HTTP/persistência e Chromium com MFA normal, resultado visível, atualização e nova sessão. Papéis reais pendentes de contas próprias/confirmadas/MFA; ativo não alterado. outputs/investmoz-operational-onboarding-20261011/preparacao-operacional.md',
'AUD-PROFILE-03':f'Delta QA {revision}: pedido/recuperação/aprovação documental independente possíveis com operações OFF; mesma creation_key repete o ID, exige documento próprio e representação, não ativa operação por guardar pedido. Aurora foi designada para representar Tempo, Lda; entidade e vínculo reais ainda ausentes, criação autenticada do cadastro mestre/representação e upload próprio de comprovativos antes do Promotor por concluir (biblioteca exige manage-portal). Registo público ativo já independente do workflow, HTTPS/SMTP STARTTLS/AUTH235 conferidos sem mensagens. Contacto/MFA próprios pendentes. outputs/investmoz-operational-onboarding-20261011/preparacao-operacional.md',
'AUD-PROFILE-31':f'Delta {revision} sobre 41caea0f900f preservada: nova flag PORTAL_PROFILE_ADMINISTRATION_ENABLED separa atribuições/pedidos da abertura operacional. Em QA: dashboard → Gestão de perfis → gravar atribuição → atualizar → nova sessão/MFA → recuperar; 1 grant/1 auditoria, zero oportunidades, operações 404, proteção MFA/revogação/segredos mantidas. Bundle de produção recompilado em QA. Zero alterações de schema/dados/código ativo. Disponibilização do delta e backup correspondente pendentes; COUNTRY02 ON e restantes flags OFF. outputs/investmoz-operational-onboarding-20261011/manifesto.json'
}
updates={row[0]:{'Evidência funcional':row[e]+'\n\n'+summaries[row[0]]} for row in rows[1:] if row[0] in summaries};assert len(updates)==3
(P/'onboarding-matrix-baseline.json').write_text(json.dumps({'rows':rows,'updates':updates},ensure_ascii=False),encoding='utf-8')
print(json.dumps({'result':'operational_preparation_recorded','delta':revision,'package_sha256':manifest['package_sha256'],'matrix_changes_prepared':3,'active_changes':0}))