docs(spec): one owned outbound HTTP boundary - #33
Draft
antstanley wants to merge 1 commit into
Draft
Conversation
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
antstanley
force-pushed
the
spec/own-outbound-http-boundary
branch
from
August 5, 2026 12:01
9ffc9a2 to
6513a08
Compare
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.
Note
Stacked PR 9 of 16 — part of stack #35, which targets
main.Base: #22 (
spec/rotate-refresh-tokens) · Followed by: #18This PR's diff shows only its own change. Merge the stack bottom-up; do not merge this before its base.
Why it sits at position 9: Consolidates the two provider validators behind a shared
VerificationKeySet— the consolidation #20 explicitly declined — so it must follow the specs that change those validators.Scope of this PR
This PR currently carries the change spec. It will also carry the implementation plan and the build work for that spec — plan and code land as later commits on this same branch, so the spec, its plan, and its implementation review and merge as one unit.
Review order within the PR: spec first, then plan, then implementation.
Change spec adopting the
provider-response-boundaryhardening proposal, which a coverage audit found was almost entirely unadopted.Why it exists. Of the proposal's three "land immediately" items, only the discovery status check had been taken (by #25). Its Option 2 — a shared
ProviderTransportandVerificationKeySet— was declined by #20 ("the binding does not move"), leaving four findings with no home and two only half-covered.Proposed delta. Every provider request goes through a single
ProviderTransport(HttpsUrlin, status checked before body, bounded read,UpstreamBodyout). Every JWK becomes a verification key only through a singleVerificationKeySetwhose constructor applies the RFC 7517 §4.2–4.3 purpose filter and carries the resolved algorithm as data — replacing two driftedfind_jwkcopies, the per-request deep clone, and both per-provideralgmatches. The JWKS cache's write guard comes off the network path via an explicit single-flight permit, with a committedclippy.tomlconfiguringawait-holding-invalid-typesso the pattern cannot return. Outbound, the user-sync webhook's HMAC grows to cover a timestamp and a ULID delivery id, with a receiver contract that obliges freshness and dedup checks.Findings closed:
g2-jwk-selection-oidc,g2-jwk-selection-apple,g2-jwks-cache-lock-across-await,g1-webhook-delivery-replayable. Partials finished:g2-jwks-response-size-unbounded(success path),g2-provider-endpoint-scheme-oidc(origin constraint).The scan's remediation was wrong, and the spec says so.
g2-provider-endpoint-scheme-oidcrecommends requiring thatjwks_uri,token_endpointandrevocation_endpointshare the issuer's origin. Google's live discovery document putstoken_endpoint/revocation_endpointonoauth2.googleapis.comandjwks_urionwww.googleapis.com— none on the issuer's origin, and eTLD+1 does not rescue it. Implementing that literally breaks the repo's flagship example. The spec instead pins a declared origin set (issuer origin ∪ configured-endpoint origins ∪ an explicitendpoint_originslist), which keeps the real property — a discovery document may confirm origins, never widen them.Two findings contradict each other, and the ordering resolves it.
g2-jwks-response-size-unboundedtreats the guard-held-across-fetch as a mitigation bounding concurrent allocation to one body per provider;g2-jwks-cache-lock-across-awaittreats the same guard as the defect. Fixing the lock removes a bound the other relies on, so the byte ceiling is a hard prerequisite of the single-flight redesign.Other corrections from reading the code: only two unbounded success sinks remain, not three —
token_endpoint.rsreads oneraw_bodyshared by the error and success paths, already routed throughread_boundedby #31, so a second read there would be a bug. And migration is five call sites, not the proposal's four: both providers implementrevoke_tokenindependently.Canonical pages:
02-ports-and-adapters.md,05-provider-system.md,06-configuration.md,development-guidelines.md,canonical-types.schema.json.Drafted with the
spec-creatorplugin from a deep security scan of the repository at53cbdec9. Spec only — no source changes.