0008 — Adota xadm-comum-web (base transversal da casa) e desliga o security transitivo¶
Status: Aprovado · Responsável: Gustavo Madruga · Atualizado em: 2026-08-05 · Decidido em: 2026-08-05
Contexto¶
O int-pied mantinha, no pacote comum, cópias divergentes da base transversal que a casa extraiu
para a lib br.com.xadm:xadm-comum-web:0.1.0 (br.com.xadm.comum.web, publicada no Forgejo
Packages): ProblemDetail e UnifiedErrorResponseProcessor (byte-idênticos ao canônico),
VersaoProvider (mesmo papel de VersaoInfo, nome divergente) e HealthController respondendo
{status:"ok"} sem @Secured (o canônico é {status:"UP"} + @Secured(IS_ANONYMOUS)). maxsul
era o único dos 4 apps da casa que ainda não consumia a lib — sem o repo maven do Forgejo, sem
xadm-seguranca.
O refino da spec pegou dois fatos que só o artefato publicado responde: o POM da lib declara
io.micronaut.security:micronaut-security em scope compile — logo, transitivo — e o shape real
do /health. maxsul é deliberadamente aberto, sem auth (diagnóstico atrás da rede — decisões
0004/0005). No Micronaut, micronaut-security no classpath liga o SecurityFilter por default e
rejeita (401) todo endpoint não-@Secured — o que trancaria o webhook, as telas e o próprio
/health do healthcheck.
Decisão¶
Consumir a lib e remover as cópias, reconciliando nome/contrato para o canônico:
build.gradle.kts: repo maven do Forgejo (https://fonte.xadm.biz/api/packages/xadm/maven, org pública → leitura anônima) +implementation("br.com.xadm:xadm-comum-web:0.1.0").- Deletadas as cópias locais (
ProblemDetail,UnifiedErrorResponseProcessor,HealthController,VersaoProvider); imports migrados parabr.com.xadm.comum.web(WebhookController,GlobalExceptionHandler,Application,GlobalViewModel). - Security transitivo desligado em
application.yml:micronaut.security.enabled: false. Mantém a postura "tudo aberto" e deixa o@Secured(IS_ANONYMOUS)da lib inerte — não há SecurityFilter para interceptar. - Contrato do
/health:ok→UP(mudança observável). A lib mantém o campoversao(shape §5{status, versao}intacto; verificado pelo gate). Docs de operação e o teste atualizados.
Consequências¶
- Uma fonte única para a base transversal (§1.9): correção/evolução na lib chega aos 4 apps sem
divergência de cópia.
VersaoProviderdeixa de existir;VersaoInfolê o mesmo/version.properties#app.version(a taskgerarVersionPropertiesdo build permanece). micronaut-security(emicronaut-management) agora estão no classpath, apenas desligados. Um dev da Fase 2 que for introduzir auth não precisa adicionar a dependência — precisa religar o filtro (micronaut.security.enabled: true) e desenhar as regras (intercept-url-map/@Secured). O/healthdo management segueenabled: false(oHealthControllerda lib é quem serve/health).- Mudança de contrato
ok→UPé HTTP-200 nos dois casos: o healthcheck do Dockerfile (curl -f) e o Coolify/Traefik julgam por status HTTP, não pelo corpo — imunes. Nenhum monitor faz grep de"ok". - Reversível: remover a dependência e restaurar as cópias é uma edição de build + git revert; o
contrato do
/healthvolta com o literal.
Alternativas consideradas¶
- Manter security ligado +
intercept-url-mapliberando/**anonimamente — rejeitado: mais superfície de config agora, sem ganho presente (a auth da Fase 2 ainda não está desenhada). Desligar o filtro é a expressão mais enxuta da postura atual e trivial de reverter. - Excluir a transitiva no Gradle (
exclude group: "io.micronaut.security") — rejeitado: o@Securedda lib passaria a não resolver em runtime de forma silenciosa, e a casa pode vir a expor membros que dependem de tipos de security; desligar por config é mais honesto que amputar o classpath. - Pedir à casa expor security como
compileOnly/optional na lib — encaminhado como feedback §6 pro repo central (beneficia os outros apps abertos), mas não bloqueia esta adoção: desligar por config resolve no app hoje.