fix(rust): close the gaps between a verified credential and a trusted one - #531
Conversation
… was sent with The signature bound only the Content-Digest header string, so the digest a peer signed was never checked against the bytes that arrived. Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
A JWKS publisher that sets use, key_ops, or alg has stated the key's purpose, and ignoring that lets a key be conscripted into a job it was never offered for. Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
…t one that does not The docs promised a JetStream-backed production store in trogon-aauth-person; no such implementation ships, which understates the multi-replica gap. Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
…hed confirmation claim Three mint sites embedded a caller-supplied JWK verbatim into cnf and signed it, so one careless caller could publish a private key in a token. Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
Dedup keyed on an unsigned header an attacker can vary freely, and the stream had no duplicate window, so the guarantee was absent rather than weak. Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
…was asked for A typo in the signing key parsed to None and read as verification-not-wanted, so the misconfiguration silently cost the very check it was meant to enable. Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
Code signing is the wrong place to accept the permissive default, which lets one signature validate under more than one public key. Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
…verifies it The validator was built from the token's own header, so its algorithm check compared the header against itself and admitted whatever was asserted. Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
…he corpus claims exists Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
PR SummaryHigh Risk Overview Verification and issuance: OIDC and AAuth JWT paths now enforce deployment algorithm allowlists and honor JWK Gateway and ingress: Tier-3 bundle signing env parsing distinguishes unset vs invalid pubkey; an invalid configured key refuses to load policy bundles instead of running unverified wasm. GitLab webhooks set JetStream Hygiene: JWT/bearer types use redacted Reviewed by Cursor Bugbot for commit b771fb5. Bugbot is set up for automated code reviews on this repo. Configure here. |
|
Warning Review limit reached
Next review available in: 10 minutes You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
WalkthroughThe pull request defines external OIDC federation, validates confirmation and token JWK metadata, verifies HTTP content digests, distinguishes gateway signing-key states, strengthens signed-bundle verification, redacts credential debug output, reconciles JetStream streams, and propagates signed GitLab webhook identifiers. ChangesExternal OIDC federation
Confirmation-key validation
Gateway policy verification
AAuth request and token verification
GitLab webhook delivery
Credential debug redaction
JWKS publisher validation
Estimated code review effort: 5 (Critical) | ~90 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 6
🧹 Nitpick comments (1)
rsworkspace/crates/platform/trogon-gateway/src/source/gitlab/server/tests.rs (1)
371-371: 🗄️ Data Integrity & Integration | 🔵 Trivial | 🏗️ Heavy liftExercise duplicate rejection, not only header construction.
This test sends one request and inspects
NATS_MESSAGE_ID. It does not send a replay or assert that JetStream suppresses the second delivery. Add a test that submits the same signed request twice within the configured duplicate window and asserts one stored delivery. Use a JetStream-backed test or a mock that models duplicate handling. Theduplicate_windowsetting is stream-level behavior. (docs.rs)Also applies to: 397-407
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@rsworkspace/crates/platform/trogon-gateway/src/source/gitlab/server/tests.rs` at line 371, The test dedup_id_comes_from_signed_webhook_id_not_idempotency_key currently verifies only the NATS_MESSAGE_ID header; extend it to submit the identical signed request twice within the configured duplicate_window and assert that JetStream stores or delivers only one message. Use a JetStream-backed fixture or a duplicate-aware mock, and preserve the existing assertion that the deduplication ID comes from the signed webhook ID.Sources: Coding guidelines, MCP tools
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/adr/0038-agent-identity-crypto-suite.md`:
- Around line 158-170: Update the RSA-2048/RS256 profile in ADR 0038 to define
the key as signing material owned by the separate federation issuer from
ADR#0053, not as an additional key bound to an agent identity. Preserve agent
identity only in assertion claims, and add issuer-specific custody and rotation
guidance distinct from agent key management.
In `@docs/adr/0053-external-oidc-federation-surface.md`:
- Around line 144-150: Update the offboarding discussion in the paragraph
beginning “Standing across the boundary” to distinguish future exchanges from
already-issued tokens: state that assertion TTL and deletion of the Decision 3
binding bound future exchanges, while an existing external resource token
remains valid until its own expiry or revocation by the external provider.
Preserve the requirement to revoke on both planes.
In `@rsworkspace/crates/a2a/a2a-auth-callout/src/credentials/oidc.rs`:
- Around line 283-295: Replace the formatted InvalidCredentials returns in the
OIDC verification flow with dedicated typed CredentialError variants that retain
the unsupported algorithm, JWK kid, and rejection reason. Add the variants to
CredentialError and render their user-facing messages in its Display
implementation, updating the algorithm and jwk_permits_verification_with checks
without changing other credential failures.
In `@rsworkspace/crates/aauth/trogon-aauth-verify/src/http_pop.rs`:
- Around line 551-565: Update parse_sha256_content_digest to parse raw as a
complete Structured Fields Dictionary, accepting sha-256 Items with parameters
and applying last-member-wins behavior for duplicate sha-256 keys. Use the
existing Structured Fields parser if available, otherwise implement equivalent
Dictionary parsing, and add tests covering parameterized Items and duplicate
keys.
In `@rsworkspace/crates/platform/trogon-gateway/src/source/gitlab/server.rs`:
- Line 90: Update the GitLab stream setup around the get_or_create_stream call
so an existing GITLAB stream is reconciled with duplicate_window set from
config.timestamp_tolerance. When creation does not apply the value, call the
NatsJetStreamClient update_stream path for the existing stream while preserving
normal creation behavior and error propagation.
In `@rsworkspace/crates/platform/trogon-identity-types/src/aauth/mod.rs`:
- Around line 54-70: The Cnf::public constructor currently permits incomplete
public JWKs, and the public Cnf::jwk field bypasses validation. Make jwk
private, introduce a distinct input type for issuer-side construction that
converts into a typed validated public-JWK value, and validate all required
public parameters for each supported kty before constructing Cnf. Keep
peer-supplied claim deserialization separate from Cnf::public so every
issuer-created Cnf is guaranteed usable.
---
Nitpick comments:
In
`@rsworkspace/crates/platform/trogon-gateway/src/source/gitlab/server/tests.rs`:
- Line 371: The test dedup_id_comes_from_signed_webhook_id_not_idempotency_key
currently verifies only the NATS_MESSAGE_ID header; extend it to submit the
identical signed request twice within the configured duplicate_window and assert
that JetStream stores or delivers only one message. Use a JetStream-backed
fixture or a duplicate-aware mock, and preserve the existing assertion that the
deduplication ID comes from the signed webhook ID.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 9aef4a2d-3713-47f2-873f-58b0a2ed70b0
📒 Files selected for processing (33)
docs/adr/0017-aauth-agent-authentication.mddocs/adr/0036-agent-self-certifying-identity.mddocs/adr/0038-agent-identity-crypto-suite.mddocs/adr/0049-revocation-latency-target.mddocs/adr/0053-external-oidc-federation-surface.mddocs/adr/index.mdrsworkspace/crates/a2a/a2a-auth-callout/src/constants.rsrsworkspace/crates/a2a/a2a-auth-callout/src/credentials/oidc.rsrsworkspace/crates/a2a/a2a-auth-callout/src/credentials/oidc/tests.rsrsworkspace/crates/a2a/a2a-gateway/src/runtime/env.rsrsworkspace/crates/a2a/a2a-gateway/src/runtime/env/tests.rsrsworkspace/crates/a2a/a2a-gateway/src/runtime/policy_stack.rsrsworkspace/crates/a2a/a2a-gateway/src/runtime/policy_stack/tests.rsrsworkspace/crates/a2a/a2a-redaction/src/signed_bundle/verify.rsrsworkspace/crates/aauth/trogon-aauth-as/src/error.rsrsworkspace/crates/aauth/trogon-aauth-as/src/mint.rsrsworkspace/crates/aauth/trogon-aauth-person/src/error.rsrsworkspace/crates/aauth/trogon-aauth-person/src/mint.rsrsworkspace/crates/aauth/trogon-aauth-verify/Cargo.tomlrsworkspace/crates/aauth/trogon-aauth-verify/src/http_pop.rsrsworkspace/crates/aauth/trogon-aauth-verify/src/http_pop/tests.rsrsworkspace/crates/aauth/trogon-aauth-verify/src/replay.rsrsworkspace/crates/aauth/trogon-aauth-verify/src/token.rsrsworkspace/crates/aauth/trogon-aauth-verify/src/token/tests.rsrsworkspace/crates/platform/trogon-gateway/src/source/gitlab/constants.rsrsworkspace/crates/platform/trogon-gateway/src/source/gitlab/server.rsrsworkspace/crates/platform/trogon-gateway/src/source/gitlab/server/tests.rsrsworkspace/crates/platform/trogon-gateway/src/source/gitlab/signature.rsrsworkspace/crates/platform/trogon-identity-types/src/aauth/mod.rsrsworkspace/crates/platform/trogon-identity-types/src/aauth/tests.rsrsworkspace/crates/platform/trogon-identity-types/src/constants.rsrsworkspace/crates/platform/trogon-jwks-publisher/src/provider.rsrsworkspace/crates/platform/trogon-jwks-publisher/src/provider/tests.rs
Code Coverage SummaryDetailsDiff against mainResults for commit: b771fb5 Minimum allowed coverage is ♻️ This comment has been updated with latest results |
… log A bearer token in a log is a usable credential for the rest of its lifetime, and these two carried a redacted Display next to a derived Debug, which is the form tracing actually records. Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
The neighbouring wire claim type already hand-redacts what it prints; the inbound assertion, the minted user JWT, and the signed response carrying it did not, and each is replayable for as long as it is valid. Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
The builder already exists so misconfiguration fails at startup rather than remotely, but it vetted only the filename, leaving a rotation that reuses or omits a kid to surface as a verification failure at the consumer with nothing visible on this side. Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
…rovisioned stream A stream created before the dedup window was paired with the signature timestamp tolerance kept JetStream's default window, so the declared bound never took effect where it mattered most: a deployment that had already been running. Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
Recording the RSA profile under a blanket agent-binding claim invited an implementation that binds one issuer key per agent, when the identity belongs in the assertion claims and the key's custody belongs to the issuer. Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
… edge Naming TTL and unbinding as the only bounds left the residual window ambiguous, and an operator sizing an offboarding procedure from it would have underestimated how long an already-issued external token keeps working. Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
…operator tuned Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
…an issued token Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
…llows Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
There was a problem hiding this comment.
Actionable comments posted: 6
♻️ Duplicate comments (1)
rsworkspace/crates/platform/trogon-identity-types/src/aauth/mod.rs (1)
73-86: 🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy liftValidate public-key material, not only member presence.
Cnf::publicaccepts unusable keys such as a P-256 JWK with short coordinates ("x": "AAA"), invalid base64url data, an unsupported curve, or an unusable RSA modulus. The token can then be minted successfully, but downstream key construction and proof-of-possession verification fail.Parse and validate each supported key type during construction, or convert a distinct issuer input type into typed key-specific domain values. Keep permissive inbound claims in a separate wire type.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@rsworkspace/crates/platform/trogon-identity-types/src/aauth/mod.rs` around lines 73 - 86, Update Cnf::public to validate complete public-key material for each supported kty, not merely non-empty required members. Parse base64url coordinates and modulus, reject malformed or unusable values and unsupported curves, and ensure RSA parameters satisfy key-construction requirements before returning Ok; keep permissive inbound claims separate from the validated typed representation.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@rsworkspace/crates/a2a/a2a-auth-callout/src/credentials/oidc/tests.rs`:
- Around line 593-596: Strengthen the debug-redaction assertions in the token
test around token and its dbg representation: verify the full compact JWT and
each unique segment (including hhh, ppp, and sss) are absent from dbg, while
retaining the assertion that <redacted> is present and the original as_str value
remains unchanged.
In `@rsworkspace/crates/platform/trogon-identity-types/src/aauth/mod.rs`:
- Around line 37-42: Replace the derived Debug implementation on Cnf with a
custom redacted formatter that never emits the embedded jwk Value or private JWK
members, while preserving the existing Clone, PartialEq, Eq, Serialize, and
Deserialize derives. Add a regression test alongside the inbound-deserialization
test that formats a Cnf containing a private key member such as d and verifies
the debug output does not contain that sensitive value.
In `@rsworkspace/crates/platform/trogon-jwks-publisher/src/publisher.rs`:
- Around line 78-114: Replace the standalone validate_selectable_by_kid function
with a PublishableJwkSet domain type whose TryFrom<JwkSet> implementation
enforces duplicate and missing key-id rules. Update JwksPublisherConfig.entries
and with_jwk_set to store and construct PublishableJwkSet values, and expose
only an immutable JwkSet view where serialization requires the raw set.
In `@rsworkspace/crates/platform/trogon-nats/src/jetstream/client.rs`:
- Around line 60-62: Update the stream reconciliation flow around cached_info,
merge, and context.update_stream so it cannot unconditionally write a stale full
configuration. Use the available conditional update mechanism, or reread the
stream and retry reconciliation when the version changes, preserving concurrent
operator-managed fields such as num_replicas, storage, and limits.
In `@rsworkspace/crates/platform/trogon-nats/src/jetstream/mocks.rs`:
- Around line 258-260: Replace the string-backed MockError constructions in the
stream-creation failure paths, including the corresponding block around the
second referenced location, with a typed MockError variant such as
MockError::SimulatedStreamCreation. Update the MockError definition if needed so
tests can structurally match this failure without relying on String payloads.
In `@rsworkspace/crates/platform/trogon-nats/src/jetstream/traits.rs`:
- Around line 41-48: Replace the orchestration-oriented
create_or_reconcile_stream method in the infrastructure trait with separate
passthrough operations for reading, creating, and updating streams, removing the
merge callback from the trait API. Move the Get-Merge-Update workflow and
merge-field ownership into the GitLab provisioning implementation, updating its
callers to compose the individual operations.
---
Duplicate comments:
In `@rsworkspace/crates/platform/trogon-identity-types/src/aauth/mod.rs`:
- Around line 73-86: Update Cnf::public to validate complete public-key material
for each supported kty, not merely non-empty required members. Parse base64url
coordinates and modulus, reject malformed or unusable values and unsupported
curves, and ensure RSA parameters satisfy key-construction requirements before
returning Ok; keep permissive inbound claims separate from the validated typed
representation.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 7657b514-e1ec-435a-afea-547b68d9efc9
📒 Files selected for processing (46)
docs/adr/0038-agent-identity-crypto-suite.mddocs/adr/0053-external-oidc-federation-surface.mdrsworkspace/crates/a2a/a2a-auth-callout/src/caller_jwt_header.rsrsworkspace/crates/a2a/a2a-auth-callout/src/caller_jwt_header/tests.rsrsworkspace/crates/a2a/a2a-auth-callout/src/credentials/oidc.rsrsworkspace/crates/a2a/a2a-auth-callout/src/credentials/oidc/tests.rsrsworkspace/crates/a2a/a2a-auth-callout/src/denial_category.rsrsworkspace/crates/a2a/a2a-auth-callout/src/error.rsrsworkspace/crates/a2a/a2a-auth-callout/src/jwt/mod.rsrsworkspace/crates/a2a/a2a-auth-callout/src/jwt/tests.rsrsworkspace/crates/a2a/a2a-auth-callout/src/wire/callout_auth_response_claims.rsrsworkspace/crates/a2a/a2a-auth-callout/src/wire/callout_auth_response_claims/tests.rsrsworkspace/crates/a2a/a2a-gateway/tests/aauth_roundtrip.rsrsworkspace/crates/a2a/a2a-identity-types/src/jwt.rsrsworkspace/crates/a2a/a2a-identity-types/src/jwt/tests.rsrsworkspace/crates/aauth/trogon-aauth-as/src/pending/tests.rsrsworkspace/crates/aauth/trogon-aauth-as/src/policy/tests.rsrsworkspace/crates/aauth/trogon-aauth-as/src/request/tests.rsrsworkspace/crates/aauth/trogon-aauth-as/src/server.rsrsworkspace/crates/aauth/trogon-aauth-as/src/test_support.rsrsworkspace/crates/aauth/trogon-aauth-person/src/agent/tests.rsrsworkspace/crates/aauth/trogon-aauth-person/src/http/tests.rsrsworkspace/crates/aauth/trogon-aauth-person/src/pending/tests.rsrsworkspace/crates/aauth/trogon-aauth-person/src/server.rsrsworkspace/crates/aauth/trogon-aauth-person/src/server/tests.rsrsworkspace/crates/aauth/trogon-aauth-person/src/store/tests.rsrsworkspace/crates/aauth/trogon-aauth-person/tests/person_server_e2e.rsrsworkspace/crates/aauth/trogon-aauth-sdk/src/tests.rsrsworkspace/crates/aauth/trogon-aauth-sdk/src/verify_response.rsrsworkspace/crates/aauth/trogon-aauth-sdk/src/verify_response/tests.rsrsworkspace/crates/aauth/trogon-aauth-verify/src/http_pop.rsrsworkspace/crates/aauth/trogon-aauth-verify/src/http_pop/tests.rsrsworkspace/crates/aauth/trogon-aauth-verify/src/nats_pop.rsrsworkspace/crates/aauth/trogon-aauth-verify/src/token.rsrsworkspace/crates/aauth/trogon-aauth-verify/tests/nats_pop_roundtrip.rsrsworkspace/crates/platform/trogon-gateway/src/source/gitlab/server.rsrsworkspace/crates/platform/trogon-gateway/src/source/gitlab/server/tests.rsrsworkspace/crates/platform/trogon-identity-types/src/aauth/mod.rsrsworkspace/crates/platform/trogon-identity-types/src/aauth/tests.rsrsworkspace/crates/platform/trogon-identity-types/src/constants.rsrsworkspace/crates/platform/trogon-jwks-publisher/src/provider/tests.rsrsworkspace/crates/platform/trogon-jwks-publisher/src/publisher.rsrsworkspace/crates/platform/trogon-jwks-publisher/src/publisher/tests.rsrsworkspace/crates/platform/trogon-nats/src/jetstream/client.rsrsworkspace/crates/platform/trogon-nats/src/jetstream/mocks.rsrsworkspace/crates/platform/trogon-nats/src/jetstream/traits.rs
🚧 Files skipped from review as they are similar to previous changes (9)
- rsworkspace/crates/platform/trogon-jwks-publisher/src/provider/tests.rs
- rsworkspace/crates/aauth/trogon-aauth-verify/src/token.rs
- rsworkspace/crates/platform/trogon-gateway/src/source/gitlab/server.rs
- rsworkspace/crates/a2a/a2a-auth-callout/src/credentials/oidc.rs
- rsworkspace/crates/aauth/trogon-aauth-verify/src/http_pop/tests.rs
- rsworkspace/crates/aauth/trogon-aauth-verify/src/http_pop.rs
- docs/adr/0038-agent-identity-crypto-suite.md
- docs/adr/0053-external-oidc-federation-surface.md
- rsworkspace/crates/platform/trogon-gateway/src/source/gitlab/server/tests.rs
…on hides Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
…he logs Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
…unrepresentable Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
… for Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
…owns Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
…ready agrees Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
…ho wins a race Whichever concurrent create the scheduler and the server ordered first decided whether the arm under test ran at all, so the suite failed on CI for reasons the code under test had nothing to do with. Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
… to skip The last-wins note read as a promise to recover from a member that does not parse, and nothing held the parser to refusing one, so a later reader could have relaxed it into burying an unreadable digest under a trailing good one. Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
…error-naming convention Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
…can hide Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
…o step over Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
There are 2 total unresolved issues (including 1 from previous review).
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 19fe392. Configure here.
…t-wins behind Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>

Summary
Every change here came out of auditing our own credential surfaces against the siblings we had already hardened, and finding places where a successful verification did not establish what the code downstream assumed it had established. The gaps were consistent in shape: a signature covering less than the request it arrived with, a publisher's declared key purpose accepted but never honored, a token free to nominate the algorithm that verifies it, a fail-open path where the operator had explicitly asked for verification, and a dedup window keyed on something a replay could vary.
Note
ADR 0053 records the external federation surface these verifiers now front, and the edits to the existing ADRs bring the corpus back in line with what is actually built rather than what was once planned.