8.6 KiB
8.6 KiB
phase, slug, status, nyquist_compliant, wave_0_complete, created
| phase | slug | status | nyquist_compliant | wave_0_complete | created |
|---|---|---|---|---|---|
| 12.1 | user-plugin-admin-screens | draft | false | false | 2026-10-04 |
Phase 12.1 — Validation Strategy
Per-phase validation contract for feedback sampling during execution. Seeded from
12.1-RESEARCH.md§ Validation Architecture. The phase has no requirement IDs; success criteria (SC) and CONTEXT.md decisions (D-NN) are the units.
Test Infrastructure
| Property | Value |
|---|---|
| Framework | Go testing + testcontainers Postgres (cabana and plugin harnesses exist); SPA: vitest + @vue/test-utils + happy-dom |
| Config file | admin/vitest.config.ts; Go needs none |
| Quick run command (framework) | go vet ./modules/cabana/ ./modules/pact/ && go test ./modules/cabana/... ./modules/pact/... -count=1 |
| Quick run command (plugin) | go -C ../fonoteka.go test ./plugins/golem15/user/... -count=1 |
| Quick run command (SPA) | npm --prefix admin run typecheck && npm --prefix admin test |
| Full suite command (framework) | go vet ./... && go test ./... -count=1 |
| Full suite command (application) | go -C ../fonoteka.go vet ./... && go -C ../fonoteka.go test ./... -count=1 |
| Docs | go test ./cmd/summer -run TestDocsTree -count=1 and go run ./cmd/summer docs:build --check |
| Generated artefacts | scripts/check-admin-openapi.sh --check and scripts/check-admin-dist.sh |
| Estimated runtime | not measured; the planner records it once the quick commands have run |
Sampling Rate
- After every task commit: Run the quick run command of the repository the task wrote to; plus
scripts/check-admin-openapi.sh --checkandscripts/check-admin-dist.shwhenadmin/or swag annotations changed - After every plan wave: Run both full suites and the docs checks
- Before
/gsd-verify-work:scripts/check-phase12.1.sh --allmust be green (modelled onscripts/check-phase12.2.sh) - Max feedback latency: not measured; set with the estimated runtime
Per-Task Verification Map
Task IDs are assigned by the planner; rows are keyed by unit until then.
| Task ID | Plan | Wave | Requirement | Threat Ref | Secure Behavior | Test Type | Automated Command | File Exists | Status |
|---|---|---|---|---|---|---|---|---|---|
| TBD | TBD | TBD | D-09 | — | Bulk action ids outside the list scope never reach Run; partial selection refused; undeclared or unregistered action refused; own permission enforced; one transaction, rollback on error |
integration | go test ./modules/cabana/... -run 'TestBulkAction' -count=1 |
❌ W0 | ⬜ pending |
| TBD | TBD | TBD | D-09 | — | A YAML bulk action the controller does not register fails boot | unit | go test ./modules/cabana/... -run 'TestListSchemaBulkActions' -count=1 |
❌ W0 | ⬜ pending |
| TBD | TBD | TBD | D-10 | — | Record action runs in form scope; out-of-scope 404; not-applicable refused; own permission enforced | integration | go test ./modules/cabana/... -run 'TestRecordAction' -count=1 |
❌ W0 | ⬜ pending |
| TBD | TBD | TBD | D-11 | — | context: preview field never writable |
unit + SPA | go test ./modules/cabana/... -run 'TestPreview' -count=1; npm --prefix admin test -- winterUrl FormView |
❌ W0 | ⬜ pending |
| TBD | TBD | TBD | D-12 | — | Row state from the fixed set; unknown value dropped | integration + SPA | go test ./modules/cabana/... -run 'TestRowState' -count=1; npm --prefix admin test -- DataTable |
❌ W0 | ⬜ pending |
| TBD | TBD | TBD | D-16 | — | permissioneditor: unknown code 422, value outside the mode's set 422, stored JSON shape |
integration + SPA | go test ./modules/cabana/... -run 'TestPermissionEditor' -count=1; npm --prefix admin test -- PermissionEditorField |
❌ W0 | ⬜ pending |
| TBD | TBD | TBD | contract | — | New routes in the inventory, permission matrix and OpenAPI document | contract | go test ./modules/cabana/... -run 'TestPhase09ContractInventory|TestPhase09PermissionMatrix|TestPhase10OpenAPIConformance' -count=1 |
✅ (extend) | ⬜ pending |
| TBD | TBD | TBD | SC-1 | — | Three controllers boot; navigation and permissions gate them | integration | go -C ../fonoteka.go test ./plugins/golem15/user/... -run 'TestAdmin(Users|Groups|Organisations)' -count=1 |
❌ W0 | ⬜ pending |
| TBD | TBD | TBD | SC-2 | — | Groups field sync; organisation members set and clear organisation_id |
integration | go -C ../fonoteka.go test ./plugins/golem15/user/... -run 'TestAdminUserGroupsField|TestAdminOrganisationMembers' -count=1 |
❌ W0 | ⬜ pending |
| TBD | TBD | TBD | SC-3 / D-13 / D-14 | — | activate, unban, unsuspend, deactivate, restore, ban, force delete with cleanup | integration | go -C ../fonoteka.go test ./plugins/golem15/user/... -run 'TestAdminUserActions|TestAdminUserForceDelete' -count=1 |
❌ W0 | ⬜ pending |
| TBD | TBD | TBD | SC-4 | T-12-18 | Without the extra permission a privileged membership change is 403 and nothing changes; privileged code create, rename and delete refused; every other path leaves users_groups unchanged |
integration | go -C ../fonoteka.go test ./plugins/golem15/user/... -run 'TestAdminPrivilegedGroups' -count=1 |
❌ W0 | ⬜ pending |
| TBD | TBD | TBD | D-30 | T-12.1-38, T-12.1-39 | Without the extra permission, changing the email or password of a privileged-group member, or permanently deleting them (form delete, bulk delete as a whole), is 403 and nothing changes; with it each succeeds; a name-only update stays allowed | integration | go -C ../fonoteka.go test ./plugins/golem15/user/... -run 'TestAdminPrivilegedMember' -count=1 |
❌ W0 | ⬜ pending |
| TBD | TBD | TBD | D-15 | — | Resolver equals PHP getMergedPermissions on a table of cases |
unit | go -C ../fonoteka.go test ./plugins/golem15/user/... -run 'TestMergedPermissions|TestPermissionSetScan' -count=1 |
❌ W0 | ⬜ pending |
| TBD | TBD | TBD | D-17 | — | last_seen written by the auth path; absent from every user payload |
integration | go -C ../fonoteka.go test ./plugins/golem15/user/... -run 'TestLastSeen' -count=1 |
❌ W0 | ⬜ pending |
| TBD | TBD | TBD | D-19 | — | Password mismatch 422; send_invite sends one mail; password never in a response |
integration | go -C ../fonoteka.go test ./plugins/golem15/user/... -run 'TestAdminUserPassword|TestAdminUserInvite' -count=1 |
❌ W0 | ⬜ pending |
| TBD | TBD | TBD | D-20 | — | Avatar shared between the admin file route and the user API | integration | go -C ../fonoteka.go test ./plugins/golem15/user/... -run 'TestAdminAvatarSharedWithAPI' -count=1 |
❌ W0 | ⬜ pending |
| TBD | TBD | TBD | D-08 | T-12-18 | A user with groups marshals without groups | regression | existing TestPhase12Threats/T-12-18 in the application |
✅ | ⬜ pending |
| TBD | TBD | TBD | schema | — | Go schema matches the PHP snapshot with one new allow-list entry | integration | go -C ../fonoteka.go test ./parity -run TestSchemaMatchesPHPSnapshot -count=1 |
✅ (extend) | ⬜ pending |
| TBD | TBD | TBD | migrations | — | Three additive migrations up and down | integration | go -C ../fonoteka.go test ./plugins/golem15/user/updates/... -count=1 |
✅ harness, ❌ cases | ⬜ pending |
| TBD | TBD | TBD | docs | — | Identifiers, links, snippets | checker | go test ./cmd/summer -run TestDocsTree -count=1 |
✅ | ⬜ pending |
Status: ⬜ pending · ✅ green · ❌ red · ⚠️ flaky
Wave 0 Requirements
- A neutral cabana fixture plugin (
modules/cabana/testdata/...,acme) with bulk actions, record actions, a preview field, row state and a permission editor sm-user-pluginadmin test harness: boot the plugin with cabana mounted and mint a backend principal with chosen permissions- SPA fixtures under
admin/tests/fixtures/for the new schema fields scripts/check-phase12.1.sh
Framework install: none needed.
Manual-Only Verifications
None identified by research. The UI-SPEC (/gsd-ui-phase 12.1) may add visual checks for the preview screen, row state styling and the permission editor.
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 recorded and within the stated maximum
nyquist_compliant: trueset in frontmatter
Approval: pending