"""Prepare only cell patches in the existing audit and readable scope/restoration records.""" from pathlib import Path from datetime import datetime,timezone import csv,json,hashlib,collections csv.field_size_limit(20000000) root=Path(__file__).resolve().parent.parent;d=root/'docs/investmoz/v2/auditoria-portal';p=root/'storage/app/private/investmoz-v2/portal-audit' read=lambda n:json.loads((p/n).read_text(encoding='utf8')) tag='[Delimitação/ACL QA 11-10-2026] ' folder=p/'functional-scope-finalize-20261011';folder.mkdir(exist_ok=True) scope=read('functional-delivery-scope-code-20261011.json');backup=read('functional-scope-backup-restoration-qa-20261011.json');target=read('functional-scope-target-backup-20261011.json') assert scope['code_revision']==backup['code_revision']==target['candidate_code_revision'] evidence='functional-document-alias-before/after-20261011.json; functional-document-boundary-chromium-20261011.json; functional-document-images-chromium-20261011.json; functional-delivery-scope-chromium-20261011.json; functional-scope-dependencies-chromium-20261011.json; functional-scope-persistence-qa-20261011.json. C126: alias geral200 enquanto rota própria403; corrigido para403 nas duas rotas, originais/derivadas permitidos por perfil recuperados pelos hashes. Revogação sintética32/auditoria elimina acesso pelo URL anterior na sessão aberta e nova. Documento aceite29 preservado. Disponibilidade imobiliária422 conserva também os erros semânticos anteriores; rascunho55planeado recuperável. Casos30–35/54 e renda4500/monthly preservados.' common='Seis categorias base e variantes delimitadas na interface QA; módulos separados não oferecidos com flagOFF, sem alterar concessões/contratos/taxonomia. Serviço VerifiedDocumentBinary aplica a autorização atual da oportunidade também na rota genérica e nas derivadas. Nenhuma tabela/ACL paralela; partilha individual continua indisponível e explicada. Publicar anúncio não publica anexos.' gap='ACL individual de anexos ainda não implementada: destinatário externo selecionado, subconjunto de membros, concessão/revogação por ficheiro. Não incluir documentos que exigem essa confidencialidade individual. Response normativo§27 integral, variantes por categoria não ensaiadas, restauração da oportunidade e leitores/dispositivos reais permanecem fora da entrega. R-ARCHIVE/R-DRAFT aguardam decisão; não confundir com restauro de anexo.' deps='030000 →040000 confirmado em prévias QA com schema/ledger/dependências consistentes;190000 apenas quando disponibilizado o percurso integrado. Alvoativo288tabelas/020000+050000/COUNTRY02ON:030000+040000 ausentes. Backup/restauro REAL do alvo em'+target['verified_at']+':288tabelas,31seq,799ficheiros,2MFA,restauro somente55441; ligado ao código'+scope['code_revision'][:12]+'. Readiness/prévias autenticadas correspondentes, ensaio de atualização do clone do alvo, ClamD3310fresh/scan/worker supervisionado e titulares/âmbitos legítimos ainda necessários. Zero geometrias no alvo; importação separada. Não ativar agora.' active='Ativo consultado READONLY investemoz:5432; COUNTRY02ON, demaisflagsOFF,288tabelas,13contas,0org/representações/geo_geometries. Nenhuma escrita ou troca de código/configuração/serviço ativo. Codefix apenas cloneQA55441. A/B eC37 preservados.' ids={'AUD-OP-01','AUD-OP-02','AUD-OP-03','AUD-OP-04','AUD-PROFILE-07','AUD-PROFILE-29','AUD-PROFILE-31','AUD-PROFILE-32','AUD-OPS-01','AUD-UI-01'} packet={'proof_filename':'csv-authoring-proof.json','files':[]} for name in ['matriz-requisitos.csv','backlog-priorizado.csv']: file=d/name;raw=file.read_bytes() with file.open(encoding='utf-8-sig',newline='')as s:rows=list(csv.reader(s)) h=rows[0];patches=[] for number,row in enumerate(rows[1:],1): rid=row[h.index('ID')] if rid not in ids:continue def append(k,v): old=row[h.index(k)];assert tag not in old,(rid,k) return old+'\n'+tag+v if name=='matriz-requisitos.csv': values={'Implementação encontrada':append('Implementação encontrada',common),'Disponibilidade ativa':active, 'Evidência funcional':append('Evidência funcional',evidence),'Lacuna':append('Lacuna',gap),'Dependência':append('Dependência',deps), 'Interface':append('Interface','Âmbito/variantes/privacidade visíveis a390px; erro422adjacente, rascunho55e renda54recuperados. Não repetirA/B/C37.'), 'API':append('API','403 nas rotas próprias/genéricas/derivadas sem perfil;401 após revogação da sessão,403no novo login; biblioteca aceita29continua200/hash. Submissão variante excluída422, sem apagar erros semânticos.'), 'Gravação':append('Gravação','SomenteQA: rascunho55 e conta sintética32/MFA normal, concessão/revogação pelos serviços existentes com auditoria. Perfis existentes não revogados;0escritasativas.'), 'Recuperação':append('Recuperação',evidence),'Resultado apresentado':append('Resultado apresentado',common), 'Versões divergentes':append('Versões divergentes','Candidata8af63e2fe657 preservada como referência;C126 impede a sua disponibilização. Novo código'+scope['code_revision'][:12]+' inclui seis ficheiros alterados face àquela, total14no delta e bundle recompilado. Propostas de restauração não são decisões implementadas.')} else: values={'Pendência':append('Pendência',gap),'Correção/componentes':append('Correção/componentes',common+' '+evidence), 'Dependência/pergunta':append('Dependência/pergunta',deps+' Decisões separadas: aprovar R-ARCHIVE(Publicador independente→needs_information/não público) e R-DRAFT(autor/coeditor autorizado→draft, nunca submetido/publicado)? Nenhuma republicação automática.'), 'Ordem do próximo lote':append('Ordem do próximo lote','RevisãoQA delimitada comC126corrigido; preparar ensaio de atualização do clone real, readiness por instalação e serviços do destino. ACLindividual fora do pacote; não oferecer divulgação seletiva. COUNTRY02ativo preservado; nenhuma ativação autorizada.')} patches.append({'row':number,'values':values}) assert len(patches)==len(ids) packet['files'].append({'filename':name,'input_sha256':hashlib.sha256(raw).hexdigest(),'rows':rows,'patches':patches,'allowed_columns':sorted({k for patch in patches for k in patch['values']}),'source_hash_updates':[]}) if name=='matriz-requisitos.csv':counts={'requirements':len(rows)-1,'rows':len(rows)-1,'source_occurrences':sum(int(r[h.index('Quantidade de linhas de origem')])for r in rows[1:]),'states':dict(collections.Counter(r[h.index('Estado')]for r in rows[1:])),'updated_IDs':sorted(ids),'new_IDs':0} (folder/'csv-edits.json').write_text(json.dumps(packet,ensure_ascii=False),encoding='utf8');(folder/'counts.json').write_text(json.dumps(counts,ensure_ascii=False,indent=2),encoding='utf8') cases=d/'casos-reproducao.md';text=cases.read_text(encoding='utf8');assert '## C126' not in text text+='''\n\n## C126 — contorno da autorização de anexos pela rota geral da biblioteca\n\n- **Prioridade/estado:** P0 de confidencialidade; corrigido e demonstrado apenas em QA. Impede disponibilizar a candidata8af63e2fe657 sem esta correção. Não existe030000/040000 no ativo; não se extrapola a exploração para documentos de outro consumidor.\n- **Operação/perfil:** gestão geral17, sem perfil/âmbito da oportunidade54; descarregar um original, imagem ou derivada por UUID.\n- **Reprodução:** autenticar17 emQAHTTPS18445; GET`/minhas-oportunidades/54/resources/documents/a61f9a47-82a7-49cc-958e-edd115729333/download` devolve403; GET`/management/documents/8dd5731f-80dc-48a1-a307-a51e27769d0b/download` devolvia200/PDF para os mesmos bytes.\n- **Esperado/observado:** ambas as rotas devem exigir a autorização vigente da oportunidade; só a primeira a exigia. Causa: rota geral aceitava manage-portal e VerifiedDocumentBinary conferia apenas scan/integridade/cifra.\n- **Correção:** serviço comum resolve a relação existente com oportunidade e exige perfil/âmbito atual, recurso ativo e oportunidade não arquivada; originais/derivadas órfãos dessa origem falham fechados. URLs assinados conservam autenticação e autorização. Sem tabelas ou cadastros paralelos; classificação não é ACL.\n- **Provas:** functional-document-alias-before/after-20261011.json; functional-document-boundary-chromium-20261011.json; functional-document-images-chromium-20261011.json. Ambos os URLs403 para17; Promotor21/Validador24/Publicador25 recuperam os três PDFs54pelos hashes; derivadas33protegidas e biblioteca29preservada. Concessão sintética32 e revogação por Superutilizador27: URL anterior recusado na sessão e após novo login, com auditoria. A retirada global anterior não foi usada como substituto desta revogação.\n- **Limite:** não implementa conceder/revogar acesso a um destinatário individual por anexo. Partilha externa seletiva e restrição entre membros autorizados continuam indisponíveis e anunciadas na interface.\n''' cases.write_text(text,encoding='utf8') print(json.dumps(counts,ensure_ascii=False))