docs(phase-08): add validation strategy and resolve research decisions
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
<domain>
|
||||
## Phase Boundary
|
||||
|
||||
Port Płytarium's MCP OAuth 2.1 authorization server so fonoteka-mcp, Claude, ChatGPT and Grok connect to the Go backend unchanged. The surface is the unauthenticated RFC group already declared raw in Phase 6 (`GET /.well-known/oauth-authorization-server`, `GET /oauth/mcp/authorize`, `POST /oauth/mcp/token`, `POST /oauth/mcp/register`) plus the five JWT-group endpoints the Nuxt `/connect` page and settings page call (`GET oauth/request/{request_id}`, `POST oauth/consent`, `POST oauth/deny`, `GET oauth/connected-apps`, `DELETE oauth/connected-apps/{id}`), the `fonoteka:oauth-client` console command, and the `scope_ceiling` logic Phase 7 C-03 deferred here.
|
||||
Port Płytarium's MCP OAuth 2.1 authorization server so fonoteka-mcp, Claude, ChatGPT and Grok connect to the Go backend unchanged. The surface is the unauthenticated RFC group already declared raw in Phase 6 (`GET /.well-known/oauth-authorization-server`, `GET /oauth/mcp/authorize`, `POST /oauth/mcp/token`, `POST /oauth/mcp/register`) plus the five JWT-group endpoints the Nuxt `/connect` page and settings page call (`GET oauth/request/{request_id}`, `POST oauth/consent`, `POST oauth/deny`, `GET oauth/connected-apps`, `DELETE oauth/connected-apps/{id}`), the `fonoteka:oauth-client` console command, and the `scope_ceiling` logic Phase 7 C-03 deferred here. Phase 8 also includes the minimal token-authenticated `GET /api/v1/fonoteka/me` prerequisite required for the unchanged `fonoteka-mcp` process to start and complete D-14's real MCP tool-call acceptance gate; this is an explicit exception to the otherwise OAuth-only endpoint boundary.
|
||||
|
||||
The PHP server is hand-rolled inside the `golem15/fonoteka` plugin (not a separate `oauthserver` plugin and not league/oauth2-server): `OAuthCodeManager` plus four API controllers, about 1,000 lines with exact bodies. Every OAuth access token is an ordinary `inv_` personal token minted by `ApiTokenManager` and verified by the existing `inv_token` guard. Grant types are `authorization_code` and `refresh_token` only; there is no client-credentials or token-exchange grant. This closes the STATE.md blocker about `ClientCredentialsStorage`/`TokenExchangeStorage`: neither is needed.
|
||||
|
||||
@@ -43,6 +43,8 @@ Out of scope: social login (`/oauth/{provider}`, `oauth-identities` routes, Phas
|
||||
- **D-17 (sweep):** Wristband adds an expiry sweep that PHP lacks, run where PHP runs its client sweep (`/register`) and also on `/token`, deleting only rows past `expires_at`: pending requests, codes (used or not) and refresh rows. Revoked or rotated rows that have not expired stay, so replay detection and connected-apps semantics match PHP. No timer, no goroutine; Phase 11 may move it into a River job. It is unobservable in recorded replays because nothing expires within a run; the schema-diff and db-capture harness must not be affected.
|
||||
- **D-18 (tests):** All PHP OAuth tests are ported (functional: OAuthAuthorizeTest, OAuthClientCommandTest, OAuthMetadataTest, OAuthMigrationTest, OAuthRegisterTest, OAuthTokenTest; security: OAuthConsentScopeCeilingTest, OAuthRefreshRotationTest, OAuthRevocationTest, TokenSurfaceIsolationTest). Framework behaviour tests run on wristband with the in-memory store; app tests run on real Postgres through the existing `classes` TestMain harness, and route-surface isolation tests inspect the surf route table as Phase 6 did. Each PHP test method maps to a named Go test so coverage can be audited.
|
||||
- **D-19 (command):** `fonoteka:oauth-client` is ported in `fonoteka.go` as a bonfire command scaffolded the Phase 4 way with the same signature (`name`, `--redirect-uri=*`, `--scope=*`, `--auth-method`, `--client-id`, `--list`) and the same output lines (`client_id=`, `client_secret=` printed once, the non-recoverable warning, `--list` never printing a secret). It is thin over wristband's client issuing helper and the app `ClientStore`.
|
||||
- **D-20 (MCP prerequisite):** Phase 8 ports the minimal exact `GET /api/v1/fonoteka/me` personal-token endpoint required by `fonoteka-mcp/src/http.ts` before it constructs the MCP server. The endpoint authenticates through the existing `inv_token` surface and implements only the response contract needed by the unchanged MCP client. This prerequisite is in scope solely to preserve D-14's real MCP tool-call gate; broader user/profile API work remains deferred.
|
||||
- **D-21 (DCR body bound):** `POST /oauth/mcp/register` accepts at most 64 KiB of JSON request body. An oversized document returns the endpoint's normal `invalid_client_metadata` response rather than a house envelope or generic HTML error. The bound is enforced before unbounded JSON decoding and is covered by the `T-08-DCR-FLOOD` failing-when-broken test.
|
||||
|
||||
### Claude's Discretion
|
||||
- Interface names and signatures in wristband, the transaction seam, in-memory store design, and where shared helpers (base64url, sha256 hex, constant-time compare) live.
|
||||
|
||||
Reference in New Issue
Block a user