Files
summercms/.planning/phases/07-user-plugin-and-authentication/07-VERIFICATION.md
Jakub Zych d4e9c17816 docs(07): record the phase goal verification
The six plans are in, and three of the four success criteria hold. AUTH-01 stays blocked because the 15 user API routes are still pending against the recorded PHP bodies.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-22 19:27:27 +02:00

5.6 KiB

phase, verified, status, score, overrides_applied
phase verified status score overrides_applied
07-user-plugin-and-authentication 2026-09-22T17:26:00Z gaps_found 3/4 must-haves verified 0

Phase 7: User plugin and authentication Verification Report

Phase Goal: The user plugin is ported with registration, login, JWT issue/refresh, organizations, personal API tokens and the must-change-password lock. Verified: 2026-09-22T17:26:00Z Status: gaps_found

Goal Achievement

Observable Truths

# Truth Status Evidence
1 A user can register, log in, log out, reset a password, verify email, and receive a JWT the Nuxt app can use unchanged ✗ FAILED Handlers and mail tests exist. The 15 /_user/api/v1 routes are recorded and pending. TestParityCorpus is 7 ported, 162 pending, 0 failing. Wrong-code activate is HTML 500 in PHP and 200 in Go. Fetch after logout is 200 in PHP and 401 in Go.
2 Organization fields arrive through a fire-and-collect event, and the user module does not import fonoteka ✓ VERIFIED TestGetApiArray and TestRegisterImportDirection passed under -race.
3 Personal tokens mint, list, and revoke inside the read/write/ai ceiling, and a read token is rejected on a write route ✓ VERIFIED TestTokenApi and TestInvScope passed under -race. The ported token and locale routes replay green.
4 The password lock returns 423 except locale and change-password, and locale still resolves while locked ✓ VERIFIED TestMustChangePasswordLock and TestLocaleFromPrincipal passed under -race.

Score: 3/4 truths verified

Required Artifacts

Artifact Expected Status Details
bouncer JWT mint/refresh/blacklist Session tokens ✓ EXISTS + SUBSTANTIVE Round-trip and concurrent blacklist tests passed
plugins/golem15/user session and account handlers Register through reset and activation ✓ EXISTS + SUBSTANTIVE Covered by session, mail, and sequence tests. Two responses differ from PHP
plugins/golem15/fonoteka tokens and locale AUTH-03 and the lock exemption ✓ EXISTS + SUBSTANTIVE Ported routes replay green
parity user-api fixtures Byte-identical replay ✗ RECORDED, NOT REPLAYED 15 routes stay pending

Artifacts: 3/4 verified

From To Via Status Details
fonoteka getApiArray listener user payload fire-and-collect ✓ WIRED TestGetApiArray
InvScope token routes Phase 6 middleware ✓ WIRED TestInvScope returns 403 for a missing write scope
user API handlers Nuxt contract parity replay ✗ NOT WIRED Pending routes are not sent to the Go handler

Wiring: 2/3 connections verified

Requirements Coverage

Requirement Status Blocking Issue
AUTH-01 ✗ BLOCKED User API responses are not the PHP contract the Nuxt app calls
AUTH-02 ✓ SATISFIED Event payload and import direction are tested. Checkbox stays open until this phase passes
AUTH-03 ✓ SATISFIED Mint, list, revoke, and scope ceiling are tested
AUTH-04 ✓ SATISFIED 423 exemption and lock clear are tested
I18N-02 ✓ SATISFIED LocaleFromPrincipal is tested, including the locked path

Coverage: 4/5 requirements satisfied. AUTH-01 blocks phase sign-off. None of the five checkboxes were marked in REQUIREMENTS.md.

Anti-Patterns Found

File Line Pattern Severity Impact
plugins/golem15/user/controllers/api_controller.go 322 VerifyActivationCode error discarded ⚠️ Warning Wrong code still returns 200
jwt_blacklist on logout — Stricter than PHP ⚠️ Warning Logged-out bearer is 401 in Go and 200 in PHP

Anti-patterns: 2 found (0 blockers, 2 warnings)

Human Verification Required

None — the failing comparison is already in the recorded fixtures.

Gaps Summary

Critical Gaps (Block Progress)

  1. User API is not the PHP contract
    • Missing: a green replay of the 15 /_user/api/v1 routes
    • Impact: the Nuxt app would notice activate and fetch-after-logout, and the other pending bodies were not accepted as matches
    • Fix: change the Go handlers to the recorded PHP status and body, then flip those routes from pending to ported only when replay is green

Non-Critical Gaps (Can Defer)

None. The schema allow-list for user_throttle and jwt_blacklist is an intentional snapshot gap, not a missing migration.

07-07-PLAN.md: Close the user API parity gaps

Objective: Make the 15 recorded /_user/api/v1 routes replay against Go.

Tasks:

  1. Match authenticated activate and activate-by-code failure to the recorded HTML 500.
  2. Match fetch-after-logout to the recorded 200, or record an explicit decision that Go's blacklist is the contract and update the fixtures.
  3. Diff the remaining pending bodies and close each one, then flip the route to ported only after replay is green.

Estimated scope: Medium

Verification Metadata

Verification approach: Goal-backward from the ROADMAP success criteria Must-haves source: ROADMAP.md Phase 7 success criteria Automated checks: go test ./... -race passed in both modules after the schema-gate fix. Schema drift check returned drift_detected: false. Human checks required: 0 Regression gate: prior-phase suites are in the same go test ./... -race run and passed


Verified: 2026-09-22T17:26:00Z Verifier: inline goal check after 07-06