From e6d013717faf3d4ac1e63036877688ca0cbfc128 Mon Sep 17 00:00:00 2001 From: Jakub Zych Date: Fri, 25 Sep 2026 21:57:54 +0200 Subject: [PATCH] docs(09-07): complete artists admin controller plan --- .planning/ROADMAP.md | 6 +- .planning/STATE.md | 21 +- .../09-07-SUMMARY.md | 188 ++++++++++++++++++ 3 files changed, 203 insertions(+), 12 deletions(-) create mode 100644 .planning/phases/09-backend-admin-authentication-and-schema-pipeline/09-07-SUMMARY.md diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index 13bde89..32d16b1 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -375,7 +375,7 @@ Plans: 4. The relation-manager schema supports search/link/unlink/manage-or-view lists for Collections' editors tab, replacing the `partial` field entirely. 5. Admin CRUD endpoints expose `listExtendQuery`/`formExtendQuery`/`formBeforeCreate`/`formBeforeUpdate`/`relationExtendManageQuery` hooks, bulk delete runs each record's lifecycle hooks, and the Settings model binds to a settings screen through the same schema pipeline. -**Plans**: 6/12 plans executed +**Plans**: 7/12 plans executed **Research flag:** yes Plans: @@ -399,7 +399,7 @@ Plans: - [x] 09-06-PLAN.md — Port the Albums admin surface and the collection boundary **Wave 7** *(blocked on Wave 6 completion)* -- [ ] 09-07-PLAN.md — Port the Artists backend controller +- [x] 09-07-PLAN.md — Port the Artists backend controller - [ ] 09-08-PLAN.md — Complete the Genres controller with form/list parity - [ ] 09-09-PLAN.md — Port the Styles controller and typed provider/filter behavior - [ ] 09-10-PLAN.md — Deliver Collections and the typed relation manager @@ -529,7 +529,7 @@ Phases execute in numeric order: 1 → 2 → 3 → 4 → 5 → 6 → 7 → 8 → | 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 | | 8. OAuth2.1 authorization server | 10/10 | Complete | 2026-09-23 | -| 9. Backend admin authentication and schema pipeline | 6/12 | In Progress| | +| 9. Backend admin authentication and schema pipeline | 7/12 | In Progress| | | 10. Admin Vue SPA | 0/TBD | Not started | - | | 11. Jobs, realtime and search infrastructure | 0/TBD | Not started | - | | 12. Płytarium API — Collections and Albums | 0/TBD | Not started | - | diff --git a/.planning/STATE.md b/.planning/STATE.md index a6559fd..ffc0fae 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -4,16 +4,16 @@ milestone: v1.0 current_phase: 09 current_phase_name: Backend admin authentication and schema pipeline status: executing -stopped_at: Completed 09-06-PLAN.md -last_updated: "2026-09-24T18:21:51.771Z" -last_activity: 2026-09-24 +stopped_at: Completed 09-07-PLAN.md +last_updated: "2026-09-25T19:49:37.835Z" +last_activity: 2026-09-25 last_activity_desc: Phase 09 execution started -state_head: 0caa86ec0b6d255dd22a55ee5923a40d3a821977 +state_head: fe639ac0d32a7a1c37d897f604fdf21f478b9854 progress: total_phases: 15 completed_phases: 8 total_plans: 67 - completed_plans: 61 + completed_plans: 62 milestone_name: milestone --- @@ -29,9 +29,9 @@ See: .planning/PROJECT.md (updated 2026-09-16) ## Current Position Phase: 09 (Backend admin authentication and schema pipeline) — EXECUTING -Plan: 7 of 12 +Plan: 8 of 12 Status: Ready to execute -Last activity: 2026-09-24 — Phase 09 execution started +Last activity: 2026-09-25 — Phase 09 execution started Progress: [██████████] 100% @@ -115,6 +115,7 @@ Progress: [██████████] 100% | Phase 09 P04 | 36min | 3 tasks | 13 files | | Phase 09 P05 | 25min | 3 tasks | 8 files | | Phase 09 P06 | 29min | 3 tasks | 15 files | +| Phase 09 P07 | 2h20m | 2 tasks | 9 files | ## Accumulated Context @@ -297,6 +298,8 @@ Recent decisions affecting current work: - [Phase 09]: Winter relation keys match exported Go fields case-insensitively and the served JSON keeps the YAML spelling - [Phase 09]: Required relation fields stay on the admin form schema and are not save-time column rules - [Phase 09]: Genre and style admin option values are decimal strings because pact.Option.Value is a string +- [Phase 09]: Artists uses only the shared cabana list and CRUD engines; the controller contains identity, asset paths, model factory, and permission declaration only +- [Phase 09]: Artist name_key and slug remain model-owned lifecycle fields and are not exposed by the admin writable projection ### Pending Todos @@ -319,6 +322,6 @@ Items acknowledged and carried forward from previous milestone close: ## Session Continuity -Last session: 2026-09-24T18:21:51.437Z -Stopped at: Completed 09-06-PLAN.md +Last session: 2026-09-25T19:49:37.540Z +Stopped at: Completed 09-07-PLAN.md Resume file: None diff --git a/.planning/phases/09-backend-admin-authentication-and-schema-pipeline/09-07-SUMMARY.md b/.planning/phases/09-backend-admin-authentication-and-schema-pipeline/09-07-SUMMARY.md new file mode 100644 index 0000000..f98e2d5 --- /dev/null +++ b/.planning/phases/09-backend-admin-authentication-and-schema-pipeline/09-07-SUMMARY.md @@ -0,0 +1,188 @@ +--- +phase: 09-backend-admin-authentication-and-schema-pipeline +plan: 07 +subsystem: admin +tags: [cabana, artists, winter-yaml, permissions, postgres, crud] + +requires: + - phase: 09-backend-admin-authentication-and-schema-pipeline + provides: compiled form/list schemas, operation permission gates, and schema-projected CRUD/bulk services +provides: + - Registered Artists admin controller with complete embedded Winter form and list assets + - Permission-first Artist schema, list, create, update, show, delete, and bulk-delete routes + - PostgreSQL acceptance coverage for projection, lifecycle normalization, pagination, atomicity, and retry safety +affects: [09-backend-admin-authentication-and-schema-pipeline, admin-api, phase-10-spa] + +actuals: + tokens: 5094 + tasks: 2 + commits: 0 + +tech-stack: + added: [] + patterns: + - "Catalog admin controllers are declarative model/config adapters over cabana; they add no local SQL or write path" + - "Every generated Artist operation shares one explicit permission checked before schema or database work" + +key-files: + created: + - ../fonoteka.go/plugins/golem15/fonoteka/controllers/artists_admin_controller.go + - ../fonoteka.go/plugins/golem15/fonoteka/controllers/artists/config_form.yaml + - ../fonoteka.go/plugins/golem15/fonoteka/controllers/artists/config_list.yaml + - ../fonoteka.go/plugins/golem15/fonoteka/models/artist/fields.yaml + - ../fonoteka.go/plugins/golem15/fonoteka/models/artist/columns.yaml + - ../fonoteka.go/plugins/golem15/fonoteka/admin_artists_test.go + modified: + - ../fonoteka.go/plugins/golem15/fonoteka/admin.go + - ../fonoteka.go/plugins/golem15/fonoteka/controllers/admin_registry.go + - ../fonoteka.go/plugins/golem15/fonoteka/controllers/genres_admin_controller.go + +key-decisions: + - "Artists uses only the shared cabana list and CRUD engines; the controller contains identity, asset paths, model factory, and permission declaration only" + - "Winter Artist YAML is copied without reducing fields, columns, toolbar behavior, labels, or layout hints" + - "Artist name_key and slug remain model-owned lifecycle fields and are not exposed by the admin writable projection" + +patterns-established: + - "Pattern: global catalog resources register a zero-state AdminController with one operation permission and a typed NewRecord factory" + - "Pattern: activation embeds both list and form assets because registry compilation validates the complete controller contract at boot" + +requirements-completed: [ADMIN-01, ADMIN-02, ADMIN-04] + +coverage: + - id: D1 + description: Artists form compilation preserves every Winter field, label, span, required/default hint, and declaration order for pl and en. + requirement: ADMIN-01 + verification: + - kind: integration + ref: plugins/golem15/fonoteka/admin_artists_test.go#TestArtistsAdminForm + status: pass + - kind: integration + ref: plugins/golem15/fonoteka/admin_artists_test.go#TestArtistsAdminRegistration + status: pass + human_judgment: false + - id: D2 + description: Artist form, create, and update operations deny unauthorized admins before Artist SQL or controller work. + requirement: ADMIN-01 + verification: + - kind: integration + ref: plugins/golem15/fonoteka/admin_artists_test.go#TestArtistsAdminWritePermissions + status: pass + human_judgment: false + - id: D3 + description: Artists list schema and routes retain source columns, actions, localization, empty arrays, stable ordering, adjacent pages, and exact identifiers. + requirement: ADMIN-02 + verification: + - kind: integration + ref: plugins/golem15/fonoteka/admin_artists_test.go#TestArtistsAdminList + status: pass + human_judgment: false + - id: D4 + description: Artist CRUD projects only form fields while model hooks derive name_key and slug and protected keys remain unchanged. + requirement: ADMIN-04 + verification: + - kind: integration + ref: plugins/golem15/fonoteka/admin_artists_test.go#TestArtistsAdminCRUD + status: pass + human_judgment: false + - id: D5 + description: Empty, duplicate, mixed-existing, successful, and repeated Artist bulk deletes preserve validation, transaction atomicity, lifecycle deletion, and retry safety. + requirement: ADMIN-04 + verification: + - kind: integration + ref: plugins/golem15/fonoteka/admin_artists_test.go#TestArtistsAdminBulk + status: pass + human_judgment: false + +duration: 2h 20m +completed: 2026-09-25 +status: complete +plan_head_before: fe639ac0d32a7a1c37d897f604fdf21f478b9854 +plan_head_after: fe639ac0d32a7a1c37d897f604fdf21f478b9854 +--- + +# Phase 9 Plan 07: Artists Admin Controller Summary + +**A complete permission-gated Artists admin controller now serves unchanged Winter form/list schemas and inherits the shared deterministic CRUD and atomic bulk contracts.** + +## Performance + +- **Duration:** 2h 20m (includes two stalled executor attempts before inline fallback) +- **Started:** 2026-09-25T17:28:00Z +- **Completed:** 2026-09-25T19:48:22Z +- **Tasks:** 2 +- **Files modified:** 9 + +## Accomplishments + +- Embedded and strictly compiled every tracked Artist form field, list column, toolbar action, locale key, layout hint, and default in source order. +- Registered `golem15.fonoteka.artists` with `golem15.fonoteka.access_artists`, enforced before schema localization or Artist database access. +- Proved shared list, projected CRUD, lifecycle normalization, atomic bulk deletion, duplicate normalization, and retry-safe repeated deletion on assembled PostgreSQL routes. + +## TDD Gate Compliance + +The RED commit `35b04e7` established failing form, registration, permission, list, CRUD, and bulk contracts before the GREEN controller/assets commit `e595617`. Task 2 edge refinements landed in `5964c8c`; the final `^TestArtistsAdmin` suite passes. + +## Task Commits + +1. **Task 1: Port Artists form schema and controller registration** - `35b04e7` (test, fonoteka.go), `e595617` (feat, fonoteka.go) +2. **Task 2: Port Artists list and prove inherited CRUD/bulk edges** - `35b04e7` (test, fonoteka.go), `5964c8c` (test, fonoteka.go) + +The framework repository required no production change for this plan, so its measured commit count is zero. Fonoteka commits span `35b04e7..5964c8c`. + +## Files Created/Modified + +- `fonoteka.go/plugins/golem15/fonoteka/controllers/artists_admin_controller.go` - Artist controller identity, model factory, asset path, and permission map +- `fonoteka.go/plugins/golem15/fonoteka/controllers/artists/config_form.yaml` - unchanged Winter form-controller contract +- `fonoteka.go/plugins/golem15/fonoteka/controllers/artists/config_list.yaml` - unchanged Winter list-controller contract +- `fonoteka.go/plugins/golem15/fonoteka/models/artist/fields.yaml` - complete Artist form fields and layout hints +- `fonoteka.go/plugins/golem15/fonoteka/models/artist/columns.yaml` - complete Artist list columns +- `fonoteka.go/plugins/golem15/fonoteka/admin_artists_test.go` - assembled permission, schema, list, CRUD, and bulk acceptance suite +- `fonoteka.go/plugins/golem15/fonoteka/admin.go` - embeds the four Artist schema assets +- `fonoteka.go/plugins/golem15/fonoteka/controllers/genres_admin_controller.go` - adds Artists to the plugin controller roster + +## Decisions Made + +- Kept Artists as a zero-state controller. All query, projection, validation, lifecycle, transaction, and response behavior remains in the shared cabana engines. +- Kept `name_key` and `slug` out of the writable schema. `models.Artist.BeforeValidate` derives them, and hostile request values are dropped. +- Preserved raw phrase keys when translations are absent, matching the established phrasebook fallback contract. + +## Deviations from Plan + +### Auto-fixed Issues + +**1. [Rule 3 - Blocking] Embedded list assets during form/controller registration** +- **Found during:** Task 1 +- **Issue:** Cabana activation compiles a controller's list contract before its optional form contract, so registering Artists with only form files fails boot. +- **Fix:** Copied and embedded the unchanged Winter `config_list.yaml` and `columns.yaml` in the registration commit; Task 2 then exercised them through real routes. +- **Files modified:** `controllers/artists/config_list.yaml`, `models/artist/columns.yaml`, `admin.go` +- **Verification:** `TestArtistsAdminRegistration`, `TestArtistsAdminList` +- **Committed in:** `e595617` + +--- + +**Total deviations:** 1 auto-fixed (1 blocking) +**Impact on plan:** The files were already Task 2 deliverables; only their activation timing moved earlier. No scope was added. + +## Issues Encountered + +The configured `gsd-executor` stalled twice without creating files or commits. Artifact reconciliation confirmed no partial plan work, so execution continued inline under the two-task threshold. Test fixtures were adjusted to respect the existing unique `name_key` constraint and PostgreSQL `int4` primary-key range. + +`ADMIN-01`, `ADMIN-02`, and `ADMIN-04` remain pending in `REQUIREMENTS.md` because later Phase 9 plans also declare them. + +## User Setup Required + +None - no external service configuration required. + +## Next Phase Readiness + +Ready for 09-08 through 09-10. Artists is complete; Genres, Styles, and Collections remain the Wave 7 peers. + +## Self-Check: PASSED + +- FOUND: `fonoteka.go` commits `35b04e7`, `e595617`, and `5964c8c` +- FOUND: Artists controller plus all four embedded Winter schema assets +- PASSED: `GOCACHE=/tmp/summercms-go-build go test ./plugins/golem15/fonoteka -run '^TestArtistsAdmin' -count=1` + +--- +*Phase: 09-backend-admin-authentication-and-schema-pipeline* +*Completed: 2026-09-25*