release: v0.7.0 - #142
Merged
Merged
release: v0.7.0#142
Conversation
Writes `## [0.7.0] — 2026-09-24` from `git log v0.6.0..HEAD`, per docs/release-policy.md R2 (em dash, as the file already uses). The range and where each commit is recorded are in the pull request's description. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The R6 audit of the v0.7.0 cut checks README claims about o3co/auth.provider
against its releases (latest v0.15.0). Three were stale:
- Under client authentication, the README said the provider pins the
introspected token's audience to the calling client's own identity, and a
note said a companion change would widen it to
`allowedAudiences ∪ {clientId}` — "until it lands". It landed in
auth.provider v0.12.0 (f0bb9ef7). The paragraph now states the pin as
released, with what earlier releases did, and the note is gone.
- The access-token lifetime key is `oauth.accessToken.defaultExpiresIn`;
`expiresIn` is what older providers used and newer ones keep as a
deprecated alias. The 0.6.0 cut kept `expiresIn` because the rename was
not yet released; it is now.
English and Japanese alike. A separate commit so it can be dropped on its
own, as in the 0.6.0 cut.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…oken The comment above the introspection client's `redirect: "manual"` said a cross-origin redirect "strips" the request's credential. `fetch` drops the `Authorization` and `Cookie` headers when a redirect crosses origins; a 307 or 308 still re-sends the body, and the introspection body is `token=<the caller's token>`. So a followed cross-origin 307/308 carried the caller's token to another origin — one more reason F43 refuses a redirect, and the reason the v0.7.0 Security entry gives. Comment only. Found while writing the v0.7.0 section. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Several changelog and README statements remain inconsistent with the documented audience and redirect behavior.
Get a fresh assessment by requesting another Copilot review.
Review effort: Lite
Findings: 2
Open (2)
What changed in this PR
Documents the v0.7.0 release, updates provider guidance, and corrects redirect behavior documentation.
Changes:
- Adds categorized v0.7.0 changelog entries.
- Updates English and Japanese README guidance.
- Clarifies cross-origin introspection redirects.
| File | Summary |
|---|---|
CHANGELOG.md |
Adds v0.7.0 release notes and migration guidance. |
README.md |
Updates provider audience and token-lifetime guidance. |
README.ja.md |
Mirrors the provider guidance updates in Japanese. |
src/modes/validation/introspection-client.mts |
Corrects redirect behavior documentation. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Copilot on #142: the previous commit restated the introspection audience pin as auth.provider has released it since v0.12.0 — the client's own `client_id` and its `allowedAudiences` — but two sentences around it still assumed the older pin. The challenge section said a token whose `aud` "does not name this proxy's client" is refused however fresh it is; the resource example said an "unrelated" `client_id` refuses every resource-audience token. Both now name the condition that actually refuses: an `aud` that is neither the client nor an audience registered in its `allowedAudiences`. English and Japanese alike. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
y1o1
added a commit
to o3co/auth
that referenced
this pull request
Sep 24, 2026
…tagging (#39) PROXY_REV and VERIFIER_REV move to the merge commits of o3co/auth.proxy#142 and o3co/auth.policy-verifier#268; PROVIDER_REV stays at v0.15.0. E2E green on run 35963975620.
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.

Writes
## [0.7.0] — 2026-09-24fromgit log v0.6.0..f42f042(release-policy R2; em dash, as the file already uses), inserted directly above## [0.6.0]. Each entry is written from the PR description that says what an operator will notice, from #95's comments and from #140's correction comment, and each claim was checked against the code atf42f042(a few measured on Node 26: whatfetchreplays across a redirect,fetchon adata:URL,JSON.stringifyof afetchTypeError). Three commits: the section; then, each separate so it can be dropped on its own, the README sentences the R6 audit found describing auth.provider as it was before v0.12.0 and v0.14.0, and a code comment that misstated whatfetchdoes with a cross-origin redirect (both below).Two commit messages in the range say things that later commits in the same range made untrue, and the section does not repeat them.
8f84104(F7) says "every other introspection failure is still 500", which F42 (3a6bdf4) replaced.2702944(F8) says validation "still sets no redirect option — filed as F43", and F43 (2923655) fixed that.What 0.7.0 contains
Changed: ten BREAKING entries, each with what an operator sees and what to do:
401to introspection is502 Provider Configuration Error.502 Bad Gateway;500is kept for the proxy's own errors.502 Provider Configuration Error.401carriesWWW-Authenticate: Bearer error="invalid_token".502 provider_config_error. A same-origin307/308used to succeed.200counts as a successful session grant.401 invalid_clientis502 provider_config_error, not401 session_required."x-request-id"torequestId, every line gets anevent, and a caller-caused401logs at info.F30 and #139 carry the
BREAKING CHANGE:footer without!in the subject, which is why the list uses both signals.Changed: operator-visible but not breaking.
error.Authorizationis stripped when stripping is on.Authorizationthat gets overwritten now logsinjection.authorization_override.921bd6c: an emptyAuthorizationgoes upstream in canonical casing. The commit is typeddocs(router):but it changes behaviour.action: "forward_stripped"is logged, and thecookie_rejectedmessage changed.200refusal is reworded.zod4.6.2 → 4.6.5.INJECTION_TIMEOUT_MS) is part of the F47 entry.Added.
depsseam's properties that 0.6.0 could not reach: F32/F41 (a supplied client's failures logged by error code, an undeclared code logged) and F33 (the session cache keyed by the grant context).VALIDATION_REALM/auth.validation.realm, and a400challenge shaped by what was sent.depson both routers and a per-router introspection cache. This is described as a library seam, not operator configuration: the package is private and ships as the image.Security.
data:URL admitted every token in 0.6.0.18b0646+2bbb83e: logged errors pass through an allowlist, the allowlist also coverserr, and the userinfo redaction now handles raw forms.F30 and #140 are also BREAKING under Changed. The two places refer to each other rather than repeating each other.
Fixed.
bb3c1f9: a single-flight whose fetcher throws synchronously no longer stays pinned.Removed.
jsonwebtokenand@types/jsonwebtoken(F24).Dev-only bumps (#129) get no entry.
Why 0.7.0: ten breaking changes → minor, while the major is 0.
Two places where the source disagrees with the brief the section was written from
{ "x-request-id", error: e }. Pino serialises onlyerr, so afetchTypeError came out as"error":{}, with no message (F48 measured this, andJSON.stringifyof the refusal gives{}). The message first reached the log incee6959(F48, this range), with a redaction that missed a space or an@.2bbb83eandcdcc8cdclosed that before any tag. So the Security entries say what 0.6.0 actually exposed: adata:URL admitted every token, and a userinfo URL failed every request. They say that 0.5.0 and 0.6.0 never wrote such a password. The allowlist and redaction are described as properties of the new error logging, not as a fix of a released leak.event" is too broad. The startup and shutdown lines have none. The entry says "every request, decision and failure line".Judged not breaking
c1318c2) changes anactionvalue, and only wherestripInboundAuthorizationis on, plus one message string. Its commit carries no breaking marker; it is under Changed with an action, so a dashboard keyed onaction: "forward"is told to add"forward_stripped".59e5a7c) adds a realm key and, for a deployment that sets none, one header: a malformedBearernow getsWWW-Authenticate: Bearer error="invalid_request"on its400. That is the400counterpart of F29, which is marked breaking; F45's commit is not. The entry under Added says so, so a reader can hold it to F29's standard.Range
git log v0.6.0..f42f042 --oneline(51 commits) and where each commit is recorded:Reviews
Reviewed before opening by a Claude reviewer (completeness, and every claim against the code at
f42f042andv0.6.0, with measurements on Node 24 and 26) and by an Opus reviewer standing in for Codex (security and breaking-change pass). Codex review not yet run: it is at its usage limit until 2026-09-30;codex review --base f42f042will be run then, and any finding filed. Their findings — three statements about 0.6.0 that were wrong, an alert claim that was wrong, an F8 action that could not fix the one case that breaks, and wording points — are folded into the section, and the three entries describing states 0.6.0 could not reach now sit under Added as properties of the new seam.R6 audit
git grep -i -E "(removed|deprecated|planned).*(1\.0 GA|next major|next release|in v[0-9]+\.[0-9]+)": every match is indocs/release-policy.md, where it is an example or the rule. There is nothing to resolve.git grep -n '"this release' -- src config: no match.git grep -n -i unreleased -- README.md README.ja.md config docs src(excluding the policy and[Unreleased]): no match.1.0 GA,next major/minor/release,this release,future release,upcoming,unreleased,will be,removed in,until it landsand version literals. Onethis releasewas rewritten to0.7.0. The remaining version literals are0.6.0(released),zod4.6.2 → 4.6.5, and RFC section numbers. No auth.provider version is named in the section.realmandintrospect.urlboot errors,Bad Gateway,introspect endpoint redirected, andprovider rejected the proxy's client (client_id)) contain no versions.release: v0.7.0.generate_release_noteslists PR titles and would not show F30 or fix: log requestId and event in both modes, and a caller-caused 401 at info (#134) #139 as breaking. That section is prepared separately and gets prepended aftergh release create.Provider claims in README.md / README.ja.md, checked against auth.provider tags (latest release v0.15.0). They are fixed in this PR's second commit, separate so it can be dropped on its own, as #92 did with 9db4ce8.
README.md:108/README.ja.md:103("A companion change inauth.providerwidens this pin toallowedAudiences ∪ {clientId}… Until it lands, only a token whoseaudis exactly the caller'sclient_id…" / 「それが入るまでは」). This landed in auth.provider v0.12.0: #506,f0bb9ef7.git tag --containsgives v0.12.0 as the first tag, and the commit says "Introspection's audience pin is the caller'sallowedAudiences∪{clientId}". The "until it lands" sentence is false for every provider release since v0.12.0. release: v0.6.0 #92 already flagged the JA sentence as a follow-up.README.md:97/README.ja.md:92say the provider pins the audience "to the calling client's own identity" / 「呼び出し元クライアント自身の識別子に固定する」. Since v0.12.0 the pin isallowedAudiences ∪ {clientId}. The bullet two lines below ("register that audience in the client'sallowedAudiences") already assumes the wider pin.README.md:152/README.ja.md:147useoauth.accessToken.expiresIn. auth.provider #591 (e354ac36, first in v0.14.0) makes that key a deprecated alias ofoauth.accessToken.defaultExpiresIn. It still works, and the standalone composition warns at boot when only the old key carries a non-default value. release: v0.6.0 #92 keptexpiresInbecause #591 was unreleased at the time. Now that it is released, the README should namedefaultExpiresInand mention the alias for providers before v0.14.0.README.md:267/README.ja.md:249("A provider that includes auth.provider#588 also caps a jwt-bearer token's lifetime …"). #588 (f40df5f8) is in v0.14.0 and v0.15.0. The sentence is true as a conditional. It could now say "auth.provider v0.14.0 and later" (R1 allows released versions).README.md:146–150/README.ja.md:141–143, the UserSession tracking section. The session grant requires a live tracked session whosesubmatches and returns400 invalid_grantotherwise. It stampssid, issues no refresh token, and answers an unauthenticated session401 unauthorized. The logout invalidation and the operator runbook exist (packages/oauth/src/grants/session.mts,packages/session/src/module.mts,docs/operator-runbook.mdat v0.15.0). F47's claim thatinvalid_clientcomes only from the client check holds at v0.15.0.README.md:233: the jwt-bearer grant readsscope, and readsresourceunderoauth.resourceIndicator.enabled. Also accurate: the rate-limit section's<endpoint>:ip:<ip>key, the 60/60s default, and thememoryRateLimiter.limits/redisRateLimiter.limits/defaultLimitkeys (packages/core/config/reference.conf,packages/core/src/ratelimit/guard.mtsat v0.15.0).One code comment was inaccurate — fixed in the third commit (comment only).
src/modes/validation/introspection-client.mts(the comment aboveredirect: "manual") says that across originsfetch"strips" the request's credential.fetchstrips theAuthorizationheader, but a307/308re-sends the body, and the body istoken=<the caller's token>. I measured this on Node 26. The Security entry states it correctly.Verification
release: v0.7.0(CHANGELOG.md),docs: the provider behaviour the README describes, as released(README.md,README.ja.md), anddocs(validation): a cross-origin redirect drops the header, not the token(a comment insrc/modes/validation/introspection-client.mts).Release order
PROXY_REVto the merge commit and runs the umbrella E2E.v0.7.0at that commit.🤖 Generated with Claude Code