docs(09-08): complete genres admin controller plan

This commit is contained in:
Jakub Zych
2026-09-26 11:25:00 +02:00
parent e6d013717f
commit e9c0722337
3 changed files with 184 additions and 10 deletions

View File

@@ -0,0 +1,171 @@
---
phase: 09-backend-admin-authentication-and-schema-pipeline
plan: 08
subsystem: admin
tags: [cabana, genres, winter-yaml, permissions, postgres, crud]
requires:
- phase: 09-backend-admin-authentication-and-schema-pipeline
provides: Genre list tracer, compiled schema registry, permission gates, and shared CRUD/bulk services
provides:
- Complete Genre form plus the tracer-proven list under the original controller identity
- Duplicate-controller rejection proof and permission-first form/write routing
- PostgreSQL list, projected CRUD, lifecycle, atomic bulk, and retry-safety coverage
affects: [09-backend-admin-authentication-and-schema-pipeline, admin-api, phase-10-spa]
actuals:
tokens: 3703
tasks: 2
commits: 0
tech-stack:
added: []
patterns:
- "Tracer controllers are enriched in place; controller ID, model, route, and permission remain immutable"
- "Duplicate admin controller IDs fail activation before any last-write-wins replacement"
key-files:
created:
- ../fonoteka.go/plugins/golem15/fonoteka/controllers/genres/config_form.yaml
- ../fonoteka.go/plugins/golem15/fonoteka/models/genre/fields.yaml
- ../fonoteka.go/plugins/golem15/fonoteka/admin_genres_test.go
modified:
- ../fonoteka.go/plugins/golem15/fonoteka/admin.go
key-decisions:
- "The Phase 9 Genre tracer remains the one production controller; form capability was added without a parallel route or identity"
- "The tracer list and columns were already byte-equivalent to the tracked Winter source, so Task 2 added behavioral proof rather than rewriting them"
- "Genre slug remains lifecycle-derived and outside the writable form projection"
patterns-established:
- "Pattern: app-level duplicate registration tests invoke cabana activation with the same plugin twice and assert the first duplicate controller ID"
requirements-completed: [ADMIN-01, ADMIN-02, ADMIN-04]
coverage:
- id: D1
description: Genre form fields, layout hints, and locale keys compile in source order under the original tracer identity.
requirement: ADMIN-01
verification:
- kind: integration
ref: plugins/golem15/fonoteka/admin_genres_test.go#TestGenresAdminForm
status: pass
- kind: integration
ref: plugins/golem15/fonoteka/admin_genres_test.go#TestGenresAdminTracerIdentity
status: pass
human_judgment: false
- id: D2
description: Duplicate Genre registrations fail activation and unauthorized form/create/update requests are denied before Genre SQL.
requirement: ADMIN-01
verification:
- kind: integration
ref: plugins/golem15/fonoteka/admin_genres_test.go#TestGenresAdminDuplicateRegistration
status: pass
- kind: integration
ref: plugins/golem15/fonoteka/admin_genres_test.go#TestGenresAdminWritePermissions
status: pass
human_judgment: false
- id: D3
description: Genre list routes preserve complete source columns, actions, exact identifiers, empty arrays, stable order, and adjacent pages.
requirement: ADMIN-02
verification:
- kind: integration
ref: plugins/golem15/fonoteka/admin_genres_test.go#TestGenresAdminList
status: pass
- kind: integration
ref: plugins/golem15/fonoteka/admin_genres_test.go#TestGenresAdminEdges
status: pass
human_judgment: false
- id: D4
description: Genre CRUD projects form fields, derives slug through lifecycle hooks, and rejects protected request keys.
requirement: ADMIN-04
verification:
- kind: integration
ref: plugins/golem15/fonoteka/admin_genres_test.go#TestGenresAdminCRUD
status: pass
human_judgment: false
- id: D5
description: Genre bulk deletion validates empty input, normalizes duplicates, rolls back mixed selections, runs AfterDelete, and is retry-safe.
requirement: ADMIN-04
verification:
- kind: integration
ref: plugins/golem15/fonoteka/admin_genres_test.go#TestGenresAdminBulk
status: pass
human_judgment: false
duration: 2h 28m
completed: 2026-09-26
status: complete
plan_head_before: e6d013717faf3d4ac1e63036877688ca0cbfc128
plan_head_after: e6d013717faf3d4ac1e63036877688ca0cbfc128
---
# Phase 9 Plan 08: Complete Genres Controller Summary
**The production Genre tracer now serves the complete Winter form and its existing full list while preserving one permission-gated identity and inheriting shared CRUD/bulk guarantees.**
## Performance
- **Duration:** 2h 28m
- **Started:** 2026-09-25T22:34:00Z
- **Completed:** 2026-09-26T01:02:16Z
- **Tasks:** 2
- **Files modified:** 4
## Accomplishments
- Added the complete strict Genre form and field assets without changing the tracer controller ID, model, route, permission, or registry entry.
- Proved duplicate controller registration fails activation and denied form/write requests cannot reach Genre SQL.
- Proved source-complete list behavior plus projected CRUD, slug lifecycle, atomic rollback, delete hooks, duplicate normalization, and retry-safe bulk deletion.
## TDD Gate Compliance
`f74acad` established failing complete Genre contracts before `c62baaa` added the form assets. `40c4c45` finalized the real lifecycle fixture; the complete `^TestGenresAdmin` suite passes.
## Task Commits
1. **Task 1: Expand the Genre tracer to complete form parity** - `f74acad` (test, fonoteka.go), `c62baaa` (feat, fonoteka.go)
2. **Task 2: Complete Genres list and exercise shared record behavior** - `f74acad` (test, fonoteka.go), `40c4c45` (test, fonoteka.go)
The framework repository required no production change, so its measured commit count is zero. Fonoteka commits span `f74acad..40c4c45`.
## Files Created/Modified
- `fonoteka.go/plugins/golem15/fonoteka/controllers/genres/config_form.yaml` - complete Winter form-controller contract
- `fonoteka.go/plugins/golem15/fonoteka/models/genre/fields.yaml` - name and description fields with all layout hints
- `fonoteka.go/plugins/golem15/fonoteka/admin_genres_test.go` - identity, security, schema, list, CRUD, lifecycle, and bulk acceptance suite
- `fonoteka.go/plugins/golem15/fonoteka/admin.go` - embeds the new Genre form assets
## Decisions Made
- Enriched `genresAdminController` in place. No second controller or route was introduced.
- Left `config_list.yaml` and `columns.yaml` unchanged because the Phase 9 tracer already carried every tracked source declaration.
- Kept slug out of the form projection; `Genre.BeforeValidate` owns initial slug normalization.
## Deviations from Plan
None - the complete source list was already present from the tracer, and the plan executed by adding form parity plus the required behavioral evidence.
## Issues Encountered
The bulk lifecycle fixture initially omitted the Albums table's required `collection_id`; the test was corrected to use an isolated real collection before acceptance was rerun. No production change was required.
`ADMIN-01`, `ADMIN-02`, and `ADMIN-04` remain pending because later Phase 9 plans also declare them.
## User Setup Required
None - no external service configuration required.
## Next Phase Readiness
Ready for 09-09 and 09-10. Genres and Artists are complete Wave 7 catalog controllers.
## Self-Check: PASSED
- FOUND: `fonoteka.go` commits `f74acad`, `c62baaa`, and `40c4c45`
- FOUND: Genre form controller and fields assets; original list identity unchanged
- PASSED: `GOCACHE=/tmp/summercms-go-build go test ./plugins/golem15/fonoteka -run '^TestGenresAdmin' -count=1`
---
*Phase: 09-backend-admin-authentication-and-schema-pipeline*
*Completed: 2026-09-26*