docs(07): verify phase after the avatar bucket gap close
Assembled avatar POST is 200. UAT is 12/12. AUTH-02 through AUTH-04 and I18N-02 are marked complete. Do not auto-advance. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,16 +1,16 @@
|
||||
---
|
||||
phase: 07-user-plugin-and-authentication
|
||||
verified: 2026-09-22T17:26:00Z
|
||||
status: gaps_found
|
||||
score: 3/4 must-haves verified
|
||||
verified: 2026-09-23T08:52:00Z
|
||||
status: passed
|
||||
score: 4/4 must-haves verified
|
||||
overrides_applied: 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
|
||||
**Verified:** 2026-09-23T08:52:00Z
|
||||
**Status:** passed
|
||||
|
||||
## Goal Achievement
|
||||
|
||||
@@ -18,93 +18,79 @@ overrides_applied: 0
|
||||
|
||||
| # | 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`. |
|
||||
| 1 | A user can register, log in, log out, reset a password, verify email, and receive a JWT the Nuxt app can use unchanged | ✓ VERIFIED | 15 `/_user/api/v1` routes and both nuxt-auth flows are `ported`. `TestParityCorpus` is recorded 169 / ported 22 / pending 147 / failing 0. UAT tests 1–4 and 12 passed. |
|
||||
| 2 | Organization fields arrive through a fire-and-collect event, and the user module does not import fonoteka | ✓ VERIFIED | UAT test 6: login/register include organisation fields; `go list -deps` on the user module does not import `plugins/golem15/fonoteka`. |
|
||||
| 3 | Personal tokens mint, list, and revoke inside the read/write/ai ceiling, and a read token is rejected on a write route | ✓ VERIFIED | UAT test 7; `TestTokenApi` and `TestInvScope`. |
|
||||
| 4 | The password lock returns 423 except locale and change-password, and locale still resolves while locked | ✓ VERIFIED | UAT tests 8–9; `TestMustChangePasswordLock`. |
|
||||
|
||||
**Score:** 3/4 truths verified
|
||||
**Score:** 4/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` |
|
||||
| `bouncer` JWT mint/refresh/blacklist | Session tokens | ✓ EXISTS + SUBSTANTIVE | Logout blacklists; fetch after logout is 401 |
|
||||
| `plugins/golem15/user` session and account handlers | Register through reset, activation, avatar | ✓ EXISTS + SUBSTANTIVE | Assembled avatar POST is 200 after 07-08 |
|
||||
| `plugins/golem15/fonoteka` tokens and locale | AUTH-03 and the lock exemption | ✓ EXISTS + SUBSTANTIVE | Ported token and locale routes replay green |
|
||||
| `parity` user-api fixtures | Byte-identical replay | ✓ REPLAYED | 15 user-api routes `ported`; both nuxt flows green |
|
||||
| serve + Handler bucket publish | Avatar boot path | ✓ EXISTS + SUBSTANTIVE | `TestPublishUploads*`, `TestAvatarAssembled` |
|
||||
|
||||
**Artifacts:** 3/4 verified
|
||||
**Artifacts:** 5/5 verified
|
||||
|
||||
### Key Link Verification
|
||||
|
||||
| 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 |
|
||||
| fonoteka `getApiArray` listener | user payload | fire-and-collect | ✓ WIRED | UAT test 6 |
|
||||
| `InvScope` | token routes | Phase 6 middleware | ✓ WIRED | `TestInvScope` 403 for missing write |
|
||||
| user API handlers | Nuxt contract | parity replay | ✓ WIRED | `TestUserAPINuxtFlows` |
|
||||
| `attach.OpenBucket` | serve / Handler | `Publish` before Assemble | ✓ WIRED | `44900f0` / `bc1adf2` |
|
||||
|
||||
**Wiring:** 2/3 connections verified
|
||||
**Wiring:** 4/4 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 |
|
||||
| AUTH-01 | ✓ SATISFIED | 07-07 flipped the 15 user-api routes and both nuxt flows to ported |
|
||||
| AUTH-02 | ✓ SATISFIED | Organisation fields via event; user does not import fonoteka |
|
||||
| AUTH-03 | ✓ SATISFIED | Mint, list, revoke, and scope ceiling |
|
||||
| AUTH-04 | ✓ SATISFIED | 423 lock with locale exemption |
|
||||
| I18N-02 | ✓ SATISFIED | preferred_locale then Accept-Language then app.locale, including while locked |
|
||||
|
||||
**Coverage:** 4/5 requirements satisfied. AUTH-01 blocks phase sign-off. None of the five checkboxes were marked in `REQUIREMENTS.md`.
|
||||
**Coverage:** 5/5 requirements satisfied.
|
||||
|
||||
## 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)
|
||||
None that block. Handler does not close the published `*blob.Bucket` (info in 07-REVIEW.md); CLI serve does.
|
||||
|
||||
## Human Verification Required
|
||||
|
||||
None — the failing comparison is already in the recorded fixtures.
|
||||
None — UAT was curl-verified on the assembled Handler. The avatar 500 is closed by 07-08 (`TestAvatarAssembled`).
|
||||
|
||||
## 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
|
||||
None.
|
||||
|
||||
### 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.
|
||||
- `app.Handler` does not close the uploads bucket (CLI serve does). Fine for `mem://` tests.
|
||||
- Static `/storage/uploads` is not mounted on Assemble; `avatar_url` is a path, not a served GET. Out of this phase's success criteria.
|
||||
|
||||
## Recommended Fix Plans
|
||||
|
||||
### 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
|
||||
None.
|
||||
|
||||
## 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`.
|
||||
**Verification approach:** Goal-backward from ROADMAP Phase 7 success criteria after 07-08 gap closure
|
||||
**Must-haves source:** ROADMAP.md Phase 7 success criteria + 07-08 PLAN must_haves
|
||||
**Automated checks:** `go vet ./... && go test ./... -race` green in `summercms.go` and `fonoteka.go` plus nested plugin packages. `TestAvatarAssembled` green. Schema drift `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*
|
||||
*Verified: 2026-09-23T08:52:00Z*
|
||||
*Verifier: inline goal check after 07-08*
|
||||
|
||||
Reference in New Issue
Block a user