docs(phase-32.1): add validation strategy

This commit is contained in:
2026-10-28 13:38:02 +01:00
parent bd23a82f22
commit 0db030598e

View File

@@ -0,0 +1,92 @@
---
phase: "32.1"
slug: "mcp-oauth-for-plugin-apps-declared-scopes-mcp-subject-on-con"
# 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
created: "2026-10-28"
---
# Phase 32.1 — Validation Strategy
> Per-phase validation contract for feedback sampling during execution.
> Seeded from `32.1-RESEARCH.md` § Validation Architecture. No REQ-IDs are mapped; rows use success criteria SC-1..SC-4.
---
## Test Infrastructure
| Property | Value |
|----------|-------|
| **Framework** | Go `testing` (stdlib). Plugins use testcontainers-go v0.44.0 off `-short`. vue-oauth-layer uses `node --test`. |
| **Config file** | none — Go has no repo-level test config. Layer: `package.json` script `test`, copied from vue-menu-layer. |
| **Quick run command** | `go test -short ./modules/pact ./modules/pier ./modules/wristband ./modules/bouncer` |
| **Full suite command** | `go test -short ./...` in this repo; `go test ./...` in each plugin repo (Docker); `pnpm test` in vue-oauth-layer |
| **Estimated runtime** | ~60 seconds for the quick command; plugin non-short tests depend on Docker |
---
## Sampling Rate
- **After every task commit:** `go test -short` on the packages that commit touched (`./modules/pact`, `./modules/pier`, `./modules/wristband`, or the plugin's `-short` suite), plus `go vet` on those packages.
- **After every plan wave:** `go test -short ./...` in the repo that merged. Plugin waves that touch consent or revoke also run the non-short tests named below when Docker is up.
- **Before `$msd-verify-work`:** Full `-short` suite in the framework repo, non-short consent/revoke/backfill tests in sm-oauthserver-plugin, `go test -short ./...` in sm-user-plugin on the v0.1.14 branch, `pnpm test` in the layer, `go test ./cmd/summer -run TestDocsTree`.
- **Max feedback latency:** 120 seconds
---
## Per-Task Verification Map
| Task ID | Plan | Wave | Requirement | Threat Ref | Secure Behavior | Test Type | Automated Command | File Exists | Status |
|---------|------|------|-------------|------------|-----------------|-----------|-------------------|-------------|--------|
| 32.1-01-01 | 01 | 1 | SC-1 | — | Declared scope names are advertised and unknown names are rejected; OIDC discovery scopes stay unchanged | unit | `go test -short ./modules/wristband -run 'TestMCPScopes\|TestMetadata' -count=1` | ❌ W0 | ⬜ pending |
| 32.1-02-01 | 02 | 2 | SC-1 | — | `Implies` applies only to OAuth MCP subjects; personal tokens are not expanded | unit | `go test -short . -run 'TestMCP' -count=1` in sm-user-plugin on v0.1.14 | ❌ W0 | ⬜ pending |
| 32.1-01-02 | 01 | 1 | SC-1 | — | pier PRM `scopes_supported` matches the published catalog | unit | `go test -short ./modules/pier -run 'TestPRM\|TestProtected' -count=1` | ❌ W0 | ⬜ pending |
| 32.1-01-03 | 01 | 1 | SC-2 | — | `MCPCallFrom` returns the call subject on a dispatched tool and is empty on a plain request | unit | `go test -short ./modules/pier -run TestDispatch -count=1` | ❌ W0 | ⬜ pending |
| 32.1-03-01 | 03 | 3 | SC-3 | — | Consent replace, revoke of one client, and MCP code deletion do not touch another client | integration | `cd ../sm-oauthserver-plugin && go test -count=1 -run 'TestMCPConsent\|TestAuthorizations\|TestMCPRevocation'` | ❌ W0 | ⬜ pending |
| 32.1-04-01 | 04 | 4 | SC-3 | — | Consent page posts scopes as JSON and does not render phrasebook strings as HTML | unit | `pnpm test` in vue-oauth-layer | ❌ W0 | ⬜ pending |
| 32.1-05-01 | 05 | 5 | SC-4 | — | Docs identifiers resolve | unit | `go test ./cmd/summer -run TestDocsTree -count=1` | ✅ | ⬜ pending |
*Status: ⬜ pending · ✅ green · ❌ red · ⚠️ flaky*
Task IDs above are placeholders until plans exist. The executor updates this map to the real task IDs.
---
## Wave 0 Requirements
- [ ] `modules/pact` test that `FrontendTokenScope` still composites without `Implies` and that `MCPCallFrom` is false on a bare context — SC-2 negative
- [ ] `modules/pier` PRM test with and without `MCPAdvertisedScopes` — SC-1
- [ ] `modules/pier` dispatch test that the context carries `MCPCall` for a frontend tool and a backend tool — SC-2
- [ ] sm-user-plugin `mcp_guard_test.go` cases for `Implies`, written against v0.1.14 — SC-1
- [ ] sm-oauthserver-plugin consent upsert, replace-not-merge, offline_access flag, revoke-deletes-MCP-code, backfill idempotence — SC-3
- [ ] `authorizations_smoke_test.go` key list includes `kind` — SC-3
- [ ] vue-oauth-layer `tests/connect.test.ts` — page mapping
- [ ] Framework install: none. Layer: `pnpm install` in the new repo once `package.json` exists
Existing wristband and pier test infrastructure hosts the new cases. No new test dependency.
---
## Manual-Only Verifications
| Behavior | Requirement | Why Manual | Test Instructions |
|----------|-------------|------------|-------------------|
| Patch tags of the framework and `sm-oauthserver-plugin`, and the changelog post | SC-4 | Tagging and publishing need an explicit user go-ahead and are not plan steps | After the code lands, ask before `git tag` or `scripts/changelog-post.py publish` |
All other phase behaviors have automated verification.
---
## 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
- [ ] `nyquist_compliant: true` set in frontmatter
**Approval:** pending