Repository navigation
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Relatório final
1. Implementation summary
Corrigi os quatro riscos e, no fim, fiz a verificação estática que pediste — que encontrou um seam real.
A) Armadilha estrutural — eliminada na origem, não mitigada. O
InternalTokenFilterdeixou de ser@Componente passou a@Beanexplícito noOrderSecurityConfig. UmFilter@Componentno pacote base é instanciado por todos os@WebMvcTestdo módulo; como@Bean, só existe nos contextos que fazem@Import(OrderSecurityConfig.class). Os três slices que não o importam deixaram de o construir. OObjectProviderficou como segunda linha de defesa, com o porquê no Javadoc.B) Rotação em k8s — sem passo manual no chart.
INTERNAL_SERVICE_TOKEN_PREVIOUSmapeado permanentemente nos dois ramos dosecret.yaml. Razão técnica: o ESO falha o Secret inteiro se uma property referenciada não existir, por isso uma chave intermitente tornaria cada rotação numa edição de chart mais uma janela sem reconciliação.C)
require-caller-header: true. Identidade deixou de ser advisória: segredo válido semX-Internal-Callerpassa a ser rejeitado.D) Segredo legado deixou de ser porta paralela. Só é honrado enquanto não existir nenhum segredo por-caller. Assim que o
acceptednomeia um caller, o legado é ignorado — uma string partilhada por toda a plataforma não prova quem a detém e anularia a identidade que o mapa impõe. Guardei o caso do placeholder de rotação vazio, para não ser confundido com "per-caller configurado" e cortar um deployment vivo.E) Verificação estática (o que me pediste para ter atenção). Li o
InternalPurchaseVerificationIntegrationTest: envia sóX-Internal-Token, nuncaX-Internal-Caller. Se carregasse a flag nova, os 3 happy-paths viravam 401. Confirmei que não carrega:order-service/src/test/resourcesnão defineapplication.security.internal.*e a flag vive só no config-service. Nada quebra. Mas isso expôs um seam que eu introduzi — o product-service passa a enviar o header sempre, inclusive contra uma config ainda legada — e escrevi o testelegacyTokenAcceptsAnnouncedCallerpara o cobrir.F) Meta. Restrições no hook
UserPromptSubmit+ memória mandatória no topo do índice. Após a tua interrupção corrigi a regra nos dois sítios: Claude não corre testes — corre o utilizador. Edocs//.claude/no.gitignoreestá registado como deliberado, com instrução de nunca mais aparecer como risco.2. Files changed
Código (4):
OrderSecurityConfig.java(novo@Bean internalTokenFilter);InternalTokenFilter.java(sem@Component);InternalTokenAutoConfiguration.java(legado só sem per-caller);InternalPurchaseVerificationIntegrationTest.java(+1 teste, +1 import).Testes novos (1 ficheiro):
tenant-context/.../InternalTokenAutoConfigurationTest.java(6 testes).Config (4):
order-service.yml(require-caller-header: true);helm/.../secret.yaml,values.yaml,values-staging.yaml.Meta (4):
.claude/hooks/mandatory-constraints.ps1(novo);.claude/settings.json;.claude/memory/feedback_mandatory_constraints_all_tasks.md(novo);MEMORY.md+project_s2s_hardening_2026_07_26.md.3. Os bugs reproduziram-se antes do fix?
A armadilha estrutural: sim — foi o teu output com os 4 testes a rebentar. Diagnosticada e agora eliminada por construção.
B, C e D não são bugs reproduzíveis — são endurecimento de configuração e política; não havia falha a provocar.
O seam do
X-Internal-Callerno caminho legado: não reproduzido — encontrado por leitura de código, não por execução. Escrevi o teste que o prova; a prova é tua.Sobre execução de testes: corri
mvn testantes de me travares (order-service212 verdes,tenant-context28 verdes, reator dos 3 módulos BUILD SUCCESS). Não devia ter corrido — regra já corrigida. As alterações desta última fase (o teste novo no IntegrationTest e o import) não foram compiladas nem corridas por mim.mvn test -pl tenant-context,order-service,product-service,gateway-api-service4. Remaining risks
legacyTokenAcceptsAnnouncedCallere o import deInternalTokenAuthenticationFilterno IntegrationTest não passaram portest-compile. É o primeiro sítio onde algo pode falhar.require-caller-header: truecria acoplamento de deploy. Order-service com esta config + product-service numa imagem antiga sem o header ⇒ 401 na verificação ⇒ 503 no POST de review. Têm de sair juntos (já obrigatório pelotenant-context). Rollback: pôr a flag afalse.secret/ecommerce/shared:internal_service_tokeneinternal_service_token_previous(esta pode ser vazia). Sem a segunda, o ESO não sincroniza e os pods não arrancam.require-caller-header: trueatravés da cadeia HTTP real. Está coberto em duas camadas adjacentes (properties→authenticator noInternalTokenAutoConfigurationTest; authenticator→401/200 noInternalTokenFilterTest), mas não na composição. Não criei outra classe Testcontainers para isso — decisão de custo/risco, e digo-o em vez de o esconder.tenant-context, emvn install -pl tenant-contextantes de qualquer build por-módulo.