docs(10): re-verify stale phase 10 report, gaps_found on check-phase10 hygiene gate
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
---
|
||||
phase: 10-admin-vue-spa
|
||||
verified: 2026-10-05T20:22:38Z
|
||||
status: human_needed
|
||||
score: 4/4 roadmap success criteria verified by automated evidence (plan truths 46/46; 1 browser re-check of changed views pending)
|
||||
verified: 2026-10-11T13:53:00Z
|
||||
status: gaps_found
|
||||
score: "4/4 roadmap success criteria hold in substance; plan truths 43/46 (3 failed, one root cause: the Phase 10 hygiene gate is red at HEAD after later phases added SPA files)"
|
||||
covered_files:
|
||||
- ".gitignore"
|
||||
- ".planning/phases/10-admin-vue-spa/10-01-PLAN.md"
|
||||
@@ -22,6 +22,7 @@ covered_files:
|
||||
- "admin/package.json"
|
||||
- "admin/src/App.vue"
|
||||
- "admin/src/api/client.ts"
|
||||
- "admin/src/api/files.ts"
|
||||
- "admin/src/api/schema.d.ts"
|
||||
- "admin/src/api/types.ts"
|
||||
- "admin/src/app/controllerRoutes.ts"
|
||||
@@ -32,6 +33,8 @@ covered_files:
|
||||
- "admin/src/app/runtime.ts"
|
||||
- "admin/src/app/theme.ts"
|
||||
- "admin/src/app/winterUrl.ts"
|
||||
- "admin/src/components/account/ApiTokenCreateDialog.vue"
|
||||
- "admin/src/components/account/ApiTokensPanel.vue"
|
||||
- "admin/src/components/form/FieldRenderer.vue"
|
||||
- "admin/src/components/form/FormErrorBanner.vue"
|
||||
- "admin/src/components/form/FormField.vue"
|
||||
@@ -40,6 +43,8 @@ covered_files:
|
||||
- "admin/src/components/form/control.ts"
|
||||
- "admin/src/components/form/fields/CheckboxField.vue"
|
||||
- "admin/src/components/form/fields/DropdownField.vue"
|
||||
- "admin/src/components/form/fields/FileCaptionModal.vue"
|
||||
- "admin/src/components/form/fields/MLField.vue"
|
||||
- "admin/src/components/form/fields/NumberField.vue"
|
||||
- "admin/src/components/form/fields/RelationField.vue"
|
||||
- "admin/src/components/form/fields/SwitchField.vue"
|
||||
@@ -47,6 +52,7 @@ covered_files:
|
||||
- "admin/src/components/form/fields/TextareaField.vue"
|
||||
- "admin/src/components/form/fields/UnsupportedField.vue"
|
||||
- "admin/src/components/form/formState.ts"
|
||||
- "admin/src/components/form/mlLocale.ts"
|
||||
- "admin/src/components/form/registry.ts"
|
||||
- "admin/src/components/list/CellValue.vue"
|
||||
- "admin/src/components/list/DataTable.vue"
|
||||
@@ -151,8 +157,8 @@ covered_files:
|
||||
- "internal/tools/swagger2openapi/main_test.go"
|
||||
- "modules/boardwalk/boardwalk.go"
|
||||
- "modules/boardwalk/boardwalk_test.go"
|
||||
- "modules/boardwalk/dist/assets/index-CqzF_Nki.css"
|
||||
- "modules/boardwalk/dist/assets/index-z_LzMU8D.js"
|
||||
- "modules/boardwalk/dist/assets/index-BeX-076N.css"
|
||||
- "modules/boardwalk/dist/assets/index-CXQZEJp2.js"
|
||||
- "modules/boardwalk/dist/index.html"
|
||||
- "modules/bouncer/cookie_guard_test.go"
|
||||
- "modules/bouncer/jwt.go"
|
||||
@@ -213,8 +219,7 @@ covered_files:
|
||||
- "scripts/check-admin-dist.sh"
|
||||
- "scripts/check-admin-openapi.sh"
|
||||
- "scripts/check-phase10.sh"
|
||||
covered_digest: "v2:sha256:778f7d89834605c7799f088401e3b1ef5edb4409f6899f322f67d165fa9e4847"
|
||||
covered_files_note: "Fingerprint refreshed 2026-10-05 at summercms.go HEAD e18885f. Content-hashed SPA bundles now modules/boardwalk/dist/assets/index-CqzF_Nki.css and index-z_LzMU8D.js. Later phases edited already-covered modules/ files (same digest-drift as Phase 9 Layer 2). Paths remain modules/. Status stays human_needed — this only clears the stale overlay so execute-phase is not re-invoked."
|
||||
covered_digest: "v2:sha256:fd0f803078fe0f4843d26e78ff531ce7b6f2271a193aac732dbd6b3ba7272a9b"
|
||||
behavior_unverified: 0
|
||||
overrides_applied: 0
|
||||
mvp_mode_note: "ROADMAP marks Phase 10 mode: mvp, but the goal is not a User Story. Following the Phase 1/3/5/8 precedent, the four ROADMAP success criteria are the contract and User Flow Coverage is derived from them."
|
||||
@@ -223,212 +228,203 @@ decision_coverage:
|
||||
total: 28
|
||||
not_honored: []
|
||||
re_verification:
|
||||
previous_status: passed
|
||||
previous_score: "4/4 roadmap success criteria verified (plan truths 46/46 verified; A3 closed by human UAT)"
|
||||
previous_head: c7487f6
|
||||
reason: "The 2026-10-01T21:29Z report went stale because Vite rebuilt the two content-hashed SPA bundles (index-CfeX_snf.css / index-J-FCndLr.js → index-CqzF_Nki.css / index-z_LzMU8D.js) and later phases edited already-covered modules/ files. Paths were already under modules/. covered_digest recomputed at HEAD e18885f; status stays human_needed for the pending browser re-walk."
|
||||
gaps_closed:
|
||||
- "Phase 10 review WR-01 (logout behind the guard did not expire a rejected cookie): logout is now mounted outside the guard and always clears the cookie (299d220). TestAdminLogoutRevokesExpiredRefreshableToken: PASS."
|
||||
previous_status: human_needed
|
||||
previous_score: "4/4 roadmap success criteria verified by automated evidence (plan truths 46/46; 1 browser re-check pending)"
|
||||
previous_head: c05ad09
|
||||
reason: "Stale (covered_changed): 76 covered files changed between c05ad09 and 07e579a (phases 10.1, 12.2, 14.2.1, 16.1, 16.2, 16.3 and admin quick fixes). The two content-hashed bundles are now index-BeX-076N.css / index-CXQZEJp2.js."
|
||||
gaps_closed: []
|
||||
gaps_remaining: []
|
||||
regressions: []
|
||||
regressions:
|
||||
- "scripts/check-phase10.sh --hygiene and --self-test exit 1 at HEAD (first broken by ea33296, 12.2-04, 2026-10-02, after the 2026-10-01 full gate run; the 2026-10-05 refresh only recomputed the digest)."
|
||||
gaps:
|
||||
- truth: "SC-4 mechanical enforcement: scripts/check-phase10.sh --hygiene passes (admin/src/api holds only schema.d.ts, client.ts and types.ts; no file other than api/client.ts calls the network directly)"
|
||||
status: failed
|
||||
reason: "Phase 12.2-04 (ea33296) added admin/src/api/files.ts, which uploads through XMLHttpRequest for progress events. The hygiene stage refuses it twice: 'direct fetch outside admin/src/api/client.ts: admin/src/api/files.ts:150' and 'unexpected files in admin/src/api: admin/src/api/files.ts'. The substance of SC-4 holds (files.ts types every wire shape through the generated aliases FileItem, FileMutationResult, AdminFileCaptionRequest, ErrorBody from types.ts and reuses the client's X-Requested-With and refresh), but the gate was never updated, unlike the precedents for MarkdownField v-html (27711b7) and listState storage (9cac45c)."
|
||||
artifacts:
|
||||
- path: "scripts/check-phase10.sh"
|
||||
issue: "hygiene_checks has no allowlist entry for admin/src/api/files.ts (XHR upload) or for the api/ directory listing"
|
||||
- path: "admin/src/api/files.ts"
|
||||
issue: "direct XMLHttpRequest outside client.ts; a fourth file in admin/src/api"
|
||||
missing:
|
||||
- "Either allowlist admin/src/api/files.ts in both hygiene rules (narrow pattern for the single 'new XMLHttpRequest()' line, as done for MarkdownField and listState), or move the XHR upload behind client.ts; record the decision in the 12.2 or 10 notes"
|
||||
- truth: "Every .ts and .vue file under admin/src except main.ts, api/schema.d.ts and env.d.ts is imported by at least one test file (10-05 Task 1, checked by the hygiene stage)"
|
||||
status: failed
|
||||
reason: "Five later-phase files are imported by no test file: admin/src/components/account/ApiTokenCreateDialog.vue and ApiTokensPanel.vue (16.3-02), admin/src/components/form/fields/FileCaptionModal.vue (12.2-04), admin/src/components/form/fields/MLField.vue (a913eec), admin/src/components/form/mlLocale.ts (14.2.1-03). The two account components are exercised indirectly (admin/tests/account/*.test.ts mount the app at /account), but the rule requires a direct import."
|
||||
artifacts:
|
||||
- path: "admin/tests"
|
||||
issue: "no test imports src/components/account/ApiTokenCreateDialog, src/components/account/ApiTokensPanel, src/components/form/fields/FileCaptionModal, src/components/form/fields/MLField or src/components/form/mlLocale"
|
||||
missing:
|
||||
- "Add a direct import (a focused component/unit test) for each of the five files, e.g. import ApiTokensPanel in admin/tests/account/ApiTokensPanel.test.ts"
|
||||
- truth: "scripts/check-phase10.sh --all is the phase acceptance command and --self-test proves each detector fails closed"
|
||||
status: failed
|
||||
reason: "--self-test exits 1 with 'refuse: self-test hygiene rejected the clean scratch copy', because the scratch copy of HEAD already carries the two violations above. --all therefore cannot pass. The detectors themselves still work (they caught real drift); the stage goes green once the two gaps above are closed."
|
||||
artifacts:
|
||||
- path: "scripts/check-phase10.sh"
|
||||
issue: "self-test and all stages red at HEAD as a consequence of gaps 1 and 2"
|
||||
missing:
|
||||
- "Close gaps 1 and 2, then re-run scripts/check-phase10.sh --self-test and --hygiene"
|
||||
human_verification:
|
||||
- test: "Re-walk the Phase 10 admin flows in a real browser on the current build: run the fonoteka binary, open /plytadmin as a superuser and as a genres-only admin, then use the list and form of each of the five controllers (search, sort, filter, paging, save, 422 field errors), link and unlink a Collection editor, open Ustawienia, and glance at light and dark mode."
|
||||
expected: "Everything still behaves as approved in 10-UAT.md tests 2 to 5. The limited admin sees only fonoteka > Genres. Lists and forms render. The editor round trip works. The Albums form now also shows the Phase 10.1 widgets and partials, and they do not break the Phase 10 form."
|
||||
why_human: "10-UAT.md was approved on 2026-09-27 against c7487f6. Since then Phase 10.1 changed ListView.vue, FormView.vue, ListToolbar.vue, FormField.vue, registry.ts, router.ts and main.css, and fonoteka's Albums controller now registers plugin widgets and partials. The Phase 9 review fixes changed server-side navigation (WR-01, WR-02, WR-17). Vitest and the Postgres acceptance test pass, but D-23 keeps the real browser out of the automated suite, and the browser checks for these views (10.1-UAT.md tests 1 and 4) are still pending. Closing 10.1-UAT tests 1 and 4 with Genres, Collections and Settings included also closes this item."
|
||||
expected: "Everything still behaves as approved in 10-UAT.md tests 2 to 5. The limited admin sees only fonoteka > Genres. Lists and forms render. The editor round trip works. The Albums form's later widgets, partials and field types do not break the Phase 10 form; list state persisted in the URL and storage does not confuse paging or filtering."
|
||||
why_human: "10-UAT.md was approved on 2026-09-27 against c7487f6. Since then phases 10.1, 12.2, 14.2.1, 16.1, 16.2 and 16.3 changed ListView.vue (+97), FormView.vue, FormField.vue, formState.ts, registry.ts, AppShell.vue, PluginRail.vue, UserMenu.vue, useAuth.ts and main.css. Vitest and the Postgres acceptance test cover behavior, but D-23 keeps the real browser out of the automated suite. 10.1-UAT.md (tests 1 and 4) is still status: testing with all items pending; closing those with Genres, Collections and Settings included also closes this item."
|
||||
- test: "Carried: decide CR-01 (refresh ignores tokens_valid_after / is_activated)"
|
||||
expected: "Fix now or accept with override"
|
||||
why_human: "Security-policy decision"
|
||||
resolution: "Fixed (be4a923, a13a121). TestAdminRefreshRevocation re-run this session: PASS. Approved in 10-UAT.md test 1. Still applies, still resolved."
|
||||
resolution: "Fixed (be4a923, a13a121), approved in 10-UAT.md test 1. TestAdminRefreshRevocation re-run this session: PASS."
|
||||
- test: "Carried: Secure cookie on http://localhost (assumption A3)"
|
||||
expected: "Chrome and Firefox store summer_admin with default cookie_secure"
|
||||
why_human: "Browser cookie policy, non-inferable"
|
||||
resolution: "Approved in 10-UAT.md test 6. The cookie attributes (cabana auth.go) are unchanged in substance since then. Still resolved."
|
||||
resolution: "Approved in 10-UAT.md test 6. auth.go change since c05ad09 is only the /auth/me profile builder (profileFor with avatar); cookie attributes untouched."
|
||||
- test: "Carried: review the 17 judgment-tier prohibitions"
|
||||
expected: "Accept or reject the verifier's non-authoritative verdicts"
|
||||
why_human: "Judgment-tier prohibitions need human resolution"
|
||||
resolution: "Accepted in 10-UAT.md test 7. Re-checked against HEAD in this report and all are still not violated, so the acceptance carries over."
|
||||
resolution: "Accepted in 10-UAT.md test 7. Re-checked at HEAD; still not violated (see Prohibitions)."
|
||||
human_verified:
|
||||
- item: "CR-01 decision"
|
||||
uat: "10-UAT.md test 1 (pass)"
|
||||
- item: "A3 Secure cookie on http://localhost"
|
||||
uat: "10-UAT.md test 6 (pass)"
|
||||
- item: "17 judgment-tier prohibitions"
|
||||
uat: "10-UAT.md test 7 (pass)"
|
||||
---
|
||||
|
||||
# Phase 10: Admin Vue SPA Verification Report
|
||||
|
||||
**Phase Goal:** A minimal Vue 3 + TypeScript admin SPA renders login, permission-gated navigation, lists, forms and the relation manager for Albums, Artists, Collections, Genres and Styles, typed from the generated OpenAPI document.
|
||||
**Verified:** 2026-10-01T21:29:59Z (summercms.go HEAD f2f2279, fonoteka.go HEAD e62f4fc)
|
||||
**Status:** human_needed
|
||||
**Re-verification:** Yes. The previous report (c7487f6, passed) went stale. Phase 10.2 moved its 59 framework paths under `modules/`, and later phases changed covered code.
|
||||
**Verified:** 2026-10-11T13:53:00Z (summercms.go HEAD 07e579a, fonoteka.go HEAD e074028)
|
||||
**Status:** gaps_found
|
||||
**Re-verification:** Yes (quick mode). The previous report (c05ad09, human_needed) went stale because 76 covered files changed.
|
||||
|
||||
**MVP note:** ROADMAP marks this phase `mode: mvp`, but the goal is not a User Story. Following the precedent of Phases 1, 3, 5 and 8, the four ROADMAP success criteria are the contract and plan `must_haves` are supporting evidence.
|
||||
## What changed since c05ad09
|
||||
|
||||
## What changed since the previous verification
|
||||
|
||||
| Source | Change to covered code | Effect on this report |
|
||||
| Source | Covered code touched | Effect |
|
||||
|---|---|---|
|
||||
| Phase 10.2 (5e50b16, 57e7b56) | Framework packages moved to `modules/<pkg>`. Moves only, plus retargeted fixtures. | 59 covered paths re-mapped. No behavior change. |
|
||||
| Phase 10.1 (f928194..5bbb0ad) | Runtime extension point. The SPA gains `WidgetField`, `PartialField`, `PartialHost` with an allowlisted node renderer, `pluginAssets.ts`, toolbar actions in `ListToolbar.vue`, and plugin CSS scoped per controller in `router.ts`. `ListView.vue`, `FormView.vue`, `FormField.vue` and `registry.ts` were extended. cabana gains action and asset routes. The OpenAPI document and `schema.d.ts` were regenerated (+516 / +325 lines, additive). The dist was rebuilt. | Phase 10 tests still pass, together with the new ones (Vitest went from 441 to 681). The drift gates are clean. The changed views need a browser re-check, so a human item is open. |
|
||||
| Phase 11 (f7b6b0c, 93c735b, 5382947, 61da4d1) | cabana writes are commit-safe, transaction gates fail closed, the jwt.auth 401 gets a cache header, and the Phase 10 gate accepts the Phase 12 pending goldens | `go test` and the gate stages pass |
|
||||
| Phase 9 review fixes (b4b8b5d..4ae272e, 2da8112) | WR-01 wildcard permissions, WR-02 drops a denied main menu item and repoints its target, WR-17 merges an admin's own permissions over the role's, WR-03 and WR-05 refuse writes and relation link/unlink that are not declared, WR-14 mounts logout outside the guard and always clears the cookie, WR-11 case-insensitive unique emails, WR-19 TxFromContext | Re-checked against the SPA's contract: the assembled acceptance test (exact nav sets, CRUD, link/unlink, logout) and the named cabana tests pass |
|
||||
|
||||
## User Flow Coverage
|
||||
|
||||
Derived user story: *As a Płytarium admin, I want to log in to /plytadmin, see only what my role permits, and manage Albums, Artists, Collections, Genres, Styles and Collection editors, so that the catalogue can be administered without the PHP backend.*
|
||||
|
||||
| Step | Expected | Evidence (this session) | Status |
|
||||
|---|---|---|---|
|
||||
| Open /plytadmin | Embedded SPA served with base /plytadmin | `modules/boardwalk/boardwalk.go`, `TestPhase10TracerSPA` PASS, `check-admin-dist.sh` "matches a fresh build" | VERIFIED |
|
||||
| Log in | Cookie session, no token in body | `modules/cabana/auth.go` login, `useAuth.login`, `LoginView.test.ts` (Vitest PASS), `TestPhase10Coverage` PASS | VERIFIED |
|
||||
| See permitted navigation | Limited admin sees Genres only | `TestPhase10AssembledAcceptance` SC-1 PASS (exact nav sets) and `TestNavigationDropsDeniedParentAndRepointsTarget` PASS | VERIFIED (automated); browser re-check pending |
|
||||
| Use five lists and forms | Schema-driven list and form, create, update | `TestPhase10AssembledAcceptance` SC-2 and `TestPhase10Controllers` PASS, ListView/FormView Vitest PASS | VERIFIED (automated); browser re-check pending |
|
||||
| Link and unlink an editor | Search candidates, link, unlink | `TestPhase10AssembledAcceptance` SC-3 PASS, `relation.smoke.test.ts` PASS | VERIFIED (automated); browser re-check pending |
|
||||
| Stay signed in / be signed out | Refresh keeps an active session; reset, deactivation or deletion ends it | `TestAdminRefreshRevocation` PASS | VERIFIED |
|
||||
| Log out | Cookie expired, old cookie 401, works with an expired access token | Acceptance test (logout then /auth/me 401) and `TestAdminLogoutRevokesExpiredRefreshableToken` PASS | VERIFIED |
|
||||
| 12.2-04 (ea33296) | adds `admin/src/api/files.ts` (XHR upload) and `FileCaptionModal.vue` | Phase 10 hygiene gate goes red (gaps 1-3) |
|
||||
| 14.2.1 (a04116d, a913eec) | `mlLocale.ts`, `MLField.vue`, `MarkdownField.vue` (sanitized v-html, gate allowlisted in 27711b7) | `mlLocale.ts`, `MLField.vue` imported by no test (gap 2) |
|
||||
| 16.1 / quick fixes (9cac45c, cd25af0) | list state kept in URL and localStorage (`listState.ts`), gate allowlisted | Storage rule still enforced; no token stored (comment and code checked) |
|
||||
| 16.2 (717d46e..4adb48a) | plugin field types: cabana `form_schema.go`, `registry.go`, `pact/capabilities.go`, `FormField.vue`, `formState.ts`, `registry.ts` | Phase 10 tests still pass |
|
||||
| 16.3 (b9273c1..b45af8e) | API tokens: cabana `http.go`, `contracts.go`, `admin_openapi.go`, `ApiTokensPanel.vue`, `ApiTokenCreateDialog.vue`; OpenAPI and `schema.d.ts` regenerated; `types.ts` +12 aliases | Two components imported by no test (gap 2); types.ts still aliases only |
|
||||
| My account / avatars (143eca5, 64d21c8), shell fixes | `auth.go` `/auth/me` profile via `profileFor`, `UserMenu.vue`, `AppShell.vue`, `PluginRail.vue`, `Breadcrumbs.vue`, `useAuth.ts` | Phase 10 Go tests and fonoteka acceptance pass |
|
||||
|
||||
## Goal Achievement
|
||||
|
||||
### Observable Truths (ROADMAP contract)
|
||||
|
||||
| # | Truth | Status | Evidence |
|
||||
| # | Truth | Status | Evidence (this session) |
|
||||
|---|---|---|---|
|
||||
| 1 | An admin logs in through the SPA and sees only the navigation items their permissions allow. | ✓ VERIFIED | Server: `TestPhase10AssembledAcceptance` (fonoteka, Postgres) asserts the limited admin's nav is exactly `fonoteka:[genres]`, the developer's is `albums,collections,genres,styles,artists`, the limited admin gets 403 on albums and an empty settings list. It passes at HEAD with the Phase 9 WR-01/WR-02/WR-17 permission changes in place. `TestNavigationDropsDeniedParentAndRepointsTarget`: PASS. SPA: `useNavigation.ts`, `PluginRail.vue` and `SectionPanel.vue` are unchanged since c7487f6. Their Vitest tests pass. |
|
||||
| 2 | Each of the five controllers renders a working list and form generated from its JSON schema. | ✓ VERIFIED | Server: the SC-2 loop and `TestPhase10Controllers` (fields and columns equal the tracked YAML) pass. `TestCRUDOperationsFollowDeclarations` (Phase 9 WR-03) passes, and SC-2's create and update still succeed under it. SPA: `ListView.vue` still loads `/schema/list` and the list, and `FormView.vue` still loads `/schema/form` and the record and then POSTs or PUTs. 10.1 adds toolbar actions, widgets, partials and plugin CSS on top. `ListView.test.ts` (+171 lines) and `FormView.test.ts` (+144) pass with the original Phase 10 cases intact. Vitest: 53 files, 681 passed. Browser confirmation of the changed views is the open human item. |
|
||||
| 3 | The Collections form's relation manager lets an admin search, link and unlink an editor. | ✓ VERIFIED | Server: the SC-3 block covers candidates with the owner excluded, link, list, the linked user dropping out of the candidates, unlink, and an empty list afterwards. It passes with Phase 9 WR-05 (undeclared link/unlink refused) in place. SPA: `RelationManager.vue` and `RelationPickerModal.vue` are unchanged since c7487f6, and their tests and `relation.smoke.test.ts` pass. |
|
||||
| 4 | API calls in the SPA use TypeScript types generated from the OpenAPI document, with no hand-maintained duplicate type. | ✓ VERIFIED | `client.ts` is `createClient<paths>` over the generated `schema.d.ts`. `admin/src` has no other `fetch(`, and `pluginAssets.ts` loads same-origin assets through elements, not a fetch. `types.ts` (+12 lines for the 10.1 types) still contains only aliases onto `components['schemas']` and `paths[...]`. `check-admin-openapi.sh --check`: exit 0. `check-phase10.sh --hygiene`: passed. |
|
||||
| 1 | An admin logs in through the SPA and sees only the navigation items their permissions allow. | ✓ VERIFIED | fonoteka `TestPhase10AssembledAcceptance` PASS (exact nav sets for limited admin and developer, 403 on albums for the limited admin). cabana `TestNavigationDropsDeniedParentAndRepointsTarget`, `TestAdminRefreshRevocation`, `TestAdminLogoutRevokesExpiredRefreshableToken`, `TestPhase10*` PASS. SPA nav/auth Vitest is in the orchestrator's parallel regression run. |
|
||||
| 2 | Each of the five controllers renders a working list and form generated from its JSON schema. | ✓ VERIFIED | `TestPhase10Controllers` and SC-2 loop of `TestPhase10AssembledAcceptance` PASS; `TestCRUDOperationsFollowDeclarations` PASS. `ListView.vue`/`FormView.vue` still load `/schema/list`, `/schema/form` and records through the typed client. Browser re-check of the changed views remains the open human item. |
|
||||
| 3 | The Collections form's relation manager lets an admin search, link and unlink an editor. | ✓ VERIFIED | SC-3 block of `TestPhase10AssembledAcceptance` PASS. `RelationManager.vue` and `RelationPickerModal.vue` unchanged since c05ad09. |
|
||||
| 4 | API calls in the SPA use TypeScript types generated from the OpenAPI document, with no hand-maintained duplicate type. | ✓ VERIFIED (substance) | `client.ts` is `createClient<paths>`; no `fetch(` elsewhere in `admin/src`. `types.ts` still contains only aliases (new 16.2/16.3 aliases onto `Schemas['cabana.*']`). `files.ts` types all wire shapes through those aliases; its XHR exists only for upload progress. `check-admin-openapi.sh --check`: exit 0. The mechanical gate for this SC is red, see gaps. |
|
||||
|
||||
**Score:** 4/4 ROADMAP truths verified (0 present-but-behavior-unverified).
|
||||
**Score:** 4/4 ROADMAP truths hold in substance. Plan truths 43/46: three 10-05 truths about the phase gate fail (one root cause).
|
||||
|
||||
### Plan must-have truths (supporting evidence)
|
||||
### Plan must-have truths
|
||||
|
||||
There are 46 plan truths across 10-01..10-05. The earlier runs verified all of them, with A3 human-observed. Their evidence is the named tests and gates, and all of those were re-run this session as part of `go test ./...` (summercms.go), the fonoteka Phase 10 acceptance tests, Vitest, the dist and OpenAPI drift gates, and the gate stages `--self-test`, `--hygiene`, `--security` and `--evidence`. All of them pass. The renamed packages carry the same tests: `modules/cabana/phase10_*_test.go`, `modules/phrasebook/phase10_test.go`, `modules/surf/admin_prefix_test.go` and the others in covered_files.
|
||||
The 43 truths not listed in `gaps` are carried from the baseline: their named tests were re-run this session where they touch changed code (cabana, phrasebook, surf, boardwalk Phase 10 tests; fonoteka Postgres acceptance; dist and OpenAPI drift gates; `--security`), and the rest sit in Vitest, which the orchestrator runs in parallel.
|
||||
|
||||
Backstop (non-inferable) truths:
|
||||
|
||||
| Truth | Evidence | Status |
|
||||
| Truth (10-05) | Status | Evidence |
|
||||
|---|---|---|
|
||||
| A1 default prefix /backend; fonoteka /plytadmin | `modules/cabana/prefix.go` `DefaultAdminPrefix`, `TestPhase10Prefix` in the passing cabana run | VERIFIED |
|
||||
| A3 Secure cookie accepted on http://localhost | 10-UAT.md test 6 (human-observed). The cookie attributes are unchanged in substance. | VERIFIED (human-observed) |
|
||||
| A10 30 s blacklist grace plus single-flight refresh | `modules/cabana/auth.go` reads `admin.jwt.blacklist_grace`, fonoteka `config/admin.yaml`, `client.test.ts` (Vitest PASS) | VERIFIED |
|
||||
| A8 pivot sort_order = array index | fonoteka `admin_phase10_relations_test.go` (package passes) | VERIFIED |
|
||||
| Required relation is a schema hint only | `TestPhase10RelationSave` PASS | VERIFIED |
|
||||
| A6 dark mode follows the system only | `theme.ts`, `theme.test.ts` PASS | VERIFIED |
|
||||
| SC-4 mechanical enforcement | `check-phase10.sh --hygiene` PASS | VERIFIED |
|
||||
| SC-4 hygiene: `admin/src/api` holds only schema.d.ts, client.ts, types.ts; no direct network call outside client.ts | ✗ FAILED | `check-phase10.sh --hygiene` exit 1: `admin/src/api/files.ts:150 new XMLHttpRequest()`, `unexpected files in admin/src/api: admin/src/api/files.ts` |
|
||||
| Every `admin/src` .ts/.vue (except main.ts, schema.d.ts, env.d.ts) imported by a test | ✗ FAILED | `--hygiene`: ApiTokenCreateDialog.vue, ApiTokensPanel.vue, FileCaptionModal.vue, MLField.vue, mlLocale.ts "imported by no test" |
|
||||
| `--all` is the acceptance command; `--self-test` proves detectors fail closed | ✗ FAILED | `--self-test` exit 1: "self-test hygiene rejected the clean scratch copy" |
|
||||
|
||||
Backstop truths (A1 prefix, A3 cookie, A10 blacklist grace, A8 pivot order, required-relation hint, A6 dark mode) are unchanged: their source files are untouched in substance and the A3 approval (10-UAT test 6) carries over.
|
||||
|
||||
### Prohibitions (judgment tier)
|
||||
|
||||
All 17 verdicts were accepted in 10-UAT.md test 7. I re-checked them against the code that changed since:
|
||||
Accepted in 10-UAT.md test 7, re-checked at HEAD:
|
||||
|
||||
- No Płytarium or fonoteka names appear in `admin/src`, `admin/tests`, `admin/openapi` or `modules/boardwalk/dist`. A grep came back empty, and the hygiene gate passes.
|
||||
- `admin/src` has no `v-html` or `innerHTML`. The 10.1 partials are built from an allowlisted node tree with `h()`, and text is always text (`partialNodes.ts`). Plugin labels and comments are still rendered as text.
|
||||
- Plugin JS and CSS come from cabana's same-origin asset route, so nothing loads from a foreign origin.
|
||||
- The cookie login and refresh paths still never return the JWT in a body.
|
||||
- Phase 9 WR-03 and WR-05 tighten "relation save never writes a protected FK or an out-of-scope id". They do not weaken it.
|
||||
- No consumer application names in `admin/src`, `admin/tests`, `admin/openapi`, `modules/boardwalk/dist` (grep empty).
|
||||
- Raw HTML: one `v-html` in `admin/src` (`MarkdownField.vue:128`, `sanitizedHtml`, set only from the server's 2xx sanitized answer, allowlisted in the gate by 27711b7, Phase 14.2.1 scope). Plugin labels and comments are still rendered as text.
|
||||
- Browser storage holds the sidebar flag and per-list query state only; `listState.ts` documents and implements no token or record data.
|
||||
- `modules/boardwalk/dist` references no foreign origin (`--hygiene` reached and passed that rule; only the rules in `gaps` fired).
|
||||
- Cookie login/refresh never return the JWT in a body (`TestPhase10CookieAuth` in `--security` PASS).
|
||||
|
||||
All 17 remain not violated, and the human acceptance carries over.
|
||||
All 17 remain not violated.
|
||||
|
||||
### Required Artifacts
|
||||
|
||||
| Artifact | Status | Details |
|
||||
|---|---|---|
|
||||
| `admin/` SPA (views, components, state, api, app) | ✓ VERIFIED | It exists, has substance and is wired, and it is embedded via `modules/boardwalk/dist`, which matches a fresh build |
|
||||
| `admin/openapi/admin.json`, `admin/src/api/schema.d.ts`, `admin/src/api/types.ts` | ✓ VERIFIED | No drift from generation |
|
||||
| `modules/boardwalk/boardwalk.go` + `dist/` | ✓ VERIFIED | `TestPhase10TracerSPA` PASS |
|
||||
| `modules/cabana/{auth,http,crud,relation,relation_field,form_schema,list_schema,filter_schema,schema_types,registry,contracts,csrf,lang,messages,prefix,admin_openapi}.go` | ✓ VERIFIED | Moved under modules/ and changed by 10.1, 11 and the Phase 9 fixes. The cabana package passes. |
|
||||
| `modules/bouncer/{jwt,refresh}.go` | ✓ VERIFIED | `RefreshAudienceFor` still wired from `modules/cabana/auth.go`. The new WR-14 logout helper is additive. |
|
||||
| `modules/pact/capabilities.go`, `modules/phrasebook/*`, `modules/surf/router.go` | ✓ VERIFIED | Packages pass |
|
||||
| `scripts/check-phase10.sh`, `check-admin-dist.sh`, `check-admin-openapi.sh` | ✓ VERIFIED | Retargeted to `modules/` paths, and every stage run passes |
|
||||
| `../fonoteka.go/plugins/golem15/fonoteka/admin_phase10_*_test.go` | ✓ VERIFIED | At e62f4fc: Acceptance, Tracer and Controllers PASS |
|
||||
| `admin/` SPA | ✓ VERIFIED | Embedded via `modules/boardwalk/dist`; `check-admin-dist.sh` exit 0 (bundles index-BeX-076N.css, index-CXQZEJp2.js) |
|
||||
| `admin/openapi/admin.json`, `schema.d.ts`, `types.ts` | ✓ VERIFIED | `check-admin-openapi.sh --check` exit 0; types.ts alias-only |
|
||||
| `modules/cabana/*`, `modules/bouncer/*`, `modules/pact/capabilities.go`, `modules/phrasebook/*`, `modules/surf/router.go`, `modules/boardwalk/boardwalk.go` | ✓ VERIFIED | Targeted Phase 10 tests ok in all four packages |
|
||||
| `scripts/check-phase10.sh` | ✗ RED | `--security` exit 0; `--hygiene` and `--self-test` exit 1 (gaps) |
|
||||
| `scripts/check-admin-dist.sh`, `scripts/check-admin-openapi.sh` | ✓ VERIFIED | exit 0 |
|
||||
| fonoteka `admin_phase10_*_test.go` | ✓ VERIFIED | Acceptance, Tracer, Controllers PASS at e074028 |
|
||||
|
||||
### Key Link Verification
|
||||
|
||||
| From | To | Via | Status |
|
||||
|---|---|---|---|
|
||||
| `admin/src/api/client.ts` | generated `schema.d.ts` | `createClient<paths>`, the only `fetch(` in `admin/src` | WIRED |
|
||||
| `admin/src/state/useAuth.ts` logout | `POST /auth/logout` | `modules/cabana/http.go:205`, now mounted outside the guard with `requireAjax`. The client sets `X-Requested-With` on every request (`client.ts:71`). | WIRED |
|
||||
| `modules/cabana/auth.go` refresh | `bouncer.RefreshAudienceFor` → the guard's `UserProvider` | `s.users` (`lazyBackendUsers`) | WIRED |
|
||||
| `admin/src/views/ListView.vue` / `FormView.vue` | `/schema/list`, `/schema/form`, records | client calls (10.1 additions on top) | WIRED |
|
||||
| `RelationManager.vue` | `/relations/{name}`, `/candidates` | client calls | WIRED |
|
||||
| `admin/src/api/client.ts` | generated `schema.d.ts` | `createClient<paths>` | WIRED |
|
||||
| `admin/src/api/files.ts` | generated aliases + client refresh | imports from `./types` and `./client` | WIRED (outside the gate's allowlist) |
|
||||
| `useAuth.ts` logout | `POST /auth/logout` | outside the guard, always clears cookie | WIRED (`TestAdminLogoutRevokesExpiredRefreshableToken` PASS) |
|
||||
| `cabana/auth.go` refresh | `bouncer.RefreshAudienceFor` | `s.users` | WIRED (`TestAdminRefreshRevocation` PASS) |
|
||||
| `ListView.vue` / `FormView.vue` / `RelationManager.vue` | schema, record and relation endpoints | typed client | WIRED |
|
||||
| `modules/boardwalk` | `admin` build | `go:embed dist`, drift gate | WIRED |
|
||||
|
||||
### Data-Flow Trace (Level 4)
|
||||
|
||||
These are unchanged in structure. Every flow is ✓ FLOWING:
|
||||
|
||||
- navigation comes from `GET /navigation`, filtered on the server
|
||||
- list rows and columns come from the list endpoint and `/schema/list`
|
||||
- form fields and the record come from `/schema/form` and `GET /{id}`
|
||||
- the relation manager's linked rows and candidates come from `/relations/{name}` and `/candidates`
|
||||
- strings come from `GET /lang`
|
||||
Unchanged in structure; every flow FLOWING (navigation from `GET /navigation` filtered server-side, lists/forms from schema endpoints and records, relations from `/relations/{name}` and `/candidates`, strings from `GET /lang`).
|
||||
|
||||
### Behavioral Spot-Checks (run this session)
|
||||
|
||||
| Behavior | Command | Result | Status |
|
||||
|---|---|---|---|
|
||||
| Vet | `go vet ./...` (summercms.go) | exit 0 | ✓ PASS |
|
||||
| Full Go suite | `go test -count=1 ./...` (summercms.go), run once | Most packages ok. Eight packages failed only because testcontainers Postgres did not start within the timeout (`context deadline exceeded`, and one `internal/dev` watch timeout) while Vitest and other suites shared the machine: docs/examples/blog, internal/dev, beachcomber, bouncer, cabana, conga, lagoon/attach, lighthouse. | see re-run |
|
||||
| Re-run of those 8 packages serially | `go test -count=1 -p 1 <8 pkgs>` | all 8 ok, exit 0 | ✓ PASS |
|
||||
| Logout, nav, refresh, CRUD gating, Phase 10 coverage | `go test -count=1 -run '^(TestAdminLogoutRevokesExpiredRefreshableToken\|TestNavigationDropsDeniedParentAndRepointsTarget\|TestAdminRefreshRevocation\|TestPhase10Coverage\|TestCRUDOperationsFollowDeclarations)$' ./modules/cabana/` | all PASS | ✓ PASS |
|
||||
| SC-1..SC-3 assembled on Postgres plus tracer and controllers | `go test -count=1 -run '^(TestPhase10AssembledAcceptance\|TestPhase10TracerSPA\|TestPhase10Controllers)$' ./plugins/golem15/fonoteka/` (fonoteka.go) | 3 PASS, ok 6.6s | ✓ PASS |
|
||||
| SPA unit/component suite | `npx vitest run` (admin) | 53 files, 681 passed | ✓ PASS |
|
||||
| Embedded dist drift (incl. vue-tsc) | `scripts/check-admin-dist.sh` | "modules/boardwalk/dist matches a fresh build" | ✓ PASS |
|
||||
| Phase 10 framework tests | `go test -count=1 -run 'TestPhase10\|TestAdminLogoutRevokesExpiredRefreshableToken\|TestNavigationDropsDeniedParentAndRepointsTarget\|TestAdminRefreshRevocation\|TestCRUDOperationsFollowDeclarations' ./modules/{cabana,phrasebook,surf,boardwalk}/` | 4 packages ok | ✓ PASS |
|
||||
| SC-1..SC-3 on Postgres | fonoteka.go `go test -count=1 -run '^(TestPhase10AssembledAcceptance\|TestPhase10TracerSPA\|TestPhase10Controllers)$' ./plugins/golem15/fonoteka/` | 3 PASS | ✓ PASS |
|
||||
| Embedded dist drift | `scripts/check-admin-dist.sh` | exit 0 | ✓ PASS |
|
||||
| OpenAPI and types drift | `scripts/check-admin-openapi.sh --check` | exit 0 | ✓ PASS |
|
||||
| Phase gate stages | `scripts/check-phase10.sh --self-test / --hygiene / --security / --evidence` | each exit 0 | ✓ PASS |
|
||||
| Gate security stage | `scripts/check-phase10.sh --security` | exit 0 | ✓ PASS |
|
||||
| Gate hygiene stage | `scripts/check-phase10.sh --hygiene` | exit 1, 7 refusals (files.ts x2, five untested modules) | ✗ FAIL |
|
||||
| Gate self-test | `scripts/check-phase10.sh --self-test` | exit 1, "rejected the clean scratch copy" | ✗ FAIL |
|
||||
| go vet, full `go test -short`, Vitest | orchestrator's parallel regression gate | not duplicated here | — |
|
||||
|
||||
### Probe Execution
|
||||
|
||||
No `probe-*.sh` scripts are declared or present. `check-phase10.sh` is the phase gate. Its stages were run as listed above. Its `--go`, `--postgres`, `--spa`, `--openapi` and `--dist` stages were covered directly by the full Go run with the serial re-run, the fonoteka tests, Vitest and the two drift scripts.
|
||||
No `probe-*.sh` declared or present; `check-phase10.sh` is the phase gate (stages above).
|
||||
|
||||
### Requirements Coverage
|
||||
|
||||
| Requirement | Source Plan | Description | Status | Evidence |
|
||||
|---|---|---|---|---|
|
||||
| ADMIN-06 | 10-01..10-05 | Minimal Vue 3 + TS SPA renders login, permission-gated navigation, lists, forms and the relation manager for the five controllers using generated types | ✓ SATISFIED (automated); browser re-check pending | Truths 1-4 |
|
||||
| ADMIN-06 | 10-01..10-05 | Minimal Vue 3 + TS SPA renders login, permission-gated navigation, lists, forms and the relation manager for the five controllers using generated types | ✓ SATISFIED (substance); gate red; browser re-check pending | Truths 1-4 |
|
||||
|
||||
Orphaned requirements: none.
|
||||
|
||||
### Decision Coverage
|
||||
|
||||
All 28 trackable CONTEXT.md decisions are honored (no decision was reverted by the later phases).
|
||||
|
||||
### Anti-Patterns Found
|
||||
|
||||
| File | Pattern | Severity | Impact |
|
||||
|---|---|---|---|
|
||||
| `modules/cabana/auth.go`, `http.go` | Phase 10 review WR-01: logout behind the guard | resolved | Fixed by Phase 9 WR-14 (299d220) |
|
||||
| `modules/bouncer/refresh.go`, fonoteka `golem15/user` | WR-08: the site-user refresh ignores tokens_valid_after | ⚠️ Warning | Outside the Phase 10 contract. Core user plugin contract kept. |
|
||||
| `modules/cabana/relation_field.go`, `crud.go` | WR-02 and WR-03 (Phase 10 review) | ⚠️ Warning | Phase 9 WR-03 and WR-05 now refuse undeclared writes and link/unlink. Not re-triaged here. |
|
||||
| `modules/pact/capabilities.go` | WR-04: `FilterOptions(scope)` has no ctx or db | ⚠️ Warning | Open |
|
||||
| `admin/src/views/*.vue` | WR-05: loaders without try/catch | ⚠️ Warning | Open |
|
||||
| `ListView.vue`, `RelationManager.vue` | WR-06: no page clamp after delete or unlink | ⚠️ Warning | Open |
|
||||
| `modules/bouncer/refresh.go` | WR-07: the refresh window slides with no absolute cap | ⚠️ Warning | Residual risk in T-10-05 |
|
||||
| `scripts/check-phase10.sh` vs `admin/src/api/files.ts` | Phase gate not updated for a later-phase exception | 🛑 Blocker (evidenced: gate run red) | Phase 10 acceptance command fails |
|
||||
| five later-phase SPA modules | imported by no test | 🛑 Blocker (evidenced: gate run red) | Breaks the 10-05 every-module-tested rule |
|
||||
| Phase 10 review WR-04..WR-08 | carried from baseline | ⚠️ Warning | Unchanged, out of this re-check's scope |
|
||||
|
||||
None of the non-planning covered files contains an unreferenced `TBD`, `FIXME` or `XXX` marker (grep came back empty).
|
||||
|
||||
### Other observations (Info)
|
||||
|
||||
- Phase 10.1's own UAT (10.1-UAT.md) is still `status: testing` with 6 items pending. Its tests 1 and 4 overlap the open Phase 10 human item.
|
||||
- The summercms.go working tree has an uncommitted change to `.planning/phases/10.2-.../10.2-VERIFICATION.md` that this verifier did not make (another run in progress), plus the untracked `SummerCMS landing page.zip`. Neither is Phase 10 code.
|
||||
- The first full `go test` run was disturbed by machine load: Postgres containers timed out at startup. A fail-closed reading needs the serial re-run. If the gate is run in CI, run it on an otherwise idle machine.
|
||||
No unreferenced `TBD`/`FIXME`/`XXX` in changed covered files.
|
||||
|
||||
### Human Verification Required
|
||||
|
||||
### 1. Browser re-walk of the Phase 10 flows on the current build
|
||||
|
||||
**Test:** Run the fonoteka binary and open /plytadmin. Log in as a superuser and then as a genres-only admin. For each of the five controllers, use the list and form (search, sort, filter, paging, save, 422 field errors). Link and unlink a Collection editor. Open Ustawienia. Glance at light and dark mode.
|
||||
**Expected:** Everything still behaves as approved in 10-UAT.md tests 2 to 5. The Albums form's new 10.1 widgets and partials do not break the Phase 10 form.
|
||||
**Why human:** Phase 10.1 changed the very views the 2026-09-27 approval covered, and D-23 keeps browser e2e out of the automated suite. Closing 10.1-UAT tests 1 and 4 with Genres, Collections and Settings included also closes this item.
|
||||
**Test:** Run the fonoteka binary and open /plytadmin. Log in as a superuser and then as a genres-only admin. Use the list and form of each of the five controllers (search, sort, filter, paging, save, 422 field errors). Link and unlink a Collection editor. Open Ustawienia. Glance at light and dark mode.
|
||||
**Expected:** Behaves as approved in 10-UAT.md tests 2 to 5; later widgets, field types and persisted list state do not break the Phase 10 views.
|
||||
**Why human:** Later phases changed the views that the 2026-09-27 approval covered; D-23 keeps browser e2e out of the suite. 10.1-UAT tests 1 and 4 are still pending and overlap.
|
||||
|
||||
The carried items (CR-01, A3, the 17 prohibitions) remain resolved, with evidence re-run this session.
|
||||
Carried items CR-01, A3 and the 17 prohibitions stay resolved by 10-UAT.md tests 1, 6 and 7.
|
||||
|
||||
### Gaps Summary
|
||||
|
||||
There are no gaps. All four ROADMAP success criteria hold at HEAD on automated evidence re-run this session:
|
||||
One root cause, three failed plan truths: the Phase 10 acceptance gate `scripts/check-phase10.sh` is red at HEAD because later phases added SPA files without updating its hygiene rules or adding direct-import tests. It has been red since ea33296 (12.2-04, 2026-10-02); the 2026-10-05 refresh only recomputed the digest and did not re-run the gate.
|
||||
|
||||
- `go vet` is clean
|
||||
- every Go package passes, with eight container-startup timeouts cleared by a serial re-run
|
||||
- the fonoteka Postgres acceptance test passes
|
||||
- Vitest passes, 681 of 681
|
||||
- the dist and OpenAPI drift gates and four gate stages pass
|
||||
- `admin/src/api/files.ts` (XHR upload) trips the "direct fetch outside client.ts" and "unexpected files in admin/src/api" rules. Its wire types are the generated aliases, so SC-4's intent holds. The fix is a narrow allowlist entry like the MarkdownField and listState precedents, or routing the upload through client.ts.
|
||||
- `ApiTokenCreateDialog.vue`, `ApiTokensPanel.vue`, `FileCaptionModal.vue`, `MLField.vue` and `mlLocale.ts` are imported by no test. The fix is a direct import in a focused test for each.
|
||||
- `--self-test` fails only as a consequence of the two items above.
|
||||
|
||||
The status is human_needed, not passed, because the human browser approvals predate the Phase 10.1 changes to ListView, FormView, the toolbar, the router and the styles. Those approvals cannot be carried over to the changed views.
|
||||
The ROADMAP success criteria themselves hold on re-run evidence (fonoteka Postgres acceptance, Phase 10 Go tests, drift gates). No later phase in the roadmap takes over this gate, so nothing is deferred. A small `/msd-quick` fix that closes both items and re-runs `check-phase10.sh --self-test --hygiene` should restore human_needed (the browser re-walk stays open).
|
||||
|
||||
---
|
||||
|
||||
_Verified: 2026-10-01T21:29:59Z_
|
||||
_Verifier: Claude (gsd-verifier)_
|
||||
_Verified: 2026-10-11T13:53:00Z_
|
||||
_Verifier: Claude (msd-verifier)_
|
||||
|
||||
Reference in New Issue
Block a user