Skip to content

test(ci): cover the person route, per-issuer audiences and exact trust - #247

Closed
alukach wants to merge 7 commits into
feat/platform-trustfrom
test/sts-ci-gaps
Closed

alukach wants to merge 7 commits into
feat/platform-trustfrom
test/sts-ci-gaps

Conversation

@alukach

@alukach alukach commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

Note

Stacked on #237: the new person-route tests rely on #237's rule that AUTH_ISSUER is dropped from PLATFORM_ISSUERS. Until #237's branch has its latest review fixes pushed, this diff also shows those five commits; the change here is the last two commits.

What I'm changing

This closes test gaps found in the review of #237:

  • The person route had no CI test with a validly signed token. Since GitHub became a platform issuer, nothing in CI checked the person issuer's issuer and audience gate, its signature check or its credential sealing.
  • Per-issuer audiences weren't observable. CI gave the person issuer and GitHub the same audience. A platform path that checked the person audiences instead of GitHub's own would have passed.
  • The stub trusted any subject in this repository, matched by prefix. source.coop matches a trust on the exact (account, issuer, subject).
  • A 200 saying {"trusted": false} had no test.
  • The staging smoke test could fail instead of skip. It minted a token whenever FEDERATION_TEST_AUDIENCE was set. Without FEDERATION_TEST_TRUST_ACCOUNT, the token then named the stub's account, which staging doesn't have.

How I did it

  • Second worker. ci.yml starts a second wrangler dev on port 8788 with --var AUTH_ISSUER:<GitHub> --var AUTH_AUDIENCE:source-data-proxy-ci, so CI's token is a person token there. tests/test_person_route.py exchanges it at _default and lists a public product with the credentials, which unseals the session. It also checks that a wrong-audience token and a tampered token are refused. That worker's PLATFORM_ISSUERS still names GitHub, so these tests also pin that the person route wins.
  • Separate audiences. The main worker's AUTH_AUDIENCE is now not-the-data-proxy, the audience of the wrong-audience token CI already mints. A platform path reading the person audiences would then accept that token and refuse the real one.
  • Exact trust. The mint step exports the token's sub as CI_TRUSTED_SUBJECT, and the stub trusts exactly that subject.
  • 200 "no". The stub's ci-tests--says-no-with-200 account answers 200 {"trusted": false}, and a test checks that the proxy refuses it.
  • Staging. The mint step runs only when both FEDERATION_TEST_AUDIENCE and FEDERATION_TEST_TRUST_ACCOUNT are set.

Not covered: the stub still reads the proxy's assertion without verifying its signature. It has no key or crypto library, so a mis-signed trust lookup would still pass CI.

How to test it

CI on this PR is the test: the new tests need the GitHub token that only same-repository runs mint. Locally, without a token, 40 pass and 20 skip. I also checked by hand that --var overrides .dev.vars: with those flags, a GitHub-issued token at _default reaches the person route, and the worker logs PLATFORM_ISSUERS names AUTH_ISSUER; ignoring that entry.

PR Checklist

Related Issues

Follows the review of #237.

🤖 Generated with Claude Code

alukach and others added 7 commits September 30, 2026 23:27
A token file written with `jq -r … > file` ends in a newline, which SDKs
send as-is and the signature's base64 decode rejects with a 400.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The separate refused key cost an extra Cache API match before every
lookup, and the delete of the positive entry never found anything after
a 403. A refusal is now stored as {"trusted":false} under the same key
for REFUSED_TRUST_CACHE_SECS: one Cache API read per exchange.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Platform-token refusals and the API key path's non-key errors came from
build_sts_error_response without it, and SDKs show only the message.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The platform path takes its issuers' tokens ahead of the STS route, so
an entry for AUTH_ISSUER would refuse every person exchange. Drop it at
load with an error.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The fail-closed check ran before the API-key and platform short-circuits,
so an empty AUTH_AUDIENCE also disabled exchanges that carry their own
audience checks (platform) or none at all (keys).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Run a second worker whose AUTH_ISSUER is GitHub, so CI's token is a
  person token there: tests/test_person_route.py exchanges it at
  _default and signs with the result, and refuses a wrong audience and a
  tampered signature. No CI test reached the person route with a
  validly signed token since GitHub became a platform issuer.
- Give the main worker's AUTH_AUDIENCE the wrong-audience token's
  audience, so a platform path that checked the person audiences
  instead of GitHub's own would fail CI.
- The stub trusts exactly the subject of the token CI minted, as
  source.coop matches a trust, instead of a repository prefix.
- Pin that a 200 saying {"trusted": false} is still refused.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With FEDERATION_TEST_AUDIENCE set but FEDERATION_TEST_TRUST_ACCOUNT
unset, the token named the stub's account, which staging lacks, and the
copy-source test failed instead of skipping.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@claude

claude Bot commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Claude finished @alukach's task in 23s —— View job


I'll analyze this and get back to you.


💰 Estimated review cost: $0.16 · 0m22s · 4 turns

@github-actions

github-actions Bot commented Oct 1, 2026

Copy link
Copy Markdown

🚀 Latest commit deployed to https://source-data-proxy-pr-247.source-coop.workers.dev

  • Date: 2026-10-01T06:38:20Z
  • Commit: 3126d31

@alukach
alukach marked this pull request as ready for review October 1, 2026 06:44
@alukach

alukach commented Oct 1, 2026

Copy link
Copy Markdown
Contributor Author

Folded into #237: cherry-picked onto feat/platform-trust as 8938bb2 and 2ee4431.

This branch was successfully deployed

1 active deployment
preview — 39cc0e01 Deployed Oct 1, 2026 by alukach via Deploy & Test / Deploy #400
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant