🤖 AI: Fix Caching of Pub Keys - #27
Merged
Merged
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
Repeated cache directives can be ignored, and oversized cache-age values can panic the process.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Adds bounded, expiration-aware public-key caching and improves diagnostics for rejected MAuth requests.
Changes:
- Honors MAuth cache headers with TTL and LRU eviction.
- Records claimed application UUIDs on validation failures.
- Adds configurable cache capacity, tests, documentation, and a version bump.
File summaries
| File | Description |
|---|---|
src/validate_incoming.rs |
Implements expiring LRU caching and attempted identity extraction. |
src/protocol_test_suite.rs |
Updates test configuration construction. |
src/lib.rs |
Defines and initializes the process-wide cache. |
src/config.rs |
Adds cache-capacity configuration. |
src/axum_service.rs |
Logs and exposes attempted identities on rejection. |
README.md |
Documents identity diagnostics and caching behavior. |
Cargo.toml |
Adds the LRU dependency and bumps the version. |
Review details
- Files reviewed: 7/7 changed files
- Comments generated: 2
- Review effort level: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
ykitamura-mdsol
approved these changes
Sep 10, 2026
ykitamura-mdsol
left a comment
Contributor
There was a problem hiding this comment.
copilot seems to be happy 👍
Contributor
Author
|
thanks @ykitamura-mdsol! i actually reviewed this myself as well 😉 |
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.
Problem
Cached public keys never expired. After an application rotated its key,
long-running processes continued rejecting its requests until restarted.
Validation failures also omitted the application UUID claimed by the request,
making rejections harder to diagnose.
Changes
Replace the process-lifetime key map with a bounded, expiring LRU cache:
Cache-Control: max-age, accounting forAgeand time spent fetching the response.
no-cacheorno-store.unsuccessful lookups, including 404 responses, are not cached.
Cache-Controlfield lines, use the shortest repeatedmax-age, and handle unreadable headers and overflowing values safely.ConfigFileSection::pubkey_cache_capacity. Zero uses the default.Add
AttemptedMAuthIdentityfor rejection diagnostics. It records the UUIDclaimed in the signature header and is included in rejection logs. The Required
layer exposes it through the 401 response extensions; the Optional layer places
it in request extensions alongside the validation error.
This is not an authenticated identity. Trust decisions must continue to use
ValidatedRequestDetails. When both signature headers are present, diagnosticidentity extraction prefers V2.
Implementation notes
The cache remains process-wide to preserve entries across the existing service
cloning behavior. The validation services' custom
Cloneimplementationsreconstruct
MAuthInfofrom configuration;MAuthInfoitself derivesClone.The first configuration loaded determines cache capacity, matching the existing
HTTP client's initialization behavior.
Response headers are inspected before consuming the JSON body. Concurrent cache
misses are not coalesced, so simultaneous requests for an expired key can each
fetch it. A rotated key becomes available after cache expiry; this change does
not add an immediate refresh on signature failure.
Feature gating and dead-code annotations also allow Clippy to pass with and
without incoming-validation support.
Compatibility
Bump the crate version to 0.8.0. Adding
pubkey_cache_capacitybreaksexisting exhaustive
ConfigFileSectionstruct literals; addpubkey_cache_capacity: Noneto retain the default capacity.Validation
cargo fmt --checkcargo clippy --all-targets --all-features -- -D warningsaxum-servicealone, and withtracing-otel-31alonecargo test --all-features: 39 tests and 4 doctests passTests cover cache-header parsing, expiry boundaries, overflow handling, LRU
eviction, and diagnostic identity extraction. A local HTTP server test verifies
that a cached key is reused, a rotated signature initially fails, and expiry
triggers a refetch that restores successful validation. Expiry is controlled
without sleeping, and temporary signing keys are generated in memory.
Middleware tests verify that Required validation returns a 401 with the claimed
identity without invoking the handler, and Optional validation passes the
claimed identity and error to the handler without marking the request as
authenticated. Both V1 and V2 signature headers are covered.