Files
summercms/.planning/phases/08-oauth2-1-authorization-server/08-08-PLAN.md
2026-09-23 17:46:38 +02:00

7.8 KiB

phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, must_haves
phase plan type wave depends_on files_modified autonomous requirements must_haves
08-oauth2-1-authorization-server 08 execute 7
08-06
../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
true
AUTH-07
truths artifacts key_links
D-20: The unchanged fonoteka-mcp receives exact scopes, collection_ids, user_id, and name from personal-token GET /me.
D-12: Invalid personal tokens retain exact Invalid token bytes and no backend Bearer/resource-metadata challenge.
path provides
../fonoteka.go/plugins/golem15/fonoteka/controllers/api/me_token_controller.go Minimal MCP bootstrap endpoint
from to via pattern
me_token_controller.go bouncer.Credential 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.

<execution_context> @/home/jin/.codex/get-shit-done/workflows/execute-plan.md @/home/jin/.codex/get-shit-done/templates/summary.md </execution_context>

@.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 .planning/phases/08-oauth2-1-authorization-server/08-CONTEXT.md .planning/phases/08-oauth2-1-authorization-server/08-PATTERNS.md ../fonoteka.go/plugins/golem15/fonoteka/classes/auth/token_guard.go ../fonoteka.go/plugins/golem15/fonoteka/controllers/api/me_locale_controller.go ../fonoteka.go/plugins/golem15/fonoteka/routes.go /media/nvme/dev/golem15/fonoteka/plugins/golem15/fonoteka/controllers/api/MeTokenController.php /media/nvme/dev/golem15/fonoteka/plugins/golem15/fonoteka/tests/security/TokenSurfaceIsolationTest.php /media/nvme/dev/golem15/fonoteka/fonoteka-mcp/src/http.ts - 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. Use exact `TestPhase8RedMCPMe`/`PHASE8_RED:mcp-me` package/test/sentinel under `go test -json`; reject any unexpected failing action/package/test, compile/setup/panic/no-test result, or missing/duplicate sentinel. scripts/check-phase8-red.sh go PHASE8_RED:mcp-me git.golem15.com/golem15/fonoteka/plugins/golem15/fonoteka TestPhase8RedMCPMe -- bash -lc "cd ../fonoteka.go && go test -json ./plugins/golem15/fonoteka -run '^TestPhase8RedMCPMe$' -count=1" - RED contains exactly the selected test/package failure and exact sentinel once; unrelated/build/setup/panic/no-test failures are rejected. - Valid `inv_` read-scoped token expects exact `{"data":{"scopes":[],"collection_ids":[],"user_id":...,"name":...}}` field set with arrays never null. - Missing/invalid token retains exact `{"error":"Invalid token"}` 401 with no challenge; wrong scope retains the existing exact 403; route table proves personal-token group only. 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 ../fonoteka.go/plugins/golem15/fonoteka/controllers/api/me_token_controller_test.go ../fonoteka.go/plugins/golem15/fonoteka/oauth_tools_test.go ../fonoteka.go/plugins/golem15/fonoteka/classes/auth/token_guard.go ../fonoteka.go/plugins/golem15/fonoteka/models/api_token.go ../fonoteka.go/plugins/golem15/fonoteka/routes.go /media/nvme/dev/golem15/fonoteka/plugins/golem15/fonoteka/controllers/api/MeTokenController.php /media/nvme/dev/golem15/fonoteka/fonoteka-mcp/src/http.ts - 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/controllers/api ./plugins/golem15/fonoteka -run '^Test(MeToken|TokenSurface|OAuthTools)' -count=1) - Handler reuses `bouncer.Credential` and `bouncer.User` with no bearer reparse or second token query and emits only scopes, collection_ids, user_id, and name. - Nil scopes/collection ids serialize as `[]`; nullable name matches PHP; raw token/hash/client id/other profile fields never appear. - GET `/api/v1/fonoteka/me` inherits exactly `inv_token`, `throttle:fonoteka-api-token`, `inv.scope:read` in order and has no JWT/raw duplicate. - Missing/invalid/wrong-scope exact bytes and absence of backend Bearer/resource-metadata headers remain unchanged. 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.