fix(e2e): map the verifier's grammar at its entry sites; single-source issuer/audience - #15
Merged
Merged
Conversation
…e issuer/audience
The verifier's {action}:{resourceType} scope grammar entered this repo
at four sites but carried its ownership statement at exactly one
(tests/abac/index.test.js). The other three absorbed it silently:
- tests/abac/application.conf: the collector pipeline — the actual
provider→verifier claim mapping — had zero comments while the
oauth.jwt block above it was fully annotated. Each block now states
which module owns the vocabulary it names.
- tests/provider/clients.yaml: read:project / read:project.member sit
under the provider-vocabulary key allowedScopes but are written in
the verifier's grammar. The header now says who owns the grammar and
who owns the strings.
- tests/shared/oauthFlow.js: verify()'s defaults and authorize()'s
default scope are two spellings of one value via the verifier's
derivation rule (auth.policy-verifier#117); the invariant is now in
verify()'s docblock.
Also flagged the resource homonym in both docblocks: authorize()'s
resource is the RFC 8707 indicator URI, verify()'s is the verifier's
dot-notation resource string. Both mirror their wire fields exactly, so
neither is renamed — the comment is the fix.
And killed the last two-definitions drift: ISSUER/AUDIENCE fallback
literals in oauthFlow.js duplicated the compose literals — the exact
pattern 4ea0484 closed for the secret. Both are now exported once from
the Makefile, interpolated into compose with :?err guards, and read via
requireEnv with no fallback. The clients.yaml audience stays as the one
deliberate copy (volume-mounted, out of interpolation's reach) and says
so.
Verified: node --check, YAML parse, compose config resolves with the
Makefile env and fails without it. Runtime path unchanged — comments
plus env plumbing only; CI's e2e run is the executable check.
Closes #12
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR improves the maintainability of the cross-component E2E suite by (1) documenting where the policy-verifier’s scope/resource grammar enters the umbrella tests, and (2) eliminating issuer/audience literal drift by single-sourcing JWT env values via the Makefile → compose interpolation → test-process env requirements.
Changes:
- Single-source
OAUTH_JWT_ISSUER/OAUTH_JWT_AUDIENCEalongsideOAUTH_JWT_SECRET(Makefile exports, compose:?guards, tests require env with no fallbacks). - Add ownership/grammar mapping comments at the verifier-grammar entry sites (
application.conf,clients.yaml, andoauthFlow.js), including disambiguation of theresourcehomonym (RFC 8707 vs verifier/verifybody field).
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tests/shared/oauthFlow.js | Removes issuer/audience fallbacks, adds verifier-grammar invariant + resource homonym documentation. |
| tests/provider/clients.yaml | Documents that allowedScopes strings are written in the verifier’s {action}:{resourceType} grammar and calls out the deliberate audience “second copy”. |
| tests/docker-compose.yml | Switches issuer/audience to required compose interpolation (${VAR:?…}) to prevent drift. |
| tests/abac/application.conf | Annotates the collector pipeline as provider→verifier claim mapping and documents vocabulary ownership. |
| Makefile | Exports OAUTH_JWT_ISSUER / OAUTH_JWT_AUDIENCE as the single source of truth for compose + test processes. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
…Makefile as source of truth The message still said make test-e2e 'exports it from tests/docker-compose.yml'; compose only interpolates the values now, the single definition is the Makefile's export block. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
6 tasks
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.
Closes #12 (parent: #11). Merge after #14 — the new comments link
docs/claims-contract.md, which #14 introduces.What
Three ownership mappings, one homonym disambiguation, one drift-pattern kill:
tests/abac/application.conf— the collector pipeline (PayloadScopeCollector/PayloadSubjectIdCollector/ResourceActionScopeRuleCollector) is the provider→verifier claim mapping machinery, and now says so: each block states which module owns the vocabulary it names, in the same style as the annotatedoauth.jwtblock above it.tests/provider/clients.yaml—read:project/read:project.membersit under the provider-vocabulary keyallowedScopesbut are written in the verifier's{action}:{resourceType}grammar. The header now names the grammar owner (auth.policy-verifier) vs the string owner (this registration), and marks the audience URL as the one deliberate second copy (volume-mounted, out of compose interpolation's reach).tests/shared/oauthFlow.js—verify()'s defaults (resource='project:1', action='read') andauthorize()'s default scope (read:project) are two spellings of one value via the verifier's derivation rule (auth.policy-verifier#117). The invariant is now inverify()'s docblock.resourcehomonym — same parameter name, two protocols in one file: authorize()'s RFC 8707 indicator URI vs verify()'s dot-notation resource string. Decision: comment-only, no rename — both params mirror load-bearing wire fields exactly (the verifier 400s unknown body keys; the RFC 8707 query param is literallyresource). Both docblocks now carry the disambiguation.oauthFlow.js's fallback literals silently duplicated the compose literals, the exact two-definitions drift 4ea0484 closed for the secret. Now: oneexport OAUTH_JWT_ISSUER/AUDIENCEin the Makefile →${VAR:?run via make test-e2e}in compose →requireEnvin the tests, no fallbacks.Verification
node --check tests/shared/oauthFlow.js, YAML parse of clients.yaml.docker compose configresolves with the Makefile-exported env and fails without it (the:?errguards work).Note: running vitest outside
make test-e2enow fails at import for issuer/audience too — intended, same doctrine the secret already had.🤖 Generated with Claude Code