Skip to content

Bootstrap: drop /bootstrap POST, defer person binding to first authorized request#7

Merged
rohanharikr merged 1 commit into
mainfrom
bootstrap-spec-aligned-rewrite
May 11, 2026
Merged

Bootstrap: drop /bootstrap POST, defer person binding to first authorized request#7
rohanharikr merged 1 commit into
mainfrom
bootstrap-spec-aligned-rewrite

Conversation

@rohanharikr
Copy link
Copy Markdown
Contributor

Summary

  • The PS-side /bootstrap endpoint was removed in hellocoop/Wallet#3937 (and bootstrap_endpoint was dropped from issuer's static metadata). npx @aauth/bootstrap --ps <url> was unconditionally throwing "PS metadata missing bootstrap_endpoint" against any current PS.
  • Align the package with draft-hardt-aauth-bootstrap §Self-Hosted Enrollment: "publication of the JWKS is the enrollment — there is no separate enrollment step." Person binding now happens lazily on the agent's first /aauth/token call, per §Agent-Person Binding in the protocol spec.

What --ps <url> does now

Before: signed POST to /bootstrap, 202 + Location polling, browser open for consent, binding established at setup time.

After: fetch <ps>/.well-known/aauth-person.json, validate required fields (issuer, token_endpoint, jwks_uri) and that issuer matches the URL, write agentId + personServerUrl to ~/.aauth/config.json. No network POST. No browser. No interaction at setup time.

The first time the agent makes an authorized request (resource → 401 → PS /aauth/token), the PS sees a new (user, agent_id) tuple and surfaces the consent screen as enrollment + auth in one step.

Code changes

  • bootstrap/src/bootstrap-ps.ts — collapsed ~204 → ~70 lines. Dropped ephemeral keypair, agent_token mint, signed POST, 202 polling, browser open.
  • bootstrap/src/cli.ts — dropped onInteraction callback and --login-hint / --domain-hint / --provider-hint / --tenant flags from runBootstrapPS (these parameterized the now-removed POST; @aauth/fetch already has equivalent flags for the real /aauth/token call). Updated success message + help text. No default PS URL shown anywhere.
  • bootstrap/package.json — dropped @aauth/mcp-agent, @hellocoop/httpsig, open from dependencies (no longer used).
  • local-keys/src/create-agent-token.ts — tweaked error message ("register" → "configure one").
  • local-keys/src/index.ts — exported writeConfig so other packages / tests can reset config state.

Docs

  • Removed "default PS is https://person.hello-beta.net" claim and the beta-data-reset warning from README.md, bootstrap/README.md, bootstrap/skills/setup.md, fetch/README.md, fetch/skills/fetch.md, local-keys/README.md.
  • Reframed --ps everywhere from "register" → "configure"; placeholder <your-ps-url> in examples.

Tests

bootstrap/src/bootstrap-ps.test.ts (new, 12 cases):

  • Happy path — fetches correct well-known URL, writes agentId + personServerUrl
  • local override propagates into agentId
  • Existing key entries preserved when writing the agent config
  • Validation errors — missing issuer / token_endpoint / jwks_uri
  • Issuer mismatch — throws
  • HTTP non-OK metadata response — throws
  • Trailing-slash normalization on issuer/URL and metadata URL
  • Regression guard — asserts exactly one fetch call (metadata GET) so we don't accidentally reintroduce the /bootstrap POST

Verification

End-to-end verified locally against person.hello-beta.net:

node bootstrap/dist/cli.js --agent https://rohanharikr.github.io --ps https://person.hello-beta.net
# → "Person server configured. Person binding will happen on the agent's first authorized request."
# → ~/.aauth/config.json updated with agentId + personServerUrl
# → no browser, no POST, no errors

node fetch/dist/cli.js "https://whoami.aauth.dev?scope=openid+profile"
# → resource returns 401 + resource_token
# → fetch hits PS /aauth/token → 202 + interaction URL
# → browser opens for consent
# → PS writes binding, issues auth_token
# → fetch retries and prints a real identity response

All 218 prior tests + 12 new tests pass. (1 pre-existing test failure in agent-token-hardware.test.ts is environment-dependent and unaffected by this PR.)

Test plan

  • Re-run node bootstrap/dist/cli.js --agent <url> --ps <ps-url> against a current PS — should succeed without throwing
  • Inspect ~/.aauth/config.jsonagentId and personServerUrl correctly written, existing keys map preserved
  • No new npx @aauth/local-keys references in docs (already cleaned up in Docs: fix stale CLI references and broken links across READMEs #6)
  • All 13 package.json files line up post-merge for the version bump (separate commit)

🤖 Generated with Claude Code

The PS-side /bootstrap endpoint was removed in hellocoop/Wallet#3937
(bootstrap_endpoint was also dropped from issuer's PS metadata). The CLI
was unconditionally fetching bootstrap_endpoint from metadata and POSTing
to /bootstrap, so npx @aauth/bootstrap --ps <url> threw immediately with
"PS metadata missing bootstrap_endpoint" against any current PS.

Align the package with draft-hardt-aauth-bootstrap §Self-Hosted
Enrollment: publication of the JWKS is the enrollment, there is no
separate enrollment step. Person binding to a user happens lazily on the
agent's first /aauth/token call, per §Agent-Person Binding in the
protocol spec.

Code changes:
- bootstrap/src/bootstrap-ps.ts: collapse from ~204 to ~70 lines. New
  behavior: fetch PS metadata, validate required fields (issuer,
  token_endpoint, jwks_uri) and that issuer matches the URL, write
  agentId + personServerUrl to ~/.aauth/config.json. No network POST,
  no ephemeral keypair, no agent token mint, no 202 polling, no
  browser open.
- bootstrap/src/cli.ts: drop onInteraction callback and login-hint /
  domain-hint / provider-hint / tenant flags from runBootstrapPS
  (those parameterized the now-removed POST; equivalent flags already
  exist on @aauth/fetch for the real /aauth/token call). Drop `open`
  import. Update success message and help text — no default PS URL
  shown anywhere.
- bootstrap/package.json: drop @aauth/mcp-agent, @hellocoop/httpsig,
  open (no longer used).
- local-keys/src/create-agent-token.ts: tweak error message
  ("register" → "configure one").
- local-keys/src/index.ts: export writeConfig so other packages /
  tests can reset config state.

Docs:
- README.md, bootstrap/README.md, bootstrap/skills/setup.md,
  fetch/README.md, fetch/skills/fetch.md, local-keys/README.md:
  remove the "default PS is person.hello-beta.net" claim and the
  beta-data warning; reframe `--ps` from "register" to "configure";
  use <your-ps-url> placeholder in examples.

Tests:
- bootstrap/src/bootstrap-ps.test.ts: new file, 12 cases covering
  happy path, validation errors, issuer mismatch, trailing-slash
  normalization, config preservation, and a regression guard that
  asserts no registration POST is made.

End-to-end verified locally against person.hello-beta.net with a
real fetch through whoami.aauth.dev — lazy binding works:
resource → 401 + resource_token → fetch hits PS /aauth/token →
PS detects new (user, agent_id) → 202 + interaction URL → browser
consent → binding written → auth_token issued → fetch retries
resource and gets a real identity response.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@rohanharikr rohanharikr merged commit 8438a55 into main May 11, 2026
1 check passed
@rohanharikr rohanharikr deleted the bootstrap-spec-aligned-rewrite branch May 11, 2026 17:48
rohanharikr added a commit that referenced this pull request May 11, 2026
Minor release with bootstrap rewrite (#7):
- @aauth/bootstrap no longer POSTs to /bootstrap. Aligned with
  draft-hardt-aauth-bootstrap §Self-Hosted Enrollment — person binding
  now happens lazily on the agent's first /aauth/token request.
- CLI --ps becomes local-config-only: validates PS metadata and writes
  agentId + personServerUrl to ~/.aauth/config.json.
- Dropped --login-hint/--domain-hint/--provider-hint/--tenant from the
  bootstrap path (those parameterized the now-removed POST; @aauth/fetch
  already has the equivalent flags for the real token call).
- Removed default PS URL from all docs.
- 12 new tests covering the new flow + a regression guard against
  re-introducing the /bootstrap POST.

Internal workspace dep ranges bumped from ^0.8.0 to ^0.9.0 so installs
from the npm registry resolve to matching versions.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant