Files
summercms/.planning/phases/10-admin-vue-spa/10-05-PLAN.md
2026-09-27 14:11:07 +02:00

29 KiB

phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, estimate, must_haves
phase plan type wave depends_on files_modified autonomous requirements estimate must_haves
10-admin-vue-spa 05 execute 5
10-01
10-02
10-03
10-04
admin/vitest.config.ts
admin/tests/setup.ts
admin/tests/fixtures/**
admin/tests/app/i18n.test.ts
admin/tests/app/winterUrl.test.ts
admin/tests/app/listQuery.test.ts
admin/tests/app/runtime.test.ts
admin/tests/app/icons.test.ts
admin/tests/app/client.test.ts
admin/tests/app/router.test.ts
admin/tests/state/useAuth.test.ts
admin/tests/state/useNavigation.test.ts
admin/tests/state/useSidebar.test.ts
admin/tests/state/useToasts.test.ts
admin/tests/state/useSettings.test.ts
admin/tests/shell/AppShell.test.ts
admin/tests/shell/PluginRail.test.ts
admin/tests/shell/SectionPanel.test.ts
admin/tests/shell/SectionFlyout.test.ts
admin/tests/shell/UserMenu.test.ts
admin/tests/shell/Breadcrumbs.test.ts
admin/tests/list/DataTable.test.ts
admin/tests/list/ListToolbar.test.ts
admin/tests/list/FilterBar.test.ts
admin/tests/list/Pagination.test.ts
admin/tests/list/CellValue.test.ts
admin/tests/list/ListView.test.ts
admin/tests/form/registry.test.ts
admin/tests/form/FormGrid.test.ts
admin/tests/form/FormField.test.ts
admin/tests/form/FormTabs.test.ts
admin/tests/form/fields.test.ts
admin/tests/form/RelationField.test.ts
admin/tests/form/FormView.test.ts
admin/tests/form/Settings.test.ts
admin/tests/relation/RelationManager.test.ts
admin/tests/relation/RelationPickerModal.test.ts
admin/tests/views/LoginView.test.ts
boardwalk/boardwalk_test.go
bouncer/cookie_guard_test.go
cabana/phase10_coverage_test.go
phrasebook/phase10_test.go
surf/admin_prefix_test.go
internal/tools/swagger2openapi/main_test.go
../fonoteka.go/plugins/golem15/fonoteka/admin_phase10_e2e_test.go
scripts/check-phase10.sh
.planning/phases/10-admin-vue-spa/10-SECURITY-REVIEW.md
.planning/phases/10-admin-vue-spa/10-VALIDATION.md
true
ADMIN-06
tokens raw_tokens tasks confidence
110000 110000 3 low
truths artifacts key_links prohibitions
Per D-23 and the project rule that unit tests close every phase, Vitest suites exist for every module, composable, component and view under admin/src (tests/app, tests/state, tests/shell, tests/list, tests/form, tests/relation, tests/views) with neutral acme fixtures, and npm --prefix admin test passes with no browser e2e dependency.
Every Phase 10 Go change (cabana prefix/cookie/CSRF/options/relation save/messages/toolbar/filters/bundle, boardwalk, phrasebook Forms/Bundle/overrides, bouncer cookie guard, surf prefix collision, swagger2openapi unions) has named tests covering its success and failure branches, and both repositories pass go vet ./... and go test ./...
TestPhase10AssembledAcceptance proves the four success criteria through the real router at /plytadmin over cookie transport: a limited admin sees only permitted navigation while a developer sees every entry (SC-1); each of Albums, Artists, Collections, Genres and Styles serves its list, form schema, create and update (SC-2); the Collections editors relation searches candidates, links and unlinks (SC-3); every path it calls exists in admin/openapi/admin.json (SC-4).
scripts/check-phase10.sh --all exits non-zero on any failing stage, a go test run that matches zero tests or skips one, OpenAPI or dist drift, a hygiene violation, or an evidence gap; --self-test proves each of those detectors fails closed.
10-SECURITY-REVIEW.md lists T-10-01 through T-10-25 and T-10-SC with disposition, production mitigation, and the exact test or gate stage that fails when the mitigation is removed; 10-VALIDATION.md maps every plan task to its command with nyquist_compliant true only after the gate passes.
statement verification
[flagged assumption SC-4] 'No hand-maintained duplicate type' is enforced mechanically: admin/src/api holds only the generated schema.d.ts, the client, and type aliases onto generated schemas; no interface or type literal re-declares an API payload. backstop
path provides
scripts/check-phase10.sh Fail-closed Phase 10 gate with self-test, go, security, postgres, spa, openapi, dist, hygiene, evidence and all stages
path provides
../fonoteka.go/plugins/golem15/fonoteka/admin_phase10_e2e_test.go Assembled PostgreSQL acceptance for SC-1 to SC-4
path provides
cabana/phase10_coverage_test.go Remaining branch coverage for Phase 10 cabana changes
path provides
.planning/phases/10-admin-vue-spa/10-SECURITY-REVIEW.md Threat-to-test evidence ledger
from to via pattern
scripts/check-phase10.sh go test -json output zero-test, skip and failure detection per stage phase10_detect
from to via pattern
scripts/check-phase10.sh scripts/check-admin-openapi.sh and scripts/check-admin-dist.sh openapi and dist stages check-admin
from to via pattern
10-VALIDATION.md 10-01..10-05 task verify commands per-task verification map 10-0
[flagged-unverified] Phase acceptance must not depend on skipped PostgreSQL tests, zero-test runs, or a hand-edited boardwalk/dist or schema.d.ts.
[flagged-unverified] No test or fixture inside summercms.go may use Płytarium or fonoteka names; app names appear only in fonoteka.go tests.
[flagged-unverified] A high threat must not be marked mitigated without naming the executable test or gate stage that fails when the mitigation is removed.

Phase Goal

As a backend administrator, I want to open my project's own admin URL, log in and manage Albums, Artists, Collections, Genres and Styles through schema-driven lists, forms and the relation manager, so that I can administer the catalogue from one Go binary without the WinterCMS backend.

Close Phase 10 with full unit test coverage (the project rule: unit tests are the last plan), an assembled acceptance test for all four success criteria, and one fail-closed gate script with security evidence.

Purpose: Plans 10-01 to 10-04 carried smoke tests only; this plan brings every SPA module and every Go change to named, branch-level tests and makes the phase acceptance a single command. Decisions implemented: D-23 (Vitest plus Go tests, no Playwright), D-04 (drift gates in the phase gate), D-15/D-16 (SC-4 hygiene), D-28 (this is plan 05). Output: Vitest suites, Go coverage tests in both repos, scripts/check-phase10.sh, 10-SECURITY-REVIEW.md, finalized 10-VALIDATION.md.

Repos: Task 1 summercms.go; Task 2 summercms.go and fonoteka.go; Task 3 summercms.go (script) plus planning docs (separate docs commit). Never add co-author tags.

<execution_context> @/.claude/gsd-core/workflows/execute-plan.md @/.claude/gsd-core/templates/summary.md </execution_context>

@.planning/PROJECT.md @.planning/STATE.md @.planning/phases/10-admin-vue-spa/10-CONTEXT.md @.planning/phases/10-admin-vue-spa/10-RESEARCH.md @.planning/phases/10-admin-vue-spa/10-VALIDATION.md @.planning/phases/10-admin-vue-spa/10-01-SUMMARY.md @.planning/phases/10-admin-vue-spa/10-02-SUMMARY.md @.planning/phases/10-admin-vue-spa/10-03-SUMMARY.md @.planning/phases/10-admin-vue-spa/10-04-SUMMARY.md @scripts/check-phase9.sh @.planning/phases/09-backend-admin-authentication-and-schema-pipeline/09-SECURITY-REVIEW.md Gate pattern to reuse: `scripts/check-phase9.sh` (`phase9_detect` parses `go test -json` and exits 1 on fail, 2 on a skipped test, 3 on zero passing tests; `phase9_go DIR PKGS -run REGEX`; staged `case` dispatch; `--self-test` feeds synthetic bad runs to the detector). Threat IDs in this phase: T-10-01..T-10-08 and T-10-17 (Plan 10-01), T-10-09..T-10-15 (10-02), T-10-16, T-10-18..T-10-20 (10-03), T-10-21..T-10-23 (10-04), T-10-24..T-10-25 (this plan), T-10-SC (all plans).

Artifacts this phase produces

  • Vitest suites under admin/tests/{app,state,shell,list,form,relation,views} and shared fixtures/setup
  • Go tests: extended boardwalk/boardwalk_test.go, bouncer/cookie_guard_test.go, cabana/phase10_coverage_test.go, extended phrasebook/phase10_test.go, extended surf/admin_prefix_test.go, internal/tools/swagger2openapi/main_test.go, fonoteka TestPhase10AssembledAcceptance
  • scripts/check-phase10.sh with --self-test, --go, --security, --postgres, --spa, --openapi, --dist, --hygiene, --evidence, --all; detector phase10_detect
  • .planning/phases/10-admin-vue-spa/10-SECURITY-REVIEW.md; finalized 10-VALIDATION.md (nyquist_compliant: true)
Task 1: Bring every SPA module, composable and component under Vitest admin/vitest.config.ts, admin/tests/setup.ts, admin/tests/fixtures/**, admin/tests/app/i18n.test.ts, admin/tests/app/winterUrl.test.ts, admin/tests/app/listQuery.test.ts, admin/tests/app/runtime.test.ts, admin/tests/app/icons.test.ts, admin/tests/app/client.test.ts, admin/tests/app/router.test.ts, admin/tests/state/useAuth.test.ts, admin/tests/state/useNavigation.test.ts, admin/tests/state/useSidebar.test.ts, admin/tests/state/useToasts.test.ts, admin/tests/state/useSettings.test.ts, admin/tests/shell/AppShell.test.ts, admin/tests/shell/PluginRail.test.ts, admin/tests/shell/SectionPanel.test.ts, admin/tests/shell/SectionFlyout.test.ts, admin/tests/shell/UserMenu.test.ts, admin/tests/shell/Breadcrumbs.test.ts, admin/tests/list/DataTable.test.ts, admin/tests/list/ListToolbar.test.ts, admin/tests/list/FilterBar.test.ts, admin/tests/list/Pagination.test.ts, admin/tests/list/CellValue.test.ts, admin/tests/list/ListView.test.ts, admin/tests/form/registry.test.ts, admin/tests/form/FormGrid.test.ts, admin/tests/form/FormField.test.ts, admin/tests/form/FormTabs.test.ts, admin/tests/form/fields.test.ts, admin/tests/form/RelationField.test.ts, admin/tests/form/FormView.test.ts, admin/tests/form/Settings.test.ts, admin/tests/relation/RelationManager.test.ts, admin/tests/relation/RelationPickerModal.test.ts, admin/tests/views/LoginView.test.ts admin/src (every module being tested), admin/tests/setup.ts, admin/tests/smoke/*.smoke.test.ts, admin/tests/fixtures/*, .planning/phases/10-admin-vue-spa/design/README.md (States, Interactions), phrasebook/translator.go (interpolate, Choice) - app: interpolate parity with phrasebook for :name/:Name/:NAME and overlapping names; plural selection for pl counts 1, 2, 5, 22, 25 and en 1, 2 with fallback to other; t returns the key when missing; mapWinterUrl for empty, create, update/:id, foreign and malformed input; listQuery round-trip including filter[...] and invalid numbers; runtime reads the meta and derives the API base; icons resolve lucide names, Winter aliases and the fallback; client sets X-Requested-With, single-flights refresh for concurrent 401s, replays once, then routes to login with redirect; router guard rejects protocol-relative and absolute redirect values. - state: useAuth login/logout/me and proactive refresh timing; useNavigation active plugin and first permitted controller; useSidebar viewport versus persisted manual state and storage key; useToasts queue and auto-dismiss; useSettings visibility. - shell, list, form, relation, views: each component's states from the design (selected, empty, empty search, loading, 422, toast, modal, collapsed, flyout, dark) plus its a11y roles and attributes (aria-sort, aria-current, aria-invalid, aria-describedby, aria-required, role=switch, role=tablist/tab, role=dialog with aria-modal, role=listbox with aria-multiselectable, role=menu, role=status, role=alert). Per D-23, write Vitest component and unit tests with @vue/test-utils and happy-dom for every file under `admin/src` (the list in `` is one suite per module; add a suite if a module was added after planning). Mock HTTP by injecting a fetch implementation into the openapi-fetch client from `tests/setup.ts` (never a real network), keep fixtures neutral (`acme.demo.*`, labels like "Widgets", "Members"; no Płytarium words) and shaped from real generated types (fixtures are typed by importing the generated `components` schemas in a typed helper so drift fails typecheck). Reproduce the design's extra shapes as fixtures only (D-08): tabs, switch and checkbox toggle cards, single, multiple and read-only relations, an unknown `colorpicker` type, and all three filter shapes. Assert behaviour and accessibility attributes, not snapshots of markup. Keep the smoke tests. `vitest.config.ts` keeps happy-dom and adds `restoreMocks: true`; no coverage-provider package is added (it would be a new dependency). npm --prefix admin run typecheck && npm --prefix admin test -- tests/app tests/state tests/shell tests/list tests/form tests/relation tests/views tests/smoke Non-zero exit; vitest prints "No test files found" for any listed directory, or any "FAIL" line; vue-tsc reports an error. - 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 (checked by the hygiene stage in Task 3). - `grep -rniE 'pl[yý]tarium|fonoteka|albumy|kolekcj' admin/tests` prints nothing. - `grep -rn 'playwright' admin/package.json` prints nothing. The whole SPA has behaviour and accessibility tests that run offline in seconds. Task 2: Cover every Phase 10 Go change and prove the four success criteria end to end boardwalk/boardwalk_test.go, bouncer/cookie_guard_test.go, cabana/phase10_coverage_test.go, phrasebook/phase10_test.go, surf/admin_prefix_test.go, internal/tools/swagger2openapi/main_test.go, ../fonoteka.go/plugins/golem15/fonoteka/admin_phase10_e2e_test.go boardwalk/boardwalk.go, bouncer/jwt.go, cabana/prefix.go, cabana/csrf.go, cabana/auth.go, cabana/http.go, cabana/relation_field.go, cabana/messages.go, cabana/lang.go, cabana/list_schema.go, cabana/filter_schema.go, phrasebook/loader.go, phrasebook/translator.go, surf/router.go, internal/tools/swagger2openapi/main.go, ../fonoteka.go/plugins/golem15/fonoteka/admin_phase09_e2e_test.go, ../fonoteka.go/plugins/golem15/fonoteka/admin_paths_test.go - bouncer TestPhase10CookieGuard: the backend guard reads summer_admin when no Bearer is present, Bearer wins when both are, an empty cookie is unauthenticated, a frontend-audience token in the cookie is rejected, a blacklisted jti in the cookie is rejected. - boardwalk: HEAD requests, query strings, encoded traversal, index.html requested by name gets the rewritten bytes, prefix with nested segments, extensionless unknown path returns index, unknown extension type falls back to mime. - cabana TestPhase10Coverage: every mounted unsafe route (including the options, filters and lang routes added later) is covered by the CSRF walk; options and filters edge cases (empty search, page beyond last, per_page above cap); relation labels for read-only fields; messages defaults for relation schemas; toolbar create omission without a form; bundle fallback to app.fallback_locale; refresh with an expired access token inside the refresh window via cookie. - phrasebook: override precedence (override beats plugin beats framework), a new locale via override, Bundle merge order, Forms for every entry shape. - surf: the exact prefix path and a deeper path both collide; a sibling path such as /backendx does not. - swagger2openapi TestUnionRewrite: jsonScalar and fieldContext become the documented unions and other components are untouched. - fonoteka TestPhase10AssembledAcceptance: SC-1 to SC-4 as stated in must_haves. Write the tests in `` using the existing Testcontainers PostgreSQL helpers where a database is needed (cabana's helper and fonoteka's `bootDB`/`bootConfig`), never an in-memory substitute for assembled cases. `TestPhase10AssembledAcceptance` seeds a developer-role admin, a limited admin granted only `golem15.fonoteka.access_genres`, a matching frontend user for the Albums collection resolver (Phase 9 D-14), a genre, two artists and a second user; then, through `adminAPI(...)` at `/plytadmin` with cookie login and `X-Requested-With`: compares both admins' `/navigation` (limited sees only Genres under Fonoteka, developer sees every side-menu entry including Collections); for each of the five controllers GETs `schema/list`, the list, `schema/form`, POSTs a record (album with genre and ordered artists) and PUTs an update; on a Collection GETs editors candidates with a search term, links the second user, sees it in the linked list, unlinks it; GETs and PUTs the fonoteka settings; loads `/lang`; logs out and gets 401 with the old cookie; finally asserts every path template it called exists in `admin/openapi/admin.json` of the framework (read via `../summercms.go/admin/openapi/admin.json` from the app test, the app knowing the framework is the allowed direction). Fill any branch the earlier plans left without a named test (extend the listed files only). go vet ./... && go test ./boardwalk ./bouncer ./cabana ./phrasebook ./surf ./internal/tools/swagger2openapi -count=1 && go test ./bouncer ./cabana ./phrasebook ./surf ./internal/tools/swagger2openapi -run '^Test(Phase10CookieGuard|Phase10Coverage|Phase10Forms|Phase10LangOverride|Phase10AdminPrefixCollision|UnionRewrite)$' -count=1 -v && (cd ../fonoteka.go && go vet ./... && go test ./plugins/golem15/fonoteka -run '^TestPhase10AssembledAcceptance$' -count=1 -v && go test ./... -count=1) Any command exits non-zero; the verbose runs lack a "--- PASS" line for TestPhase10CookieGuard, TestPhase10Coverage, TestPhase10Forms, TestPhase10LangOverride, TestPhase10AdminPrefixCollision, TestUnionRewrite or TestPhase10AssembledAcceptance, or print "no tests to run" or a SKIP. - Each behavior above is a named passing test; TestPhase10AssembledAcceptance runs against real PostgreSQL and exercises SC-1 to SC-4. - Both repositories pass `go vet ./...` and `go test ./...`. - `grep -rniE 'pl[yý]tarium|fonoteka' boardwalk bouncer cabana phrasebook surf internal/tools --include=*_test.go` prints nothing. Every Go change in Phase 10 has branch-level tests, and one assembled test proves the four success criteria through the real router. Task 3: One fail-closed Phase 10 gate plus threat and validation evidence scripts/check-phase10.sh, .planning/phases/10-admin-vue-spa/10-SECURITY-REVIEW.md, .planning/phases/10-admin-vue-spa/10-VALIDATION.md scripts/check-phase9.sh, scripts/check-admin-openapi.sh, scripts/check-admin-dist.sh, .planning/phases/10-admin-vue-spa/10-VALIDATION.md, .planning/phases/09-backend-admin-authentication-and-schema-pipeline/09-SECURITY-REVIEW.md, every 10-0N-PLAN.md threat_model and verify block, every 10-0N-SUMMARY.md (1) `scripts/check-phase10.sh` (bash, set -euo pipefail, committed with the executable bit), modelled on `scripts/check-phase9.sh`: `phase10_detect` parses `go test -json` (exit 1 fail, 2 skip, 3 zero tests, 4 non-JSON); `phase10_go DIR PKGS -run REGEX` runs it. Stages: `--self-test` (bash -n, detector fails on synthetic fail, skip and zero-test runs, every mode flag present, the hygiene stage fails on a temporary fixture containing a raw-HTML directive in a scratch copy); `--go` (go vet and go test ./... in both repos); `--security` (TestPhase10CookieAuth, TestPhase10CSRF, TestPhase10Prefix, TestPhase10CookieGuard, TestPhase10RelationForgedID, TestPhase10CollectionOwnerReadOnly, TestPhase10Bundle, boardwalk tests, plus `scripts/check-phase9.sh --security`); `--postgres` (TestPhase10TracerSPA, TestPhase10AdminAuth, TestPhase10AlbumRelations, TestPhase10Controllers, TestPhase10AssembledAcceptance through the detector so a skip or zero match fails); `--spa` (`npm --prefix admin ci`, typecheck, `npm --prefix admin test`); `--openapi` (`scripts/check-admin-openapi.sh --check`, TestPhase10OpenAPIConformance, TestPhase09ContractInventory, fonoteka `scripts/check-openapi.sh`); `--dist` (`scripts/check-admin-dist.sh`); `--hygiene` (fails when: summercms.go files outside `.planning` under `admin/src`, `admin/tests`, `admin/openapi`, `boardwalk`, `cabana`, `phrasebook` match Płytarium, fonoteka or Polish catalogue domain words; `admin/src` contains a raw-HTML directive; any file under `admin/src` other than `api/client.ts` calls the fetch API directly; `admin/src/api` holds anything but `schema.d.ts`, `client.ts` and `types.ts`, or `types.ts` declares an interface or object type literal instead of aliases onto generated schemas; `boardwalk/dist` references another origin; an icon namespace import or the deprecated lucide package appears; a route literal for the retired admin prefix appears in Go code other than MintAudience issuer arguments; a `.ts` or `.vue` file under `admin/src` other than `main.ts`, `env.d.ts` and `api/schema.d.ts` is imported by no test); `--evidence` (review lists T-10-01..T-10-25 and T-10-SC, validation has `nyquist_compliant: true`, no pending row, and names ADMIN-06; then runs --security, --postgres and --openapi); `--all` runs every stage in order.

(2) 10-SECURITY-REVIEW.md: a fresh code-and-test review of every threat in the five plans' registers (T-10-01..T-10-25, T-10-SC): threat, severity, disposition, the production mitigation with file references, the exact test or gate stage, the observed result, residual risk. A high threat is marked mitigated only when the named test fails if the protection is removed (state how that was checked). Accepted and transferred threats keep their rationale verbatim from the originating plan.

(3) 10-VALIDATION.md: replace the seeded rows with the actual plan/task IDs and commands from the executed plans, record per-row status from the final gate, fill Wave 0 items, keep the two manual-only rows (visual fidelity; full browser flow) pointing at the human-check blocks of Plans 10-03 and 10-04, and set nyquist_compliant: true and wave_0_complete: true only after scripts/check-phase10.sh --all passes.

(4) Run scripts/check-phase10.sh --all; commit the script with the code and the two docs in a separate docs commit. scripts/check-phase10.sh --self-test && scripts/check-phase10.sh --all <fails_when>Non-zero exit, or any output line starting with "refuse:"; the final line "phase10 all passed" is absent.</fails_when> <acceptance_criteria> - scripts/check-phase10.sh --all exits 0 and prints "phase10 all passed". - grep -c 'T-10-' .planning/phases/10-admin-vue-spa/10-SECURITY-REVIEW.md is at least 26 and every T-10 ID from the five plans appears. - grep -c 'nyquist_compliant: true' .planning/phases/10-admin-vue-spa/10-VALIDATION.md prints 1 and no table row in it contains "pending". </acceptance_criteria> Phase 10 has one command that proves everything, and auditable threat and validation evidence.

Multi-Source Coverage Audit

Source Item Coverage Plan evidence
GOAL SPA renders login, permission-gated navigation, lists, forms and the relation manager for the five controllers, typed from the generated OpenAPI document COVERED 10-01 tracer (login, nav, typed list); 10-02 contract; 10-03 lists/forms/settings; 10-04 relation manager and shell; 10-05 assembled acceptance
REQ ADMIN-06 COVERED 10-01, 10-02, 10-03, 10-04, 10-05
GOAL SC-1 login and permission-filtered navigation COVERED 10-01 Tasks 2-3; 10-04 Task 2; TestPhase10AssembledAcceptance
GOAL SC-2 five controllers list and form COVERED 10-02 Task 3 TestPhase10Controllers; 10-03 Tasks 1-3
GOAL SC-3 Collections relation manager search/link/unlink COVERED 10-04 Task 1; TestPhase10AssembledAcceptance
GOAL SC-4 generated types, no hand-maintained duplicates COVERED 10-01 Task 2 pipeline; 10-02 Task 3 full typing and conformance; 10-05 hygiene stage
CONTEXT D-01, D-02, D-03, D-04 packaging, prefix, API move, committed dist COVERED 10-01 Tasks 2-3; 10-05 dist stage
CONTEXT D-05 field renderer registry and UnsupportedField COVERED 10-03 Tasks 1 and 3; 10-04 Task 1
CONTEXT D-06, D-07 design fidelity and stack COVERED 10-01 Task 2 tokens/fonts/stack; 10-03; 10-04 Task 2
CONTEXT D-08 real YAML only, mock extras as fixtures COVERED 10-02 Task 3 TestPhase10Controllers; 10-03 fixtures; 10-05 Task 1
CONTEXT D-09 error envelope and 422 mapping COVERED 10-03 Task 1
CONTEXT D-10 routes from controller IDs, rail grouping, server filtering COVERED 10-01 Task 2; 10-04 Task 2
CONTEXT D-11 lucide icons, Winter map, fonoteka icons COVERED 10-01 Tasks 2-3
CONTEXT D-12 format column plain text COVERED 10-03 Task 2
CONTEXT D-13, D-24 messages and placeholder syntax COVERED 10-02 Task 2; 10-03 Task 1
CONTEXT D-14 declarative toolbar COVERED 10-02 Task 2; 10-03 Task 2
CONTEXT D-15, D-16 framework OpenAPI and generic records COVERED 10-01 Task 2; 10-02 Task 3
CONTEXT D-17, D-18 relation options and save COVERED 10-02 Task 1; 10-03 Task 3
CONTEXT D-19 cookie transport and CSRF COVERED 10-01 Tasks 2-3
CONTEXT D-20 backend strings, bundle and overrides COVERED 10-02 Task 2; 10-03 Task 1
CONTEXT D-21 settings screen COVERED 10-03 Task 3
CONTEXT D-22, D-27 filter bar and model-backed filter options COVERED 10-02 Task 3; 10-03 Task 2
CONTEXT D-23 Vitest plus Go tests, no Playwright COVERED 10-05 Tasks 1-2
CONTEXT D-25 Collections navigation item COVERED 10-01 Task 3
CONTEXT D-26 read-only owner COVERED 10-02 Task 1; 10-03 Task 3
CONTEXT D-28 five plans COVERED 10-01 to 10-05
RESEARCH Gaps 1-9 (backend namespace, fonoteka lang, Collections nav, override layer, placeholder syntax, filter choices, page sizes, recordUrl mapping, reserved segments) COVERED 10-02 Task 2; 10-01 Task 3; 10-01 Task 3; 10-02 Task 2; 10-02 Task 2; 10-02 Task 3; 10-03 Task 2; 10-03 Task 1; 10-01 Task 3
RESEARCH Pitfalls 1-13 (embed all:, go.mod ignore, api fallback, toolbar error, delete without checkboxes, scoped ids, requiredByDefault, conformance, font subsets, refresh race, fixture names, dist drift, owner FK) COVERED 10-01, 10-02, 10-05 as cited in each task
RESEARCH Package legitimacy audit COVERED 10-01 Task 1 blocking-human checkpoint
CONTEXT Deferred ideas (10.1 extension point, Ctrl+K, badge column, Playwright, user/media navigation) EXCLUDED No task implements a deferred item

<threat_model>

Trust Boundaries

Boundary Description
Test and gate results → phase acceptance Gate completeness decides whether a vulnerable admin surface can be declared done
Framework repo → app repo boundary summercms.go must stay free of application knowledge

STRIDE Threat Register

Threat ID Category Component Severity Disposition Mitigation Plan
T-10-24 Repudiation Phase 10 acceptance evidence high mitigate check-phase10.sh detects zero-test, skipped and failing go runs, drift, hygiene and evidence gaps; --self-test proves each detector fails closed; the review names a failing-when-broken test per high threat.
T-10-25 Tampering framework/app boundary and hand-maintained API types low mitigate --hygiene stage fails on app names in summercms.go, non-alias API types, direct fetch calls, raw-HTML directives, foreign origins in dist and untested SPA modules.
T-10-SC Tampering npm/Go dependencies high mitigate No new package in this plan (no coverage provider); npm ci against the approved lockfile; swag pinned at v1.16.6.
</threat_model>
`scripts/check-phase10.sh --all` is the phase acceptance command. It fails on any non-zero stage, zero matched tests, a skipped PostgreSQL test, OpenAPI or dist drift, a hygiene violation, or an evidence gap. The manual-only checks (visual fidelity, full browser flow) are the human-check blocks in Plans 10-03 and 10-04, collected at /gsd-verify-work.

<success_criteria>

  • Every SPA module and every Phase 10 Go change has named tests; both repos are green.
  • TestPhase10AssembledAcceptance proves SC-1 to SC-4 against real PostgreSQL.
  • scripts/check-phase10.sh --all passes; the security review and validation map are complete and truthful.
  • The multi-source audit has no missing GOAL, REQ, RESEARCH or CONTEXT item and no deferred item in scope. </success_criteria>
Create `.planning/phases/10-admin-vue-spa/10-05-SUMMARY.md` when done.