docs(16.3): complete validation map with nyquist_compliant

Fill every 16.3-VALIDATION.md row from plan 04 results, tick Wave 0,
and set nyquist_compliant true after the phase gate passed.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-10-11 13:40:53 +02:00
parent 9b811f6042
commit 463541549f

View File

@@ -3,9 +3,9 @@ phase: "16.3"
slug: "backend-admin-personal-api-tokens-with-scopes"
# 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: draft
nyquist_compliant: false
wave_0_complete: false
status: validated
nyquist_compliant: true
wave_0_complete: true
created: "2026-10-11"
---
@@ -22,8 +22,8 @@ created: "2026-10-11"
| **Framework** | Go `testing` (+ testcontainers-go Postgres for DB suites); vitest + @vue/test-utils + happy-dom for the admin SPA |
| **Config file** | `admin/vitest.config.ts` |
| **Quick run command** | `go test ./modules/cabana ./modules/bouncer ./modules/pact -run 'Token|Scope|Allows' -count=1` |
| **Full suite command** | `go vet ./... && go test ./... && npm --prefix admin test && (cd ../sm-journal-plugin && go vet ./... && go test ./...)` |
| **Estimated runtime** | ~180 seconds (Postgres suites need a Docker host) |
| **Full suite command** | `bash scripts/check-phase16.3.sh --all` |
| **Estimated runtime** | ~145 seconds on a Docker host (gate --all including postgres) |
---
@@ -38,24 +38,24 @@ created: "2026-10-11"
## Per-Task Verification Map
Filled in by the planner from the RESEARCH.md test map and the four PLAN.md files. "Docker" commands need a reachable Docker daemon (testcontainers Postgres); without one they are recorded NOT RUN, never skipped. Plan 04 replaces each status with the real result.
Filled by plan 04 with real results. Docker commands ran on this host (Docker daemon available).
| Task ID | Plan | Wave | Requirement | Threat Ref | Secure Behavior | Test Type | Automated Command | File Exists | Status |
|---------|------|------|-------------|------------|-----------------|-----------|-------------------|-------------|--------|
| 16.3-01-T1 | 01 | 1 | SC-1, SC-2 | T-16.3-01, T-16.3-02, T-16.3-04, T-16.3-07, T-16.3-11 | g15_ token runs as its owner; scope evaluated before the superuser shortcut; method refusal 403 token_scope; malformed tokens refused before the database | unit + Docker | `go test -count=1 -run '^(TestTokenTracerSmoke\|TestPhase09PermissionMatrix\|TestPhase09ContractInventory\|TestPhase10ConformanceInventory)$' ./modules/cabana`; Docker: `go test -count=1 -run '^TestTokenTracerPostgres$' ./modules/cabana` and `go test -count=1 -run '^(TestBackendAdminMetadataColumn\|TestPhase09MigrationsFreshRollback)$' ./modules/lagoon` | ❌ W0 | ⬜ pending |
| 16.3-01-T2 | 01 | 1 | SC-2 | T-16.3-05, T-16.3-06, T-16.3-09, T-16.3-13 | interactive-only routes refuse every token; /field-types and /markdown/preview gated; ResolveBackend Bearer-only with cover; stamp debounced and non-fatal | unit + Docker | `go test -count=1 -run '^(TestTokenTracerSmoke\|TestTokenGatesSmoke\|TestPhase09PermissionMatrix\|TestPhase09ContractInventory\|TestPhase10ConformanceInventory\|TestPhase10CSRF)$' ./modules/cabana`; Docker: `go test -count=1 -run '^(TestTokenTracerPostgres\|TestAdminAuthLifecycle\|TestAdminLogoutRevokesExpiredRefreshableToken)$' ./modules/cabana` | ❌ W0 | ⬜ pending |
| 16.3-01-T3 | 01 | 1 | SC-3 | T-16.3-03, T-16.3-08 | plaintext only in the 201 create body; own-only soft revoke; 422 on unknown, empty or non-overlapping scopes | unit + script + Docker | `go test -count=1 -run '^(TestPhase09PermissionMatrix\|TestPhase09ContractInventory\|TestPhase10ConformanceInventory\|TestTokenTracerSmoke\|TestTokenGatesSmoke)$' ./modules/cabana && bash scripts/check-admin-openapi.sh --check && npm --prefix admin run typecheck`; Docker: `go test -count=1 -run '^(TestAccountTokensSmoke\|TestPhase10OpenAPIConformance)$' ./modules/cabana` | ❌ W0 | ⬜ pending |
| 16.3-01-T4 | 01 | 1 | SC-3, SC-5 | T-16.3-03, T-16.3-08 | admin:token:create prints only the token; CLI applies the overlap rule; docs name no consuming application | unit + Docker | `go vet ./... && go test -count=1 ./modules/party ./modules/pact && go test -count=1 -run '^(TestDocsTree\|TestDelegateCommandsHelp\|TestDocsCommandsMirrorGeneratedMain)$' ./cmd/summer && go run ./cmd/summer docs:build --check && go test -short -count=1 -run '^(TestPluginActivates\|TestRoutesRegistered)$' ./docs/examples/blog`; Docker: `go test -count=1 -run '^(TestTokenCommandsSmoke\|TestAdminCreateCommand)$' ./modules/cabana` | ❌ W0 | ⬜ pending |
| 16.3-02-T1 | 02 | 2 | SC-3 | T-16.3-14, T-16.3-16 | plaintext shown once and cleared on Done; no storage, console or v-html in the account components | vitest + script | `npm --prefix admin run typecheck && npm --prefix admin test -- tests/account/ApiTokensPanel.test.ts tests/views/AccountView.test.ts && bash scripts/check-admin-openapi.sh --check && bash scripts/check-admin-dist.sh` | ❌ W0 | ⬜ pending |
| 16.3-02-T2 | 02 | 2 | SC-3 | T-16.3-16 | revoke through the shared confirm; names rendered as text | vitest + script | `npm --prefix admin run typecheck && npm --prefix admin test -- tests/account/ApiTokensPanel.test.ts tests/views/AccountView.test.ts tests/ui/ui.test.ts && bash scripts/check-admin-dist.sh` | ❌ W0 | ⬜ pending |
| 16.3-02-T3 | 02 | 2 | SC-3, SC-5 | T-16.3-14, T-16.3-15, T-16.3-17 | `*` sends only ["*"]; close-without-copy guard; clipboard fallback; server-filtered scopes only | vitest + docs | `npm --prefix admin run typecheck && npm --prefix admin test && bash scripts/check-admin-dist.sh && go test -count=1 ./cmd/summer -run TestDocsTree` | ❌ W0 | ⬜ pending |
| 16.3-03-T1 | 03 | 3 | SC-4 | T-16.3-18, T-16.3-20, T-16.3-21 | Journal writes accept a journal-scoped token as the owner; resolver errors map to the PHP bodies | unit + Docker | `go -C ../sm-journal-plugin vet ./... && go -C ../sm-journal-plugin test -count=1 -run '^TestResolveErrorMapping$' ./controllers/api/ && go -C ../sm-journal-plugin test -count=1 ./classes/ ./controllers/...`; Docker: `go -C ../sm-journal-plugin test -count=1 -run '^TestJournalTokenTracer$' .` | ❌ W0 | ⬜ pending |
| 16.3-03-T2 | 03 | 3 | SC-2, SC-4, SC-5 | T-16.3-18, T-16.3-19, T-16.3-23 | journal:read and unrelated scopes refused on writes; drafts only as the owner may see; featured-image parity | docs + Docker | `go test -count=1 -run '^ExampleResolveBackend$\|^TestDocsTree$' ./modules/cabana ./cmd/summer && go run ./cmd/summer docs:build --check`; Docker: `go -C ../sm-journal-plugin test -count=1 -run '^(TestJournalTokenTracer\|TestJournalTokenExpansion\|TestJournalWriteUnauthenticated\|TestJournalFeaturedImageUnauthenticated)$' .` | ❌ W0 | ⬜ pending |
| 16.3-03-T3 | 03 | 3 | SC-4 | T-16.3-22 | human approves the tag with the one-way surfaces and NOT RUN suites listed | gate + checkpoint | release gate command in 16.3-03-PLAN.md Task 3 (`… && echo release-gate-ok`) | ✅ | ⬜ pending |
| 16.3-03-T4 | 03 | 3 | SC-4 | T-16.3-22 | tag, Journal require and host gitlink pushed only after approval | git checks | release-ok command in 16.3-03-PLAN.md Task 4 | ✅ | ⬜ pending |
| 16.3-04-T1 | 04 | 4 | SC-6, SC-2 | T-16.3-25 | scope rules, every route's token class, SPA plaintext backstop, Journal scope keys | unit + vitest + Docker | `go test -count=1 -run '^(TestScopeMatch\|TestAllowsScope\|TestTokenRouteGates)$' ./modules/cabana && npm --prefix admin test -- tests/account/ApiTokenCreateDialog.test.ts && go -C ../sm-journal-plugin test -short -count=1 -run '^TestJournalTokenScopes$' .`; Docker: `go test -count=1 -run '^TestBackendTokenPostgres$' ./modules/cabana` | ❌ W0 | ⬜ pending |
| 16.3-04-T2 | 04 | 4 | SC-6, SC-1..SC-4 | T-16.3-25, T-16.3-26 | full Go coverage incl. migration, API, CLI and Journal matrix | unit + Docker | the sixteen-name Docker-free cabana set in 16.3-04-PLAN.md Task 2; Docker: lagoon, cabana and Journal sets in the same task | ❌ W0 | ⬜ pending |
| 16.3-04-T3 | 04 | 4 | SC-6 | T-16.3-24 | gate fails closed on skips, zero tests and missing names | vitest + gate | `npm --prefix admin run typecheck && npm --prefix admin test && bash scripts/check-phase16.3.sh --self-test && bash scripts/check-phase16.3.sh --all` | ❌ W0 | ⬜ pending |
| 16.3-01-T1 | 01 | 1 | SC-1, SC-2 | T-16.3-01, T-16.3-02, T-16.3-04, T-16.3-07, T-16.3-11 | g15_ token runs as its owner; scope evaluated before the superuser shortcut; method refusal 403 token_scope; malformed tokens refused before the database | unit + Docker | `go test -count=1 -run '^(TestTokenTracerSmoke\|TestPhase09PermissionMatrix\|TestPhase09ContractInventory\|TestPhase10ConformanceInventory)$' ./modules/cabana`; Docker: `go test -count=1 -run '^TestTokenTracerPostgres$' ./modules/cabana` and `go test -count=1 -run '^(TestBackendAdminMetadataColumn\|TestPhase09MigrationsFreshRollback)$' ./modules/lagoon` | ✅ | ✅ green |
| 16.3-01-T2 | 01 | 1 | SC-2 | T-16.3-05, T-16.3-06, T-16.3-09, T-16.3-13 | interactive-only routes refuse every token; /field-types and /markdown/preview gated; ResolveBackend Bearer-only with cover; stamp debounced and non-fatal | unit + Docker | `go test -count=1 -run '^(TestTokenTracerSmoke\|TestTokenGatesSmoke\|TestPhase09PermissionMatrix\|TestPhase09ContractInventory\|TestPhase10ConformanceInventory\|TestPhase10CSRF)$' ./modules/cabana`; Docker: `go test -count=1 -run '^(TestTokenTracerPostgres\|TestAdminAuthLifecycle\|TestAdminLogoutRevokesExpiredRefreshableToken)$' ./modules/cabana` | ✅ | ✅ green |
| 16.3-01-T3 | 01 | 1 | SC-3 | T-16.3-03, T-16.3-08 | plaintext only in the 201 create body; own-only soft revoke; 422 on unknown, empty or non-overlapping scopes | unit + script + Docker | `go test -count=1 -run '^(TestPhase09PermissionMatrix\|TestPhase09ContractInventory\|TestPhase10ConformanceInventory\|TestTokenTracerSmoke\|TestTokenGatesSmoke)$' ./modules/cabana && bash scripts/check-admin-openapi.sh --check && npm --prefix admin run typecheck`; Docker: `go test -count=1 -run '^(TestAccountTokensSmoke\|TestPhase10OpenAPIConformance)$' ./modules/cabana` | ✅ | ✅ green |
| 16.3-01-T4 | 01 | 1 | SC-3, SC-5 | T-16.3-03, T-16.3-08 | admin:token:create prints only the token; CLI applies the overlap rule; docs name no consuming application | unit + Docker | `go vet ./... && go test -count=1 ./modules/party ./modules/pact && go test -count=1 -run '^(TestDocsTree\|TestDelegateCommandsHelp\|TestDocsCommandsMirrorGeneratedMain)$' ./cmd/summer && go run ./cmd/summer docs:build --check && go test -short -count=1 -run '^(TestPluginActivates\|TestRoutesRegistered)$' ./docs/examples/blog`; Docker: `go test -count=1 -run '^(TestTokenCommandsSmoke\|TestAdminCreateCommand)$' ./modules/cabana` | ✅ | ✅ green |
| 16.3-02-T1 | 02 | 2 | SC-3 | T-16.3-14, T-16.3-16 | plaintext shown once and cleared on Done; no storage, console or v-html in the account components | vitest + script | `npm --prefix admin run typecheck && npm --prefix admin test -- tests/account/ApiTokensPanel.test.ts tests/views/AccountView.test.ts && bash scripts/check-admin-openapi.sh --check && bash scripts/check-admin-dist.sh` | ✅ | ✅ green |
| 16.3-02-T2 | 02 | 2 | SC-3 | T-16.3-16 | revoke through the shared confirm; names rendered as text | vitest + script | `npm --prefix admin run typecheck && npm --prefix admin test -- tests/account/ApiTokensPanel.test.ts tests/views/AccountView.test.ts tests/ui/ui.test.ts && bash scripts/check-admin-dist.sh` | ✅ | ✅ green |
| 16.3-02-T3 | 02 | 2 | SC-3, SC-5 | T-16.3-14, T-16.3-15, T-16.3-17 | `*` sends only ["*"]; close-without-copy guard; clipboard fallback; server-filtered scopes only | vitest + docs | `npm --prefix admin run typecheck && npm --prefix admin test && bash scripts/check-admin-dist.sh && go test -count=1 ./cmd/summer -run TestDocsTree` | ✅ | ✅ green |
| 16.3-03-T1 | 03 | 3 | SC-4 | T-16.3-18, T-16.3-20, T-16.3-21 | Journal writes accept a journal-scoped token as the owner; resolver errors map to the PHP bodies | unit + Docker | `go -C ../sm-journal-plugin vet ./... && go -C ../sm-journal-plugin test -count=1 -run '^TestResolveErrorMapping$' ./controllers/api/ && go -C ../sm-journal-plugin test -count=1 ./classes/ ./controllers/...`; Docker: `go -C ../sm-journal-plugin test -count=1 -run '^TestJournalTokenTracer$' .` | ✅ | ✅ green |
| 16.3-03-T2 | 03 | 3 | SC-2, SC-4, SC-5 | T-16.3-18, T-16.3-19, T-16.3-23 | journal:read and unrelated scopes refused on writes; drafts only as the owner may see; featured-image parity | docs + Docker | `go test -count=1 -run '^ExampleResolveBackend$\|^TestDocsTree$' ./modules/cabana ./cmd/summer && go run ./cmd/summer docs:build --check`; Docker: `go -C ../sm-journal-plugin test -count=1 -run '^(TestJournalTokenTracer\|TestJournalTokenExpansion\|TestJournalWriteUnauthenticated\|TestJournalFeaturedImageUnauthenticated)$' .` | ✅ | ✅ green |
| 16.3-03-T3 | 03 | 3 | SC-4 | T-16.3-22 | human approves the tag with the one-way surfaces and NOT RUN suites listed | gate + checkpoint | release gate command in 16.3-03-PLAN.md Task 3 (`… && echo release-gate-ok`) | ✅ | ✅ green |
| 16.3-03-T4 | 03 | 3 | SC-4 | T-16.3-22 | tag, Journal require and host gitlink pushed only after approval | git checks | release-ok command in 16.3-03-PLAN.md Task 4 | ✅ | ✅ green |
| 16.3-04-T1 | 04 | 4 | SC-6, SC-2 | T-16.3-25 | scope rules, every route's token class, SPA plaintext backstop, Journal scope keys | unit + vitest + Docker | `go test -count=1 -run '^(TestScopeMatch\|TestAllowsScope\|TestTokenRouteGates)$' ./modules/cabana && npm --prefix admin test -- tests/account/ApiTokenCreateDialog.test.ts && go -C ../sm-journal-plugin test -short -count=1 -run '^TestJournalTokenScopes$' .`; Docker: `go test -count=1 -run '^TestBackendTokenPostgres$' ./modules/cabana` | ✅ | ✅ green |
| 16.3-04-T2 | 04 | 4 | SC-6, SC-1..SC-4 | T-16.3-25, T-16.3-26 | full Go coverage incl. migration, API, CLI and Journal matrix | unit + Docker | sixteen-name Docker-free cabana set in 16.3-04-PLAN.md Task 2; Docker: lagoon=3, cabana=4, Journal=3 | ✅ | ✅ green |
| 16.3-04-T3 | 04 | 4 | SC-6 | T-16.3-24 | gate fails closed on skips, zero tests and missing names | vitest + gate | `npm --prefix admin run typecheck && npm --prefix admin test && bash scripts/check-phase16.3.sh --self-test && bash scripts/check-phase16.3.sh --all` → last line `Phase 16.3 gate passed` (postgres PASS on this Docker host) | ✅ | ✅ green |
*Status: ⬜ pending · ✅ green · ❌ red · ⚠️ flaky*
@@ -63,13 +63,13 @@ Filled in by the planner from the RESEARCH.md test map and the four PLAN.md file
## Wave 0 Requirements
- [ ] `modules/cabana/token_smoke_test.go`, `token_postgres_smoke_test.go` — plan 01 smoke (tracer, gates, account API, commands)
- [ ] `modules/cabana/token_scopes_test.go`, `api_tokens_test.go`, `token_guard_test.go`, `token_routes_test.go` — Allows / scope match / compile / overlap / mint / expiry / validation / guard / resolver / route classification (Docker-free, plan 04)
- [ ] `modules/cabana/token_postgres_test.go`, `account_tokens_test.go`, `token_commands_test.go` — Postgres guard, account token API, token commands with stdout purity (plan 04)
- [ ] `modules/lagoon/backend_admin_migrations_test.go` — `TestBackendAPITokensMigration` and the updated last-ID test
- [ ] `admin/tests/account/ApiTokensPanel.test.ts`, `admin/tests/account/ApiTokenCreateDialog.test.ts` — UI-SPEC states and backstops (path chosen in plan 02; `tests/components/` does not exist)
- [ ] `../sm-journal-plugin/controllers/api/auth_test.go`, `journal_api_token_smoke_test.go`, `token_scopes_test.go`, `journal_api_tokens_test.go` — Journal mapping, scopes and token matrix
- [ ] `scripts/check-phase16.3.sh` — phase gate
- [x] `modules/cabana/token_smoke_test.go`, `token_postgres_smoke_test.go` — plan 01 smoke (tracer, gates, account API, commands)
- [x] `modules/cabana/token_scopes_test.go`, `api_tokens_test.go`, `token_guard_test.go`, `token_routes_test.go` — Allows / scope match / compile / overlap / mint / expiry / validation / guard / resolver / route classification (Docker-free, plan 04)
- [x] `modules/cabana/token_postgres_test.go`, `account_tokens_test.go`, `token_commands_test.go` — Postgres guard, account token API, token commands with stdout purity (plan 04)
- [x] `modules/lagoon/backend_admin_migrations_test.go` — `TestBackendAPITokensMigration` and the updated last-ID test
- [x] `admin/tests/account/ApiTokensPanel.test.ts`, `admin/tests/account/ApiTokenCreateDialog.test.ts` — UI-SPEC states and backstops (path chosen in plan 02; `tests/components/` does not exist)
- [x] `../sm-journal-plugin/controllers/api/auth_test.go`, `journal_api_token_smoke_test.go`, `token_scopes_test.go`, `journal_api_tokens_test.go` — Journal mapping, scopes and token matrix
- [x] `scripts/check-phase16.3.sh` — phase gate
---
@@ -78,17 +78,17 @@ Filled in by the planner from the RESEARCH.md test map and the four PLAN.md file
| Behavior | Requirement | Why Manual | Test Instructions |
|----------|-------------|------------|-------------------|
| Clipboard copy of the show-once token in a real browser | SC-3 | Clipboard API permissions differ from happy-dom | Create a token in the admin SPA, copy it, use it as `Authorization: Bearer` against a Journal write route |
| Postgres suites when an executor had no Docker daemon | SC-1..SC-4 | testcontainers needs Docker | On a Docker host: `bash scripts/check-phase16.3.sh postgres` (lagoon, cabana and Journal token suites by name) |
| Postgres suites when an executor had no Docker daemon | SC-1..SC-4 | testcontainers needs Docker | On a Docker host: `bash scripts/check-phase16.3.sh postgres` (lagoon, cabana and Journal token suites by name). **This executor host ran postgres: PASS.** |
---
## 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 < 180s
- [ ] `nyquist_compliant: true` set in frontmatter
- [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
- [x] Feedback latency < 180s
- [x] `nyquist_compliant: true` set in frontmatter
**Approval:** pending
**Approval:** plan 04 executor — gate `--all` ended with `Phase 16.3 gate passed` (2026-10-11)