reuse matched ApiToken without reparsing bearer input
Credential
Serve the exact personal-token bootstrap needed by the unchanged MCP process.
Purpose: Deliver the approved D-20 prerequisite as an isolated auth-surface slice that can execute in parallel with operator provisioning.
Output: /api/v1/fonoteka/me, route isolation, and assembled tests.
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
@.planning/phases/08-oauth2-1-authorization-server/08-CONTEXT.md
@.planning/phases/08-oauth2-1-authorization-server/08-UI-SPEC.md
@.planning/phases/08-oauth2-1-authorization-server/08-06-SUMMARY.md
Task 1: Specify exact MCP bootstrap and token-surface behavior in RED
../fonoteka.go/plugins/golem15/fonoteka/controllers/api/me_token_controller_test.go, ../fonoteka.go/plugins/golem15/fonoteka/oauth_tools_test.go
- Valid read-scoped inv_ token returns exactly four fields; arrays are never null.
- Missing/invalid/wrong-scope tokens preserve existing exact 401/403 bytes and headers.
- Tests compile and fail only through `PHASE8_RED:mcp-me`.
D-18 and D-20: use the assembled surf router and existing inv_token guard, not direct controller injection. Add exact positive/negative payload and route-isolation tests; mark only missing `/me` behavior with `PHASE8_RED:mcp-me` and reject syntax/setup/missing-test failures via the shared verifier.
scripts/check-phase8-red.sh mcp-me bash -lc "cd ../fonoteka.go && go test ./plugins/golem15/fonoteka/... -run 'Test(MeToken|TokenSurface|OAuthTools)' -count=1"
The assembled RED tests run through the real guard and fail only on absent `/me` behavior.
Task 2: Mount exact personal-token MCP bootstrap
../fonoteka.go/plugins/golem15/fonoteka/controllers/api/me_token_controller.go, ../fonoteka.go/plugins/golem15/fonoteka/controllers/api/me_token_controller_test.go, ../fonoteka.go/plugins/golem15/fonoteka/routes.go, ../fonoteka.go/plugins/golem15/fonoteka/oauth_tools_test.go
- Handler reads matched ApiToken and principal, emits only exact four fields, and performs no second lookup.
- Route inherits inv_token, throttle, inv.scope:read in order and appears nowhere else.
D-20: implement the exact handler using `bouncer.Credential` and `bouncer.User`, initialize arrays, preserve nullable name, and emit only locked fields through wire.WriteJSON. Mount GET `/me` in the existing personal-token group after its three middleware. D-12: leave invalid-token bytes/headers unchanged and add no RFC 9728 or Bearer challenge.
cd ../fonoteka.go && go test ./plugins/golem15/fonoteka/... -run 'Test(MeToken|TokenSurface|OAuthTools)' -count=1
The unchanged MCP process can bootstrap from an issued inv_ token without profile-surface expansion or header drift.
<threat_model>
Trust Boundaries
Boundary
Description
Bearer header → personal-token /me
Untrusted bearer input crosses existing token and scope guards.
STRIDE Threat Register
Threat ID
Category
Component
Disposition
Mitigation Plan
T-08-SCOPE-CEILING
Elevation
/me
mitigate
Existing inv.scope:read middleware.
T-08-REQUEST-LEAK
Information Disclosure
response
mitigate
Four-field positive allow-list.
T-08-SURFACE
Elevation
routes
mitigate
Personal-token-only route-table proof.
T-08-SC
Tampering
dependencies
mitigate
No install.
</threat_model>
- Focused `/me` and token-surface tests pass.
- Route table shows exact middleware order and no JWT/raw duplicate.
<success_criteria>
Real MCP bootstrap payload is exact and token failures remain unchanged.
</success_criteria>
Create `.planning/phases/08-oauth2-1-authorization-server/08-08-SUMMARY.md` when done.