Files
summercms/.planning/phases/10.1-runtime-admin-extension-point/10.1-VALIDATION.md
Jakub Zych bbceeb957f docs(10.1-04): record the Phase 10.1 security review and validation map
- 10.1-SECURITY-REVIEW.md: T-10.1-01 to T-10.1-22 and T-10.1-SC with
  mitigation, test or gate stage, observed result and 23 removal checks
- 10.1-VALIDATION.md: every plan task mapped to its command, all green
  under check-phase10.1.sh --all; nyquist_compliant and wave 0 complete
- Phase 10 deferred item for the parity failures marked resolved
2026-09-29 03:13:18 +02:00

12 KiB

phase, slug, status, nyquist_compliant, wave_0_complete, created, validated
phase slug status nyquist_compliant wave_0_complete created validated
10.1 runtime-admin-extension-point validated true true 2026-09-28 2026-09-29

Phase 10.1 — Validation Strategy

Per-phase validation contract for feedback sampling during execution. Seeded from 10.1-RESEARCH.md § Validation Architecture; task IDs and statuses are filled in from the executed plans 10.1-01 to 10.1-04 and the final run of scripts/check-phase10.1.sh --all. Requirement: ADMIN-07.


Test Infrastructure

Property Value
Framework Go testing (+ testcontainers Postgres); Vitest 3.2.7 + happy-dom 20.11.6 + @vue/test-utils 2.4.11
Config file admin/vitest.config.ts; go.mod / go.work
Quick run command go test ./modules/cabana -run 'TestPhase101' -count=1 and npm --prefix admin test -- tests/form tests/list tests/app
Full suite command go vet ./... && go test ./... in both repos, npm --prefix admin run typecheck && npm --prefix admin test
Phase gate scripts/check-phase10.1.sh --all plus scripts/check-phase10.sh --all staying green
Estimated runtime ~120 seconds with warm caches for the test commands; the full gate (npm ci, both repositories, every Postgres suite) takes several minutes

Sampling Rate

  • After every task commit: the quick run command for the touched side (cabana -run TestPhase101 or the touched vitest files), plus go vet ./...
  • After every plan wave: full suite in both repos, scripts/check-admin-openapi.sh --check, and scripts/check-admin-dist.sh after SPA changes
  • Before /gsd-verify-work: scripts/check-phase10.1.sh --all and scripts/check-phase10.sh --all green
  • Max feedback latency: 120 seconds

Per-Task Verification Map

Task IDs are {plan}-T{n}. A row lists the task that built the behaviour and the 10.1-04 task that brought its full tests. Every row's command passed in the final gate run.

Task ID Plan Wave Requirement Threat Ref Secure Behavior Test Type Automated Command File Exists Status
10.1-01-T1, 10.1-04-T1 10.1-01, 10.1-04 1, 4 ADMIN-07 (D-06, D-09) T-10.1-11 widget/partial types; per-type keys; tag prefix {vendor}-{plugin}-; reserved names; unknown key and settings-form use fail boot unit go test ./modules/cabana -run '^TestPhase101FormExtensionSchema$' -count=1 ✅ ✅ green
10.1-01-T1, 10.1-04-T1 10.1-01, 10.1-04 1, 4 ADMIN-07 (D-07) T-10.1-05, T-10.1-06, T-10.1-07 fill ⊆ writable fields; server drops extra keys; action permission + scoped record load unit + Postgres go test ./modules/cabana -run '^TestPhase101Actions$' -count=1 ✅ ✅ green
10.1-01-T3, 10.1-04-T1 10.1-01, 10.1-04 1, 4 ADMIN-07 (D-11) — headerPartial compiles; missing template / parse error / missing view model / Winter path fails boot unit go test ./modules/cabana -run '^TestPhase101PartialSchema$' -count=1 ✅ ✅ green
10.1-01-T3, 10.1-04-T1 10.1-01, 10.1-04 1, 4 ADMIN-07 (D-10, D-17) T-10.1-08, T-10.1-09, T-10.1-12 allowlisted node tree; script/on*/style/javascript: dropped; record data escaped; size, node and depth caps; model view model refused unit go test ./modules/cabana -run '^TestPhase101PartialSanitizer$' -count=1 ✅ ✅ green
10.1-01-T2, 10.1-04-T1 10.1-01, 10.1-04 1, 4 ADMIN-07 (D-12) T-10.1-05 toolbar names resolved against registered actions; unknown fails boot; permission-filtered and localized per request unit go test ./modules/cabana -run '^TestPhase101Toolbar$' -count=1 ✅ ✅ green
10.1-01-T2, 10.1-04-T1 10.1-01, 10.1-04 1, 4 ADMIN-07 (D-13, D-16) T-10.1-01, T-10.1-02, T-10.1-03 exact asset allowlist; MIME + nosniff + CORP; ETag/304; traversal/undeclared → SPA fall-through unit go test ./modules/cabana -run '^TestPhase101Assets$' -count=1 ✅ ✅ green
10.1-01-T2, 10.1-04-T1 10.1-01, 10.1-04 1, 4 ADMIN-07 (D-16) T-10.1-02 exported ContentType and SetSecurityHeaders unit go test ./modules/boardwalk -run '^TestPhase101BoardwalkExports$' -count=1 ✅ ✅ green
10.1-01-T1, 10.1-01-T2 10.1-01 1 ADMIN-07 (D-05) T-10.1-04 new POSTs refused without X-Requested-With unit go test ./modules/cabana -run '^TestPhase10CSRF$' -count=1 ✅ ✅ green
10.1-01-T1, 10.1-01-T2, 10.1-01-T3 10.1-01 1 ADMIN-07 (D-05, D-12) T-10.1-04 route inventory, permission matrix and OpenAPI conformance cover the new routes unit + Postgres go test ./modules/cabana -run '^(TestPhase09PermissionMatrix|TestPhase09ContractInventory|TestPhase10OpenAPIConformance)$' -count=1 && scripts/check-admin-openapi.sh --check ✅ ✅ green
10.1-02-T1, 10.1-02-T3, 10.1-04-T2 10.1-02, 10.1-04 2, 4 ADMIN-07 (D-14) T-10.1-13, T-10.1-16 loader idempotent; foreign and dot-segment URLs refused (encoded too); CSS disabled off-controller vitest npm --prefix admin test -- tests/app/pluginAssets.test.ts ✅ ✅ green
10.1-02-T1, 10.1-04-T2 10.1-02, 10.1-04 2, 4 ADMIN-07 (D-05, D-07, D-08) T-10.1-17, T-10.1-18 widget attributes only; event → POST once while busy; patch only fill keys; 5000 ms timeout; create mode vitest npm --prefix admin test -- tests/form/WidgetField.test.ts ✅ ✅ green
10.1-02-T2, 10.1-04-T2 10.1-02, 10.1-04 2, 4 ADMIN-07 (D-09, D-17) T-10.1-14 PartialHost renders via h(); unknown tag/attr dropped; text stays text; skeleton, empty, failure and busy-refetch states vitest npm --prefix admin test -- tests/list/PartialHost.test.ts tests/form/PartialField.test.ts ✅ ✅ green
10.1-02-T3, 10.1-04-T2 10.1-02, 10.1-04 2, 4 ADMIN-07 (D-03, D-12) — list header slot; custom toolbar button → POST {} → toast → reload; header refetch only after bulk delete and actions vitest npm --prefix admin test -- tests/list/ListToolbar.test.ts tests/list/ListView.test.ts ✅ ✅ green
10.1-02-T1, 10.1-02-T2, 10.1-04-T2 10.1-02, 10.1-04 2, 4 ADMIN-07 (D-09) — widget/partial registered, excluded from save body, span labels, render on create, form context provided vitest npm --prefix admin test -- tests/form/registry.test.ts tests/form/formState.test.ts tests/form/FormField.test.ts tests/form/FormView.test.ts ✅ ✅ green
10.1-02-T1, 10.1-02-T2, 10.1-02-T3 10.1-02 2 ADMIN-07 (D-04, D-05, D-17) T-10.1-14, T-10.1-18 end-to-end SPA smoke of widget, partials, toolbar actions and scoped stylesheets; framework strings resolve vitest + unit npm --prefix admin test -- tests/smoke && go test ./modules/phrasebook -run '^TestPhase10SPAKeysResolve$' -count=1 ✅ ✅ green
10.1-04-T3 10.1-04 4 ADMIN-07 (D-17) T-10.1-08, T-10.1-10, T-10.1-14, T-10.1-19, T-10.1-20 no raw-HTML sinks or HTML-string parsers; plugin assets contain no network, cookie or storage access; partial templates carry no script or handlers; detectors fail closed gate scripts/check-phase10.1.sh --self-test && scripts/check-phase10.1.sh --hygiene ✅ ✅ green
10.1-02-T1, 10.1-02-T2, 10.1-02-T3, 10.1-04-T2 10.1-02, 10.1-04 2, 4 ADMIN-07 (D-04) T-10.1-SC committed dist matches source gate scripts/check-admin-dist.sh ✅ ✅ green
10.1-03-T1 10.1-03 3 ADMIN-07 (D-01, D-03) T-10.1-15 Albums stats strip scoped per collection; copy in pl and en integration (Postgres) cd ../fonoteka.go && go test ./plugins/golem15/fonoteka -run '^(TestPhase101AlbumsSmoke|TestPhase10LangCatalog|TestAlbumsAdminList|TestAlbumsAdminRegistration|TestPhase10ControllerCopy)$' -count=1 ✅ ✅ green
10.1-03-T2 10.1-03 3 ADMIN-07 (D-02, D-06, D-07) T-10.1-21, T-10.1-22 Discogs widget stub fills year and format; a save persists them (json.Number fill) integration (Postgres) + unit cd ../fonoteka.go && go test ./plugins/golem15/fonoteka -run '^(TestPhase101AlbumsSmoke|TestAlbumsAdminForm|TestAlbumsAdminCRUD|TestPhase10Controllers|TestPhase10AlbumRelations|TestPhase10AssembledAcceptance)$' -count=1 && go test ./modules/lagoon -run '^TestFillJSONNumber$' -count=1 ✅ ✅ green
10.1-03-T3 10.1-03 3 ADMIN-07 (D-12) T-10.1-21 Sync with Discogs toolbar stub toasts; limited admin 403 integration (Postgres) cd ../fonoteka.go && go test ./plugins/golem15/fonoteka/... -count=1 ✅ ✅ green
10.1-03-T1, 10.1-03-T2, 10.1-03-T3, 10.1-04-T1 10.1-03, 10.1-04 3, 4 ADMIN-07 (D-01, D-02, D-03, D-12) T-10.1-05, T-10.1-06, T-10.1-09, T-10.1-15, T-10.1-21 Albums stats strip over two collections; widget stub fills and saves; toolbar action toasts; Genres-only admin 403; assets served; labels resolve in pl and en; every route template in admin.json integration (Postgres) cd ../fonoteka.go && go test ./plugins/golem15/fonoteka -run '^(TestPhase101AlbumsExtension|TestPhase101AlbumsSmoke)$' -count=1 ✅ ✅ green
10.1-03-T3, 10.1-04-T1 10.1-03, 10.1-04 3, 4 ADMIN-07 (D-01) T-10.1-20 framework repo has no application names gate scripts/check-phase10.sh --hygiene ✅ ✅ green
10.1-04-T3 10.1-04 4 ADMIN-07 T-10.1-19, T-10.1-SC the whole phase: go, security, postgres, spa, openapi, dist, hygiene and evidence stages; Phase 10 gate still green gate scripts/check-phase10.1.sh --all && scripts/check-phase10.sh --all ✅ ✅ green

Status: ⬜ pending · ✅ green · ❌ red · ⚠️ flaky


Wave 0 Requirements

  • modules/cabana/testdata/extension/ — acme fixture plugin tree (config YAML, _stats.htm, _summary.htm, fields/columns, assets/js/lookup.js, assets/css/gadgets.css, en/pl lang)
  • modules/cabana/phase101_*_test.go — schema, sanitizer, assets, actions, toolbar
  • admin/tests/fixtures/extension.*.json — list/form schema with assets, widget, partial, toolbar actions; partial nodes (from 10.1-02, reused)
  • admin/tests/app/pluginAssets.test.ts, tests/form/WidgetField.test.ts, tests/form/PartialField.test.ts, tests/list/PartialHost.test.ts
  • ../fonoteka.go/plugins/golem15/fonoteka/admin_phase101_albums_test.go
  • scripts/check-phase10.1.sh with --self-test, --go, --security, --postgres, --spa, --openapi, --dist, --hygiene, --evidence, --all

No framework install needed.


Manual-Only Verifications

Behavior Requirement Why Manual Test Instructions
Browser loads plugin module script under CSP script-src 'self'; widget renders; fill then save persists; strip and buttons wrap at 768px with pl labels; plugin CSS off on other controllers; Vite /assets dev proxy ADMIN-07 (D-13, D-16, D-07) happy-dom does not enforce CSP, load module scripts or lay out The human-check blocks of 10.1-02 Task 3 and 10.1-03 Task 3, collected at /gsd-verify-work: summer serve for fonoteka, open /plytadmin Albums in a browser, check the console for CSP errors, click the Discogs widget, save, reload

Validation Sign-Off

  • All tasks have <automated> verify or Wave 0 dependencies
  • Sampling continuity: no 3 consecutive tasks without automated verify
  • Wave 0 covers all MISSING references
  • No watch-mode flags
  • Feedback latency < 120s for the per-task commands
  • nyquist_compliant: true set in frontmatter

Approval: validated 2026-09-29 by scripts/check-phase10.1.sh --all