From 3d9c94f439a1c52b8f9fcab9a8661fb696bb4967 Mon Sep 17 00:00:00 2001 From: Kemuel-sepulvida Date: Sat, 22 Aug 2026 12:30:56 -0300 Subject: [PATCH] =?UTF-8?q?feat(assinatura):=20pend=C3=AAncia=20emite=20UR?= =?UTF-8?q?L=20de=20verifica=C3=A7=C3=A3o=20e=20casa=20legislativa=20AB#14?= =?UTF-8?q?73=20(#18)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix(Assinatura): materializacao recusa rodar sem base URL em vez de falhar 861 vezes AB#1473 Achado num acervo real em 22/08/2026: 0 de 861 materias DOCX tinham PDF-alvo, e o motivo nao aparecia em lugar nenhum. So os 7 PDF passavam — PDF nao converte, copia bytes — e davam a impressao de que a rotina estava viva. A conversao DOCX->PDF e o OnlyOffice quem faz, e para isso ele BAIXA o documento de origem por URL absoluta. `build_onlyoffice_url` prefere SAPL_INTERNAL_URL e so cai no request sem ela; no cron o "request" e o `_RequisicaoDeSistema`, que monta a partir de SITE_URL. Com as duas vazias a URL sai SEM HOST, o OnlyOffice responde erro e cada materia vira um logger.error individual. O resumo da passada (`0 gerados, 873 falhas`) nao se distingue de um dia normal no meio do log. Duas mudancas, as duas sobre visibilidade: 1. Erro de CONFIGURACAO morre no comeco, alto: sem SAPL_INTERNAL_URL nem SITE_URL o comando levanta CommandError antes de varrer o acervo, dizendo qual variavel falta e por que. Vale para a passada unica e para o laco. 2. Passada que falha sem NENHUM gerado grita no stderr: falha em todas nao e documento podre avulso, e ambiente parado (OnlyOffice fora, URL que ele nao alcanca, MEDIA sem os binarios). A fixture `base_url_configurada` entra em autouse no test_materializacao: base URL e pressuposto de toda materializacao, nao caso de borda — a ausencia dela tem os seus proprios testes. Testes: 64 passed em sapl/integracao_hub/tests/ (eram 61). * feat(assinatura): pendencia emite URL de verificacao e casa legislativa AB#1473 Sem estes dois campos o AMU assina SEM a pagina de autenticacao, e o documento sai divergente do assinado no SAPL — exatamente o que a convergencia dos assinadores elimina. Achado testando a assinatura pelo app: o microservico respondeu 400 "verification_url_base vazio.". So o SAPL sabe a URL publica desta casa e o nome dela, entao os campos precisam viajar COM a pendencia. O amu-backend ja os consome (grava em `casa_legislativa`/`verification_url_base` e repassa ao /sign); hoje chegavam vazios porque a fonte nao os emitia, e o fallback por tenant_settings tambem nao estava configurado. Reusa `_construir_url_verificacao_base` e `_obter_nome_casa_legislativa` de views_assinatura em vez de remontar a URL aqui: sao a forma canonica que o proprio SAPL usa ao chamar o microservico. Duplicar a montagem e o caminho conhecido para as duas divergirem na primeira mudanca. Sem ciclo de import (views_assinatura nao importa integracao_hub). Verificado no container sapl-localhost: - 23 testes de integracao_hub/tests/test_assinatura.py passando - payload real da materia 811/2026: verification_url_base: http:///materia/1065/verificar/ casa_legislativa: Camara Municipal de Franco da Rocha Co-Authored-By: Claude Opus 4.8 --------- Co-authored-by: Claude Opus 4.8 --- sapl/integracao_hub/serializacao.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/sapl/integracao_hub/serializacao.py b/sapl/integracao_hub/serializacao.py index 1a1686692..58bfa4f93 100644 --- a/sapl/integracao_hub/serializacao.py +++ b/sapl/integracao_hub/serializacao.py @@ -8,6 +8,8 @@ from django.utils import timezone from sapl.base.models import Autor, OperadorAutor from sapl.materia.models import MateriaLegislativa +from sapl.materia.views_assinatura import ( + _construir_url_verificacao_base, _obter_nome_casa_legislativa) from sapl.parlamentares.models import Parlamentar, Votante logger = logging.getLogger(__name__) @@ -203,6 +205,14 @@ def _autores_pendentes(materia): def serializar_pendencia(alvo, request): """Item de `assinaturas-pendentes` (§3): só existe com o PDF-alvo materializado.""" materia = alvo.materia + # `verification_url_base` e `casa_legislativa` viajam com a pendência porque + # SÓ O SAPL sabe a URL pública desta casa e o nome dela. Sem eles o AMU assina + # sem a página de autenticação — e o documento sai divergente do assinado aqui, + # que é exatamente o que a convergência dos assinadores (AB#1473) elimina. + # + # Reusamos as funções de `views_assinatura` em vez de remontar a URL aqui: elas + # são a forma canônica que o próprio SAPL usa ao chamar o microserviço. Duplicar + # a montagem é o caminho conhecido para as duas divergirem na primeira mudança. return { # Keyset da fonte: o hub le `id` no topo e devolve como `id_gt`, e a # view filtra `materia_id__gt` (o alvo e OneToOne com a materia, ver @@ -220,6 +230,9 @@ def serializar_pendencia(alvo, request): 'documento': _bloco_documento( alvo.arquivo, request, 'integracao_hub_documento_alvo', materia.pk, hash_sha256=alvo.hash_sha256), + 'verification_url_base': _construir_url_verificacao_base( + request, 'materia', materia.pk), + 'casa_legislativa': _obter_nome_casa_legislativa(), }