diff --git a/.planning/PROJECT.md b/.planning/PROJECT.md index 5518f44..ea3dced 100644 --- a/.planning/PROJECT.md +++ b/.planning/PROJECT.md @@ -44,6 +44,12 @@ Validated in Phase 5: Data layer full fidelity - [x] All 25 Płytarium models ported with matching tables, relations, casts, lifecycle hooks, and fillable/hidden/encrypted mass-assignment discipline; squashed gormigrate sets run up and down; schema-diff vs a committed PHP snapshot; `migrate:rollback --plugin=fonoteka` isolates that plugin - [x] `lagoon.Fill` allow-list copy, `lagoon.Validate` Laravel rule strings, `lagoon.Paginate` `{data, meta}` envelope, AES-256-GCM `lagoon.Encrypted`, Jsonable TEXT casts, MoneyString 4-decimal numeric, and `system_files` attach (blob + Winter Thumb names). HTTP public URL serving of uploads remains Phase 6. +Validated in Phase 7: User plugin and authentication + +- [x] User plugin port: registration, login, logout, password reset, email verification, JWT issue/refresh with Nuxt claims, organizations via fire-and-collect, personal API tokens with a read|write|ai ceiling, and the must-change-password 423 lock with locale exemption +- [x] Locale resolves per request from preferred_locale then Accept-Language then app.locale, including while the lock is active +- [x] `surf.ServeCommand` and `app.Handler` publish the uploads `*blob.Bucket` so assembled avatar POST is 200 + ### Active Framework kernel @@ -57,7 +63,7 @@ Data layer HTTP and auth -- [ ] User plugin port beyond the throwaway HS256 verifier: accounts, registration, login, password reset, JWT issuing for the SPA, organizations and org-scoped permissions +- (user plugin / JWT / orgs / personal tokens / password lock — moved to Validated in Phase 7) - [ ] OAuth2/OIDC provider (zitadel/oidc) that the MCP server and the ChatGPT connector use with the same flows as today (auth code + PKCE, refresh tokens, client management, `IssueOAuthClient` command) - [ ] All 154 Płytarium API routes ported with byte-compatible request and response shapes (collections, albums, artists, genres, styles, ratings, reservations, wishlist, sharing and invitations, notifications, realtime channel auth, CSV import/export, locale, user context, credentials) @@ -168,4 +174,4 @@ This document evolves at phase transitions and milestone boundaries. 4. Update Context with current state --- -*Last updated: 2026-09-18 after Phase 5 completion* +*Last updated: 2026-09-23 after Phase 7 completion* diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index 22297e5..fbd82f8 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -456,7 +456,7 @@ Phases execute in numeric order: 1 → 2 → 3 → 4 → 5 → 6 → 7 → 8 → | 4. CLI scaffolding, i18n and mail | 4/4 | Complete | 2026-09-18 | | 5. Data layer full fidelity | 6/6 | Complete | 2026-09-18 | | 6. HTTP routing, auth groups and rate limiting | 14/14 | Complete | 2026-09-21 | -| 7. User plugin and authentication | 8/8 | Complete | 2026-09-23 | +| 7. User plugin and authentication | 8/8 | Complete | 2026-09-23 | | 8. OAuth2.1 authorization server | 0/TBD | Not started | - | | 9. Backend admin authentication and schema pipeline | 0/TBD | Not started | - | | 10. Admin Vue SPA | 0/TBD | Not started | - | diff --git a/.planning/STATE.md b/.planning/STATE.md index 8d86976..7453490 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -2,9 +2,9 @@ gsd_state_version: 1.0 milestone: v1.0 milestone_name: milestone -status: verifying -stopped_at: Completed 07-08-PLAN.md -last_updated: "2026-09-23T08:51:11.470Z" +status: ready_to_plan +stopped_at: Phase 7 complete (8/8) — ready to discuss Phase 08 +last_updated: 2026-09-23T08:53:13.477Z last_activity: 2026-09-23 -- Completed 07-08-PLAN.md progress: total_phases: 15 @@ -21,14 +21,14 @@ progress: See: .planning/PROJECT.md (updated 2026-09-16) **Core value:** An existing WinterCMS-shaped app can be ported plugin by plugin to a single Go binary without its frontend noticing: the PHP version's API contract is the acceptance test. -**Current focus:** Phase 07 — user-plugin-and-authentication +**Current focus:** Phase 08 — oauth2 1 authorization server ## Current Position -Phase: 07 (user-plugin-and-authentication) — EXECUTING -Plan: 8 of 8 -Status: All 8 plans have SUMMARYs. Ready for phase verification — do not auto-advance. -Last activity: 2026-09-23 -- Completed 07-08-PLAN.md +Phase: 08 +Plan: Not started +Status: Ready to plan +Last activity: 2026-09-23 Progress: [██████████] 100% @@ -36,7 +36,7 @@ Progress: [██████████] 100% **Velocity:** -- Total plans completed: 48 +- Total plans completed: 56 - Average duration: 21 min - Total execution time: 104 min @@ -50,6 +50,7 @@ Progress: [██████████] 100% | 04 | 4 | - | - | | 05 | 6 | - | - | | 06 | 14 | - | - | +| 7 | 8 | - | - | **Recent Trend:** diff --git a/.planning/debug/resolved/avatar-bucket-not-published.md b/.planning/debug/resolved/avatar-bucket-not-published.md index 73279c6..8ca1864 100644 --- a/.planning/debug/resolved/avatar-bucket-not-published.md +++ b/.planning/debug/resolved/avatar-bucket-not-published.md @@ -1,7 +1,12 @@ +--- +status: resolved +updated: 2026-09-23T08:52:00Z +--- + # DEBUG: Avatar upload 500 on assembled app **Discovered:** 2026-09-23 during `$gsd-verify-work 7` -**Status:** diagnosed +**Status:** resolved **Goal:** find_root_cause_only ## Symptoms @@ -32,3 +37,7 @@ Unit tests call `publishAvatarBucket` (memblob) themselves. The ported parity fi 1. Open and publish the bucket next to `lagoon.Publish` in `ServeCommand` and `app.Handler`. Empty `storage.uploads.bucket_url` already fails loud. 2. Set `storage.uploads.bucket_url=mem://` on assembled-test configs. 3. Add a Handler-level multipart upload test so this cannot regress behind the 422 fixture. + +## Resolution + +07-08 published the bucket on both boot paths. `TestAvatarAssembled` POSTs a JPEG through `app.Handler` (200, `has_avatar`, `avatar_url`) then remove.