From afb84ee6e4bd15611c552e75d3f9864b33059ef0 Mon Sep 17 00:00:00 2001 From: dickhardt Date: Wed, 9 Sep 2026 16:51:45 +0100 Subject: [PATCH] interaction_endpoint is the person-facing page, not the agent's reach API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The field carried both roles while a 202 also sent `url=`. It no longer does: a recipient composes `{interaction_endpoint}?code=` and sends the PERSON there. mockin still published `POST /aauth/interaction` — the agent's reach API — so an agent that composed a person URL from PS metadata landed on a 404 for a POST-only route. Publish `${ISSUER}/aauth/consent` there, matching Wallet's `${PERSON}/auth`, and move the reach API to its own `reach_endpoint`. Logged as an ambiguity in session 2 (aauth-mcp OVERNIGHT-LOG.md, Track N, N7) and only reachable once a PS stopped sending `url=`. 241 passing. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01CRdau7tgZa1tPVzUdyNrHc --- package-lock.json | 4 ++-- package.json | 2 +- src/aauth/metadata.js | 9 ++++++++- test/aauth/metadata.spec.js | 5 ++++- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index cafd891..4216c82 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@hellocoop/mockin", - "version": "3.2.0", + "version": "3.2.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@hellocoop/mockin", - "version": "3.2.0", + "version": "3.2.1", "license": "MIT", "dependencies": { "@fastify/cors": "^11.3.0", diff --git a/package.json b/package.json index d0e8d0e..7a88bcc 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@hellocoop/mockin", "private": false, - "version": "3.2.0", + "version": "3.2.1", "description": "Hellō Mock Login OpenID Connect Server", "engines": { "node": ">=22" diff --git a/src/aauth/metadata.js b/src/aauth/metadata.js index d92b296..f3cd84d 100644 --- a/src/aauth/metadata.js +++ b/src/aauth/metadata.js @@ -23,7 +23,14 @@ export const metadata = async (req, res) => { person_token_endpoint: `${ISSUER}/aauth/token/person`, permission_endpoint: `${ISSUER}/aauth/permission`, audit_endpoint: `${ISSUER}/aauth/audit`, - interaction_endpoint: `${ISSUER}/aauth/interaction`, + // The PERSON-facing page: where a recipient sends the person when a + // 202 carries only a code, composed as `{interaction_endpoint}?code=`. + // It is NOT the agent's reach API (POST /aauth/interaction) — that + // field carried both roles until the flat `interaction_code` landed, + // and an agent composing a person URL from it lands on a 404. + // Hellō's Wallet publishes `${PERSON}/auth` here. + interaction_endpoint: `${ISSUER}/aauth/consent`, + reach_endpoint: `${ISSUER}/aauth/interaction`, bootstrap_endpoint: `${ISSUER}/aauth/bootstrap`, }) } diff --git a/test/aauth/metadata.spec.js b/test/aauth/metadata.spec.js index 21b4ea4..ce23dab 100644 --- a/test/aauth/metadata.spec.js +++ b/test/aauth/metadata.spec.js @@ -25,7 +25,10 @@ describe('AAuth Metadata & JWKS', function () { expect(data).to.not.have.property('token_endpoint') expect(data.permission_endpoint).to.equal(`${ISSUER}/aauth/permission`) expect(data.audit_endpoint).to.equal(`${ISSUER}/aauth/audit`) - expect(data.interaction_endpoint).to.equal(`${ISSUER}/aauth/interaction`) + // The person-facing page, not the agent's reach API: an agent + // composes `{interaction_endpoint}?code=` and sends the person there. + expect(data.interaction_endpoint).to.equal(`${ISSUER}/aauth/consent`) + expect(data.reach_endpoint).to.equal(`${ISSUER}/aauth/interaction`) expect(data.bootstrap_endpoint).to.equal(`${ISSUER}/aauth/bootstrap`) })