123 lines
17 KiB
Python
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}))
|