Files
summercms/.planning/phases/10-admin-vue-spa/10-VALIDATION.md
Jakub Zych 074fc52e5e docs(10-05): Phase 10 security review and final validation map
- 10-SECURITY-REVIEW.md: T-10-01..T-10-25 and T-10-SC with mitigation,
  test or gate stage, observed result, residual risk and the removal
  (mutation) checks behind every high threat
- 10-VALIDATION.md: executed task commands, gate statuses, Wave 0 done,
  nyquist_compliant after scripts/check-phase10.sh --all passed
2026-09-27 18:22:01 +02:00

96 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
phase: "10"
slug: "admin-vue-spa"
# status lifecycle: draft (seeded by plan-phase) → validated (set by validate-phase §6)
# audit-milestone §5.5 distinguishes NOT-VALIDATED (draft) from PARTIAL (validated + nyquist_compliant: false) (#2117)
status: validated
nyquist_compliant: true
wave_0_complete: true
created: "2026-09-27"
validated: "2026-09-27"
gate: "scripts/check-phase10.sh --all"
---
# Phase 10 — Validation Strategy
> Per-phase validation contract for feedback sampling during execution. Plan 10-05 Task 3 finalized it from the executed plans. The statuses record the final `scripts/check-phase10.sh --all` run.
---
## Test Infrastructure
| Property | Value |
|----------|-------|
| **Framework** | Go 1.27 `testing` + testify (Testcontainers Postgres harness); Vitest 3.2.7 + @vue/test-utils 2.4.11 + happy-dom 20.11.6 for the SPA |
| **Config file** | none for Go; `admin/vitest.config.ts` (happy-dom, `restoreMocks: true`, `tests/setup.ts`) |
| **Quick run command** | `go test ./cabana ./bouncer ./phrasebook ./boardwalk -count=1` / `npm --prefix admin test` |
| **Full suite command** | `scripts/check-phase10.sh --all` (go vet and go test in both repos including the fonoteka plugin modules, security, PostgreSQL, SPA, OpenAPI, dist, hygiene and evidence stages) |
| **Estimated runtime** | about 5 minutes for `--all` (Postgres-backed suites and the SPA build dominate); `npm --prefix admin test` about 20 s |
---
## Sampling Rate
- **After every task commit:** narrowest Go package test + `go vet ./...` in the touched repo; for SPA tasks `npx vitest run <dir>` + `npm run typecheck`
- **After every plan wave:** full suite in both repos + `npm --prefix admin run build` + `scripts/check-admin-dist.sh` + `scripts/check-admin-openapi.sh --check`
- **Before `/gsd-verify-work`:** `scripts/check-phase10.sh --all` must be green
- **Max feedback latency:** 180 seconds per stage
---
## Per-Task Verification Map
cwd = summercms.go. The app repo is reached via `(cd ../fonoteka.go && ...)`. The Status column is the result of the final gate run of Plan 10-05, which re-runs each row's tests through its stage.
| Task ID | Plan | Wave | Requirement / Decisions | Threat Ref | Test Type | Automated Command | File Exists | Status |
|---------|------|------|-------------------------|------------|-----------|-------------------|-------------|--------|
| 10-01-T1 | 01 | 1 | ADMIN-06 (package gate) | T-10-SC | human (blocking-human) | n/a: the user approved the 17 exact npm pins before install; later installs are `npm ci` (stage `--spa`) | ✅ package-lock.json | ✅ green (approved; `--spa` npm ci passes) |
| 10-01-T2 | 01 | 1 | ADMIN-06 SC1, SC4; D-01 D-02 D-03 D-06 D-07 D-10 D-11 D-15 D-16 D-19 | T-10-01 T-10-02 T-10-03 T-10-04 T-10-17 | assembled Postgres + unit + smoke + script | `(cd ../fonoteka.go && go test ./plugins/golem15/fonoteka -run '^TestPhase10TracerSPA$' -count=1 -v) && go vet ./... && go test ./cabana ./bouncer ./boardwalk -count=1 && npm --prefix admin run typecheck && npm --prefix admin test -- tests/smoke && scripts/check-admin-openapi.sh --check` | ✅ | ✅ green (`--postgres`, `--go`, `--spa`, `--openapi`) |
| 10-01-T3 | 01 | 1 | ADMIN-06 SC1; D-04 D-11 D-19 D-25 | T-10-05 T-10-06 T-10-07 T-10-08 | unit + assembled + script | `go test ./cabana -run '^TestPhase10(CookieAuth\|CSRF\|Prefix)$' -count=1 -v && go test ./surf -run '^TestPhase10AdminPrefixCollision$' -count=1 -v && go test ./boardwalk -count=1 -v && (cd ../fonoteka.go && go test ./plugins/golem15/fonoteka -run '^(TestPhase10AdminAuth\|TestPhase10LangCatalog\|TestAdminMetadataNavigation)$' -count=1 -v) && npm --prefix admin test -- tests/smoke && scripts/check-admin-dist.sh && scripts/check-phase9.sh --security` | ✅ | ✅ green (`--security`, `--go`, `--spa`, `--dist`) |
| 10-02-T1 | 02 | 2 | ADMIN-06 SC2; D-17 D-18 D-26 | T-10-09 T-10-10 T-10-11 | unit + assembled Postgres | `go test ./cabana -run '^TestPhase10Relation(Options\|Save\|ForgedID\|Boot)$\|^TestPhase09(PermissionMatrix\|ContractInventory)$' -count=1 -v && (cd ../fonoteka.go && go test ./plugins/golem15/fonoteka -run '^(TestPhase10AlbumRelations\|TestPhase10CollectionOwnerReadOnly\|TestAlbumsAdmin.*\|TestCollectionsAdmin.*)$' -count=1) && scripts/check-admin-openapi.sh --check` | ✅ | ✅ green (`--security`, `--postgres`, `--go`, `--openapi`) |
| 10-02-T2 | 02 | 2 | ADMIN-06 SC2; D-13 D-14 D-20 D-24 | T-10-12 T-10-13 | unit + assembled | `go test ./phrasebook ./cabana -run '^TestPhase10(Forms\|LangOverride\|SPAKeysResolve\|Bundle\|Messages\|Toolbar)$\|^TestPhase09(PermissionMatrix\|ContractInventory)$' -count=1 -v && go test ./internal/build -run '^Test.*AdminController' -count=1 && (cd ../fonoteka.go && go test ./plugins/golem15/fonoteka -run '^(TestPhase10ControllerCopy\|TestPhase10LangCatalog)$' -count=1 -v) && scripts/check-admin-openapi.sh --check` | ✅ | ✅ green (`--security`, `--go`, `--openapi`) |
| 10-02-T3 | 02 | 2 | ADMIN-06 SC2, SC4; D-08 D-15 D-16 D-27 | T-10-14 T-10-15 | unit + assembled + script | `go test ./cabana -run '^TestPhase10(FilterOptions\|OpenAPIConformance)$\|^TestPhase09(PermissionMatrix\|ContractInventory)$' -count=1 -v && scripts/check-admin-openapi.sh --check && npm --prefix admin run typecheck && scripts/check-admin-dist.sh && (cd ../fonoteka.go && go test ./plugins/golem15/fonoteka -run '^TestPhase10Controllers$' -count=1 -v) && go vet ./... && go test ./... && (cd ../fonoteka.go && go vet ./... && go test ./...)` | ✅ | ✅ green (`--go` accepts only the two deferred parity failures; `--openapi`, `--dist`, `--postgres`) |
| 10-03-T1 | 03 | 3 | ADMIN-06 SC2; D-05 D-09 D-10 D-18 D-20 D-24 | T-10-16 T-10-20 | smoke + unit + script | `npm --prefix admin run typecheck && npm --prefix admin test -- tests/smoke/edit.smoke.test.ts && go test ./phrasebook -run '^TestPhase10SPAKeysResolve$' -count=1 -v && scripts/check-admin-dist.sh` | ✅ | ✅ green (`--spa`, `--go`, `--dist`) |
| 10-03-T2 | 03 | 3 | ADMIN-06 SC2; D-12 D-13 D-14 D-22 D-27 | T-10-16 T-10-19 | smoke + unit + script | `npm --prefix admin run typecheck && npm --prefix admin test -- tests/smoke/list.smoke.test.ts && go test ./phrasebook -run '^TestPhase10SPAKeysResolve$' -count=1 -v && scripts/check-admin-dist.sh` | ✅ | ✅ green (`--spa`, `--go`, `--dist`) |
| 10-03-T3 | 03 | 3 | ADMIN-06 SC2; D-05 D-17 D-18 D-21 D-26 | T-10-18 | smoke + unit + script + assembled | `npm --prefix admin run typecheck && npm --prefix admin test -- tests/smoke && go test ./phrasebook -run '^TestPhase10SPAKeysResolve$' -count=1 -v && scripts/check-admin-dist.sh && (cd ../fonoteka.go && go test ./plugins/golem15/fonoteka -run '^TestPhase10Controllers$' -count=1 -v)`; browser part in the manual-only table | ✅ | ✅ green (`--spa`, `--dist`, `--postgres`); manual part: see Manual-Only |
| 10-04-T1 | 04 | 4 | ADMIN-06 SC3; D-05 D-06 | T-10-21 | smoke + assembled + script | `npm --prefix admin run typecheck && npm --prefix admin test -- tests/smoke/relation.smoke.test.ts && go test ./phrasebook -run '^TestPhase10SPAKeysResolve$' -count=1 -v && scripts/check-admin-dist.sh && (cd ../fonoteka.go && go test ./plugins/golem15/fonoteka -run '^TestCollectionsAdmin(RelationSchema\|Link\|Unlink\|CrossScope\|RelationEdges)$' -count=1 -v)`; browser part in the manual-only table | ✅ | ✅ green (`--spa`, `--dist`, `--go`); manual part: see Manual-Only |
| 10-04-T2 | 04 | 4 | ADMIN-06 SC1; D-06 D-10 | T-10-22 T-10-23 | smoke + script | `npm --prefix admin run typecheck && npm --prefix admin test -- tests/smoke && go test ./phrasebook -run '^TestPhase10SPAKeysResolve$' -count=1 -v && scripts/check-admin-dist.sh`; browser part in the manual-only table | ✅ | ✅ green (`--spa`, `--dist`, `--hygiene`); manual part: see Manual-Only |
| 10-05-T1 | 05 | 5 | ADMIN-06 SC1-SC4; D-08 D-23 | T-10-25 | component + unit | `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` | ✅ 48 suites, 441 tests | ✅ green (`--spa`, `--hygiene` module-import rule) |
| 10-05-T2 | 05 | 5 | ADMIN-06 SC1-SC4; D-23 | T-10-24 | unit + assembled Postgres | `go vet ./... && go test ./boardwalk ./bouncer ./cabana ./phrasebook ./surf ./internal/tools/swagger2openapi -count=1 && (cd ../fonoteka.go && go vet ./... && go test ./plugins/golem15/fonoteka -run '^TestPhase10AssembledAcceptance$' -count=1 -v && go test ./... -count=1)` | ✅ | ✅ green (`--go`, `--security`, `--postgres`; fonoteka `go test ./...` fails only the two deferred parity tests, which the gate names) |
| 10-05-T3 | 05 | 5 | ADMIN-06 (phase gate) | T-10-24 T-10-25 | gate script | `scripts/check-phase10.sh --self-test && scripts/check-phase10.sh --all` | ✅ | ✅ green ("phase10 all passed") |
*Status: ⬜ pending · ✅ green · ❌ red · ⚠️ flaky*
---
## Wave 0 Requirements
- [x] `admin/package.json` scripts: `dev`, `build`, `typecheck`, `test`, `gen:api` — Plan 10-01 Task 2
- [x] `admin/vitest.config.ts` + `admin/tests/setup.ts` (fetch mock for openapi-fetch, desktop light matchMedia) — Plan 10-01 Task 2, extended in 10-04 and 10-05 Task 1 (`restoreMocks: true`)
- [x] `admin/tests/fixtures/` — neutral schema fixtures (tabs, all field types, unsupported `colorpicker`, three filter shapes, relation manager) plus `typed.ts`, which types every fixture as its generated OpenAPI schema — Plans 10-01, 10-03, 10-04, 10-05
- [x] `boardwalk/boardwalk_test.go` — Plan 10-01 Task 3, extended in 10-05 Task 2
- [x] `scripts/check-admin-openapi.sh` (10-01 Task 2), `scripts/check-admin-dist.sh` (10-01 Task 3), `scripts/check-phase10.sh` (10-05 Task 3)
- [x] Go test helper `adminAPI(rel)` for prefix-relative admin API paths in the cabana and fonoteka admin tests — Plan 10-01 Task 2
---
## Manual-Only Verifications
| Behavior | Requirement | Why Manual | Test Instructions |
|----------|-------------|------------|-------------------|
| Visual fidelity to Direction C v2 (tokens, dark mode, collapse below ~1100px) | ADMIN-06 (D-06) | No browser e2e in Phase 10 (D-23) | Human-check in 10-04 Task 2: run `summer serve` for fonoteka, open `{backend.uri}`, compare screens against `design/Direction C v2.dc.html` in light and dark mode at desktop and tablet widths. Collected at `/gsd-verify-work` |
| Full login → navigate → edit → relation link flow in a real browser | ADMIN-06 SC1–SC3 | Playwright deferred | Human-checks in 10-03 Task 3 (five controllers) and 10-04 Tasks 1-2 (editors link/unlink; limited admin vs superuser rail). Collected at `/gsd-verify-work` |
---
## Validation Sign-Off
- [x] All tasks have `<automated>` verify or Wave 0 dependencies
- [x] Sampling continuity: no 3 consecutive tasks without automated verify
- [x] Wave 0 covers all MISSING references
- [x] No watch-mode flags (`vitest run`, `go test -count=1`)
- [x] Feedback latency < 180s per stage
- [x] Nyquist compliance set in frontmatter after `scripts/check-phase10.sh --all` passed
**Approval:** approved by the Plan 10-05 gate run (2026-09-27); manual-only rows await `/gsd-verify-work`