22 KiB
22 KiB
Deferred items
Out-of-scope discoveries made while executing phase 19.7 plans. Nothing here was changed by the plan that recorded it.
Deferred Items
- Pre-existing
gofmtdrift in cabana (found during 19.7-01 Task 1) status: open What:gofmt -l modules/cabanalistsaccount_tokens.go,account_tokens_test.go,field_trigger_smoke_test.go,token_postgres_smoke_test.go,token_routes_test.goandtoken_scopes_test.goas unformatted before this plan touched the module (alignment of map literals and struct tags). Left as is: reformatting would add diff noise unrelated to the plan (a whole-filegofmt -wontoken_routes_test.gorewrote 132 lines and was reverted). A one-linegofmt -won those six files in astyle(cabana)commit of its own fixes it. AdminRecordAction.Promptacceptance grep counted twoprompt,omitemptytags inschema_types.go(found during 19.7-01 Task 4) status: resolved What: the second match is the pre-existingFormField.PromptJSON tag atschema_types.go:376, not a duplicate of the newRecordAction.Prompt; the criterion's "prints 1" was written without that line in mind. No change needed.- Stateful pier sessions cannot carry the SDK's protocol-version context value (found during 19.7-02 Task 3)
status: open
What: go-sdk v1.8.0's
StreamableHTTPHandler.ServeHTTPstores theMcp-Protocol-Versionheader under an unexported context key that the transport'sservePOST/serveGETread; pier's own session router (needed for Redis-shared sessions, D-25) servesStreamableServerTransportdirectly and cannot set that key, so stateful streams run with the SDK's 2025-03-26 defaults for stream close/reconnect hints and the JSON-RPC batch rule (lenient, spec-compliant for older clients; 2026-07-28 clients go through the SDK's own stateless handler). Revisit if a later SDK exports the key or a transport-level setter; plan 05 may add a test pinning the behaviour. notifications/initializedlanding on another instance thaninitialize(found during 19.7-02 Task 3) status: open What: the session state is persisted afterinitializeand again after the client'sinitializednotification; when a load balancer sends the notification to a second instance, the first instance's local copy keepsInitializedParamsnil and refuses calls until that copy is dropped (session end, revocation or process restart) while the second instance serves them. Sticky sessions or a per-request re-read of the storedinitializedflag would close the gap; not needed for the single-instance demo.- cabana's backend subject events never reach pier (found during 19.7-03 Task 2)
status: resolved
What:
modules/cabana/subject_events.gofirespact.MCPSubjectChangedas a value (app.Events.Fire(ctx, pact.MCPSubjectChanged{...})), whilemodules/pier/events.golistens for a pointer (func(ctx, ev *pact.MCPSubjectChanged)). festival.Bus keys listeners by the type parameter, so pier never sees the backend subject events cabana fires (admin deletion, permission and role changes, token revocation): no list_changed and no session close for thebackendguard from cabana. cabana also fires inside the save's transaction instead of after commit, so a rolled-back save would still notify. sm-user-plugin v0.1.10 fires*pact.MCPSubjectChanged(pointer) throughlagoon.AfterCommit, which pier does receive. Fix in the framework: fire&pact.MCPSubjectChanged{}from cabana and defer it withlagoon.AfterCommit, with a pier test that a cabana save reacheshandleEvent. Must be fixed before v0.5.0. Resolved: cabana now fires&pact.MCPSubjectChanged{}throughlagoon.AfterCommit(immediately outside a transaction);subject_events_test.gopins delivery to a pointer listener, no firing before commit and none after a rollback. - pier publishes
*pier.Pieronce per application (found during 19.7-04 Task 1) status: open What:pier.Mountpublishes the mounted endpoint on the app, so a secondsurf.BuildRouter/surf.Assembleon the same*backpack.Appwithmcp.enabled: truefails withbackpack: duplicate provider for *pier.Pier. A binary builds its router once, so serving is unaffected; tests that build twice on one app (sm-demo-appTestRealtimeRoutes,socialServer) now setmcp.enabled: false. A find-or-replace publish (or skipping the publish when the same app already carries one) in pier would lift it. - MCP grants are not in the authorized-apps list (found during 19.7-04 Task 2)
status: open
What: the MCP flow (wristband
IssueCode, sm-oauthserver-plugin'sMCPStore) stamps the client'sconsented_atbut writes no row togolem15_oauthserver_consents, soGET /oauth/authorizationsdoes not list an MCP client andDELETE /oauth/authorizations/{client_id}answers 404 for it. The access token itself can still be revoked (rowrevoked_at, refused by the verifier at once) and the user cascade removes every grant, but a user has no self-service "disconnect this agent" for MCP yet. A consent row per MCP grant (written atIssueCode) would make the existing list and revocation (which already fires therevokedevent) cover MCP clients; plan 05's revoke matrix should decide. Plan 05 decision: accepted for this phase (19.7-SECURITY.md AR-19.7-03): access still ends through client revocation, user deletion or deactivation, token expiry and the verifier's refusal of a revoked token, andTestMCPEndToEndpins that therevokedevent ends the session. The consent row per MCP grant stays the follow-up. - Pre-existing
gofmtdrift in sm-journal-plugin (found during 19.7-04 Task 3) status: open What:gofmt -llistsclasses/blog_editor_test.gobefore this plan touched the repository. Left as is. - sm-demo-app push and the demo deploy wait for the user (found during 19.7-04 Task 5) status: open What: sm-demo-app master is eight commits ahead of origin (a25444e, 985af53 and this plan's 44cac13, 8668918, the pins aec16c4 oauthserver v0.1.2, 996586c journal v0.2.3, 7e76957 vue-demo-app 21a22b6, and c21ae9d with the nginx MCP locations and DEPLOY.md "MCP endpoint"). None is pushed and nothing is deployed: both need the user's go-ahead. The deploy also installs the changed vhost (DEPLOY.md, "When deploy/nginx/demo.summercms.io.conf changed") and runs the MCP smoke. The sm-oauthserver-plugin v0.1.2 and sm-journal-plugin v0.2.3 tags and the vue-demo-app commit are pushed.
- Release builds pinning summercms v0.4.4 lack the cabana subject-event fix (found during 19.7-04 Task 5)
status: open
What: the demo (GOWORK=off release build), oauthserver v0.1.2 and
Journal v0.2.3 require summercms v0.4.4, which predates
d96c726(cabana fires*pact.MCPSubjectChangedafter commit). Development builds use the go.work replace and carry the fix; a release binary does not: admin deletion, permission or role changes and token revocation in the admin do not end MCP sessions or send list_changed until the next framework tag is required by the demo. The verifier and the backend resolver still refuse at the next request, so access does not outlive the change; only the live session notification is missing. Deploy the demo after the next framework tag, or accept the gap for the demo. - Redis for MCP sessions on rome (found during 19.7-04 Task 5)
status: open
What: the demo runs one instance with
mcp.sessions.store: memory. A second instance needsSUMMER_MCP__SESSIONS__STORE=redisandSUMMER_REDIS__URLon every instance (DEPLOY.md, "MCP endpoint") and a Redis on rome; also see thenotifications/initializeditem above. - Real MCP client check of the demo not run (found during 19.7-04 Task 5) status: open What: Task 5's human check (a real client against the local demo: OAuth sign-in on /connect, user_me only, link an admin through /link-admin, reconnect with backend, the journal_ tools, a draft post, unlink) was not performed in the executor run; the automated TestMCPEndToEnd covers the same path. The local setup is DEPLOY.md, "MCP endpoint", "Locally".
- Retracted
github.com/gabriel-vasile/mimetypev1.4.15 in sm-demo-app (found during 19.7-04 Task 5) status: open What:go getin sm-demo-app warns that mimetype v1.4.15 is retracted (quadratic time on crafted CDF files). It arrives indirectly and predates this plan; ago get github.com/gabriel-vasile/mimetype@latestin the framework (and a tag) would lift it for every consumer. - Framework fixes of plan 05 are on master only (found during 19.7-05 Tasks 1-2)
status: open
What:
c49983dfix(cabana)(thebackendmiddleware refuses a dispatch marker with a frontend principal),c29d228fix(pier)(atools/callwithout arguments) and1111828fix(pier)(an ended session is not written back by a late request) are not in any tag. Applications pinning summercms v0.4.4 (the demo's release build, oauthserver v0.1.2, Journal v0.2.3) lack them until they require the next framework tag (v0.5.0 at phase completion, after the user's go-ahead). Gap closure (19.7-09): the same holds for every framework fix of plans 06 and 07; they ship together in v0.5.0 (see "Release order after the gap closure" below). - Plan 05 test commits are local and untagged (found during 19.7-05 Task 3)
status: resolved
What: sm-user-plugin 72de822 (in the sm-demo-app submodule checkout
plugins/golem15/user), sm-oauthserver-plugin 2929c91, sm-journal-plugin a9a9b80 and sm-demo-app 6fa2d56 add tests only; none is pushed or tagged. sm-demo-app'splugins/golem15/userworking tree is ahead of its v0.1.10 pin by that test-only commit and the pointer is not committed;scripts/check-pins.shreports the mismatch, which the phase gate accepts only because the commits touch*_test.gofiles alone. A patch tag (sm-user-plugin v0.1.11, sm-oauthserver-plugin v0.1.3, sm-journal-plugin v0.2.4) is optional; it would change no shipped code. Push and tags wait for the user. Superseded (19.7-09): the plugins now also carry the non-test fixes of plan 08 and the tests of plan 09, so the plan 05 test commits ship in the gap-closure plugin tags that require framework v0.5.0; the entries "Demo plugin submodules and pointers wait for the release" and "Release order after the gap closure" below track them. - Superuser refusal switch, conditional (found during 19.7-05 Task 4)
status: open
What: the security review accepted superuser reach through an agent
(19.7-SECURITY.md AR-19.7-02) and did not add
mcp.refuse_superuser_backend. When a plugin declares a superuser-only or destructive backend tool beyond content editing, add the switch (afix(pier)with README and docs) and cut a framework patch tag with the user's go-ahead. - B-IN-05: a prompted record action refused with 422 closes the dialog (found in the code review, deferred by 19.7-07) status: open What: when a prompted record action answers 422, the SPA shows the error toast and closes the prompt dialog, so the typed text is lost. Plan 07 corrected the contract text (the 422 toast behaviour is now what the docs and the OpenAPI description say). Keeping the dialog open needs a change to the shared confirm primitive every action uses (the dialog resolves before the request answers), which is out of the gap closure's scope. Follow-up: let the confirm primitive keep the dialog open on a refused submit and show the field error inline.
- B-IN-06:
window.openafter an awaited POST can be blocked by a popup blocker (found in the code review) status: resolved What: no fix required. My account always renders the answered URL as a visible link next to the section (data-account-contribution-url), so an administrator whose browser blocked the popup clicks the link (pinned byadmin/tests/account/AccountContributions.test.ts). admin:token:revokefires no MCP event (found during 19.7-07) status: open What: the CLI command revokes an admin personal token's row but does not fire the token-specificrevokedsubject event that the My account revoke fires (fireTokenRevoked). The verifier side refuses the revoked token on the next request, so access ends; only a live MCP session of that token keeps its stream until its next request or re-check. Same shape as before plan 07. Fix: call the same helper from the command after its transaction. Re-review (RB-IN-03): kept deferred. CallingfireTokenRevokedfrom the command is not enough: the command runs in its own process, which mounts no MCP endpoint, so no pier listener receives the event and nothing reaches the store a running server reads. Closing it needs the command to publish into pier's store directly (a cross-module seam).4d7eb9ddocuments in the cabana README that only the My account revoke fires the event.- RB-IN-04 optional narrowing: a focused widget host also mutes Esc, / and ? (found in the gap-closure re-review)
status: open
What:
89b85f5documents the trade-off inadmin/src/app/hotkeys.ts. The optional narrowing to plugin field types (adata-field-typemarker) was not made: atype: widgetelement with an input in a closed shadow root would then let Esc leave the form while the admin types in it. - OIDC grants on a ban or a password reset (decided during 19.7-08)
status: resolved
What: the user decided on 2026-10-23 that a ban, a password reset, an
administrator setting a password and the user's own password change end
both the MCP and the OIDC grants of the user (tokens revoked, consents
and unused codes deleted, subjects kept). Implemented by
Cascade.OnAccessRevoked(sm-oauthserver-plugin 671513d) and pinned byTestMCPGrantRevocation("access revoked ends earlier MCP and OIDC grants and keeps later ones") andTestMCPRevocationSmoke. - Local sm-oauthserver-plugin go.work retarget (found during 19.7-08 Task 2)
status: open
What: the tracked
go.workof sm-oauthserver-plugin is modified in the working tree only: itssm-user-pluginreplace points at../sm-demo-app/plugins/golem15/user(the canonical user checkout of the gap closure) instead of the committed../fonoteka.go/plugins/golem15/user. The phase gate's workspace check requires exactly that target, so the gate passes on this machine only with the local edit. Before the release either restore the committed line or decide whether go.work should leave version control; never commit the local retarget. - Demo plugin submodules and pointers wait for the release (found during 19.7-08, updated by 19.7-09)
status: open
What: in sm-demo-app the working-tree checkouts of
plugins/golem15/oauthserver(671513d, its canonical checkout is at 65f71dc with plan 09's test),plugins/golem15/journal(b129902, canonical at 2aeeccc) andplugins/golem15/user(the canonical user checkout itself, 38551a4) are ahead of their committed pins (v0.1.2, v0.2.3, v0.1.10) by unreleased commits. The gate reports them aspins: … is ahead of its pin by unreleased commitsand refuses them withPHASE197_RELEASED=1. The pointers are committed only after the plugin tags. sm-demo-app'svue-demo-apppointer is committed (00f57bf, then f53d30a for the link code test): vue-demo-app (0125e29, b973a76) must be pushed before sm-demo-app. - Release order after the gap closure (decided 2026-10-23)
status: open
What: nothing of plans 06-09 is tagged or pushed. After the re-review
of the gap closure, phase verification, Nyquist validation and UAT pass,
and on the user's go-ahead:
- framework v0.5.0 (and the changelog post);
- the sm-user-plugin, sm-oauthserver-plugin and sm-journal-plugin tags that require it;
- the bumps in sm-demo-app, fonoteka.go and sm-bm-app, with vue-demo-app pushed before sm-demo-app;
- sm-servers-app picks up E-1 and E-2 after the user plugin tag;
- then
PHASE197_RELEASED=1 bash scripts/check-phase19.7.sh --consumersmust pass (every demo pin on its tag, no drift).
readLinkCodeaccepts a valid code next to other fragment parameters (found during 19.7-09 Task 3) status: resolved (gap-closure re-review: not a defect; vue-demo-app 9c247ab pins the lenient parse) What: plan 09 described "extra parameters give ''" for the link page's code reader.readLinkCodeparses the fragment with URLSearchParams, so#code=<64 hex>&next=/xanswers the code, while an extended or foreign value (#code=<hex>x,#other=<hex>) answers ''.linkCode.test.tspins the latter and leaves the former unasserted. My account only ever sends#code=<code>, so nothing depends on it; the re-review decides whether to keep the lenient parse or require the fragment to be exactlycode=<64 hex>.docs/examples/blogtest failed once on GOPROXY=off (found during 19.7-09 Task 1) status: open What: onego test -short ./...run of the gate's go stage failed indocs/examples/blogwith "module lookup disabled by GOPROXY=off" forgolang.org/x/exp; the package passed alone and in more than twenty later full runs. The test builds a scratch module offline and depends on the module cache holding every dependency; a run that coincides with a cache change may miss one. Not caused by this phase's code; watch for a recurrence.- RA-IN-04: the cap of the non-reserving store fallback is still check-then-act (found in the gap-closure re-review, deferred by its lane A fixes)
status: open
What:
034aa19makesserveNew's fallback for a store withoutReservewrite the record before the server is built, so a reaper pass can no longer close a session that has no record yet. The Count-then-Put cap of that fallback remains racy. Closing it means makingReservepart of the exportedpier.Storeinterface or refusing a store without it at mount, which changes pier's exported API for a branch only a test wrapper (WrapStore) reaches; both shipped stores reserve atomically. - RA-WR-06 optional: the demo pin check does not require unreleased commits to be on the canonical checkout's upstream (found in the gap-closure re-review)
status: open
What:
2fdda99qualifies the gate's verdict ("Phase 19.7 gate passed WITH UNRELEASED PINS: the release pins are not yet proven") while demo submodules carry unreleased non-test commits; the exit status stays 0 so the pre-release verification can run. The review's optionalgit branch -r --containscheck was not added: the gap-closure commits are deliberately unpushed until the release order runs, so it would refuse every pre-release run.PHASE197_RELEASED=1after the tags is the release proof. - RC-CR-01 optional: base the session cutoff on
auth_time(found in the gap-closure re-review, lane C) status: open What: the self-service password change now revokes every OAuth grant as of the request (sm-user-plugin 30f7a01). The calling session's own cutoff is still itsiatsecond, so an attacker's frontend session JWT refreshed after the victim'siatsurvives the change too. That predates this phase; closing it means basingtokens_valid_afteron the calling token'sauth_timeand havingPOST /refreshand the jwt guard compareauth_timewith the cutoff, a change to session revocation in a core plugin (and to how bouncer's refresh is checked) that needs its own decision. - RC-IN-01 nginx: keep the deprecated link GET route's code out of access logs (found in the gap-closure re-review, lane C)
status: open
What: sm-user-plugin 92676ba makes the show and confirm POSTs ignore
a code in the query string.
GET /_user/api/v1/backend-link/{code}stays for compatibility (removed only in a major release), so nginx still logs the code if a third-party client calls it.access_log off;(or alog_formatwithout$request_uri) forlocation ~ ^/_user/api/v1/backend-link/in the demo's nginx config is a deploy change, made with the next demo deploy; the shipped page never calls the GET route. - RC-IN-06: the legacy MintAPIToken fallback is widened before the phrase-key check (found in the gap-closure re-review, lane C)
status: open
What:
classes.CompileAPITokenScopesadds the declared names to the process-wide fallback set beforebootAPITokenScopeschecks their phrase keys, so a boot that fails on a missing key has already widened whatMintAPITokenaccepts. Moving the add after the check needs a new exported seam or a behaviour change of the exportedCompileAPITokenScopesin a core plugin; a failed boot ends the process, so the widened set is never used in production.MintAPITokenis now markedDeprecated:in favour ofMintAPITokenFor(sm-user-plugin 9892404), which checks the application's own catalog. - RC-IN-07: sm-oauthserver-plugin builds only through its workspace file (found in the gap-closure re-review, lane C)
status: open (release-time)
What: the plugin uses
userclasses.AccessRevokedEvent,FireSubjectEventandFireSubjectEventAfterCommit, which the required sm-user-plugin v0.1.10 lacks, soGOWORK=off go build ./...fails. The release checklist for the oauthserver tag must bumpsm-user-pluginto the new user plugin tag and passGOWORK=off go build ./...before the tag; the requires are not bumped before the user plugin is tagged. - Lane C re-review fixes moved the demo's oauthserver checkout (gap-closure re-review, lane C)
status: open
What: pier now gives a backend subject only to a grant that records
its consented administrator (
pact.MCPGrant.BackendUserID, frameworkc37c6ce), so the demo's e2e tests need the oauthserver commits that record it. The working-tree checkout of sm-demo-app'splugins/golem15/oauthserverwas moved from 671513d to the canonical b6a9586 (detached, fast-forward; the pointer stays uncommitted until the plugin tag, as before). Canonical heads after the lane C fixes: sm-user-plugin 9892404, sm-oauthserver-plugin 9813c1d, sm-journal-plugin 521df9a (its prompt test's fake grants now name the consented administrator), vue-demo-app 9c247ab.backendgrants issued before the oauthserver migration202610230001record no administrator and stop acting as one until the agent is connected again.