147 lines
9.5 KiB
Markdown
147 lines
9.5 KiB
Markdown
---
|
|
phase: 09-backend-admin-authentication-and-schema-pipeline
|
|
plan: 08
|
|
type: execute
|
|
wave: 7
|
|
depends_on: [09-06]
|
|
files_modified:
|
|
- ../fonoteka.go/plugins/golem15/fonoteka/controllers/genres_admin_controller.go
|
|
- ../fonoteka.go/plugins/golem15/fonoteka/controllers/genres/config_form.yaml
|
|
- ../fonoteka.go/plugins/golem15/fonoteka/controllers/genres/config_list.yaml
|
|
- ../fonoteka.go/plugins/golem15/fonoteka/models/genre/fields.yaml
|
|
- ../fonoteka.go/plugins/golem15/fonoteka/models/genre/columns.yaml
|
|
- ../fonoteka.go/plugins/golem15/fonoteka/admin_genres_test.go
|
|
autonomous: true
|
|
requirements: [ADMIN-01, ADMIN-02, ADMIN-04]
|
|
estimate:
|
|
tokens: 15000
|
|
raw_tokens: 15000
|
|
tasks: 2
|
|
confidence: low
|
|
must_haves:
|
|
truths:
|
|
- "The tracer Genre path expands to complete D-05/D-06 form/list parity without changing its proven controller ID, route, permission, or registry wiring."
|
|
- "Genre schema collections and record lists obey ADMIN-01/02 empty/null/single/equality/adjacency/order/encoding rules exactly."
|
|
- "Genre CRUD/bulk operations use D-13 Fill/Validate/hooks, protected-field projection, and ADMIN-04 duplicate/empty/idempotency/rollback/concurrency semantics."
|
|
artifacts:
|
|
- path: "../fonoteka.go/plugins/golem15/fonoteka/controllers/genres_admin_controller.go"
|
|
provides: "Completed tracer-derived Genres controller"
|
|
- path: "../fonoteka.go/plugins/golem15/fonoteka/models/genre/fields.yaml"
|
|
provides: "Complete genre form schema"
|
|
- path: "../fonoteka.go/plugins/golem15/fonoteka/admin_genres_test.go"
|
|
provides: "Genre parity and inherited behavior coverage"
|
|
key_links:
|
|
- from: "controllers/genres_admin_controller.go"
|
|
to: "tracer controller registry entry"
|
|
via: "same exact immutable controller ID and permission mapping"
|
|
- from: "controllers/genres/config_form.yaml"
|
|
to: "models/genre/fields.yaml"
|
|
via: "strict embedded model asset path"
|
|
prohibitions:
|
|
- "[flagged-unverified] Expanding the Genre tracer must not create a second route/controller identity or weaken the permission that protected the tracer path."
|
|
---
|
|
|
|
## Phase Goal
|
|
|
|
**As a** backend administrator, **I want to** authenticate separately and manage resources described by Winter-shaped schemas, **so that** the administration surface stays permission-gated and reusable without coupling it to frontend users.
|
|
|
|
<objective>
|
|
Complete the tracer-derived Genres controller with full form/list parity and shared write behavior.
|
|
|
|
Purpose: Preserve the architecture proven in Plan 01 while filling every source schema and lifecycle behavior for Genres.
|
|
Output: Complete Genre embedded assets, unchanged registry identity, and assembled edge/CRUD/bulk tests.
|
|
</objective>
|
|
|
|
<execution_context>
|
|
@/home/jin/.codex/gsd-core/workflows/execute-plan.md
|
|
@/home/jin/.codex/gsd-core/templates/summary.md
|
|
</execution_context>
|
|
|
|
<context>
|
|
@.planning/PROJECT.md
|
|
@.planning/ROADMAP.md
|
|
@.planning/STATE.md
|
|
@.planning/phases/09-backend-admin-authentication-and-schema-pipeline/09-CONTEXT.md
|
|
@.planning/phases/09-backend-admin-authentication-and-schema-pipeline/09-01-SUMMARY.md
|
|
@.planning/phases/09-backend-admin-authentication-and-schema-pipeline/09-06-SUMMARY.md
|
|
@../fonoteka.go/plugins/golem15/fonoteka/models/genre.go
|
|
@cabana/form_schema.go
|
|
@cabana/list_schema.go
|
|
@cabana/crud.go
|
|
</context>
|
|
|
|
## Artifacts this phase produces
|
|
|
|
- Completed `fonoteka.GenresAdminController`
|
|
- Genre `config_form.yaml`, complete `config_list.yaml`, `fields.yaml`, and `columns.yaml`
|
|
- Assembled `TestGenresAdmin*` schema, registry, list, CRUD, and bulk suite
|
|
|
|
<tasks>
|
|
|
|
<task type="auto" tdd="true">
|
|
<name>Task 1: Expand the Genre tracer to complete form parity</name>
|
|
<files>../fonoteka.go/plugins/golem15/fonoteka/controllers/genres_admin_controller.go, ../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</files>
|
|
<read_first>/media/nvme/dev/golem15/fonoteka/plugins/golem15/fonoteka/controllers/genres/config_form.yaml, /media/nvme/dev/golem15/fonoteka/plugins/golem15/fonoteka/models/genre/fields.yaml, ../fonoteka.go/plugins/golem15/fonoteka/controllers/genres_admin_controller.go, ../fonoteka.go/plugins/golem15/fonoteka/models/genre.go, cabana/registry.go</read_first>
|
|
<behavior>
|
|
- Test 1: all source Genre form fields/layout/locale hints compile in stable order with explicit empty/single semantics.
|
|
- Test 2: activation retains one exact Genre controller ID/route and rejects duplicate IDs, routes, model registrations, or conflicting permissions.
|
|
- Test 3: form/create/update paths use the same permission-first registry wiring established by the tracer.
|
|
</behavior>
|
|
<action>Add the complete Genre form assets and model metadata to the production tracer controller. Reuse its controller ID, model factory, route, and permission declarations; make the registry reject any duplicate or conflicting registration instead of last-write-wins replacement. Preserve every source field and hint, cached locale key, declaration order, and strict validation rule.</action>
|
|
<verify>
|
|
<automated>(cd ../fonoteka.go && go test ./plugins/golem15/fonoteka -run '^TestGenresAdmin(Form|TracerIdentity|DuplicateRegistration|WritePermissions)$' -count=1)</automated>
|
|
<fails_when>The command exits non-zero, reports no matching test, a source form element is absent, the tracer identity/permission changes, duplicate registration overwrites an entry, or permission checks run after provider/database work.</fails_when>
|
|
</verify>
|
|
<acceptance_criteria>Genres form behavior is complete while the single tracer-proven controller identity and security ordering remain intact.</acceptance_criteria>
|
|
<done>The Genre tracer is enriched into the complete form/write controller without architectural replacement.</done>
|
|
</task>
|
|
|
|
<task type="auto" tdd="true">
|
|
<name>Task 2: Complete Genres list and exercise shared record behavior</name>
|
|
<files>../fonoteka.go/plugins/golem15/fonoteka/controllers/genres/config_list.yaml, ../fonoteka.go/plugins/golem15/fonoteka/models/genre/columns.yaml, ../fonoteka.go/plugins/golem15/fonoteka/controllers/genres_admin_controller.go, ../fonoteka.go/plugins/golem15/fonoteka/admin_genres_test.go</files>
|
|
<read_first>/media/nvme/dev/golem15/fonoteka/plugins/golem15/fonoteka/controllers/genres/config_list.yaml, /media/nvme/dev/golem15/fonoteka/plugins/golem15/fonoteka/models/genre/columns.yaml, ../fonoteka.go/plugins/golem15/fonoteka/controllers/genres/config_list.yaml, ../fonoteka.go/plugins/golem15/fonoteka/models/genre/columns.yaml, cabana/query.go, cabana/crud.go</read_first>
|
|
<behavior>
|
|
- Test 1: all source Genre list columns/filters/actions/defaults are present and stable after expansion from the tracer slice.
|
|
- Test 2: empty/single/equal/adjacent records and exact identifier/typed encoding behavior match ADMIN-02.
|
|
- Test 3: Genre record and bulk routes inherit ADMIN-04 projection, hooks, normalization, stable order, idempotency, rollback, and concurrency.
|
|
</behavior>
|
|
<action>Replace only the tracer's intentionally narrow list assets with the complete tracked Genre list/column declarations, retaining its proven route and middleware. Execute schema/list/CRUD/bulk through the shared cabana services and add assembled edge fixtures rather than controller-local query or persistence logic.</action>
|
|
<verify>
|
|
<automated>(cd ../fonoteka.go && go test ./plugins/golem15/fonoteka -run '^TestGenresAdmin(List|Edges|CRUD|Bulk)$' -count=1)</automated>
|
|
<fails_when>The command exits non-zero, reports no matching test, any source list declaration is missing, tracer middleware changes, ADMIN-02 edges drift, or record/bulk work bypasses shared lifecycle and transaction behavior.</fails_when>
|
|
</verify>
|
|
<acceptance_criteria>The Genre tracer path now carries the full list and ADMIN-04 behavior without losing its end-to-end guarantees.</acceptance_criteria>
|
|
<done>Genres form, list, CRUD, and bulk behavior is complete and edge-tested.</done>
|
|
</task>
|
|
|
|
</tasks>
|
|
|
|
<threat_model>
|
|
## Trust Boundaries
|
|
|
|
| Boundary | Description |
|
|
|----------|-------------|
|
|
| plugin registration→route table | Controller identity, permission, and model provider enter the framework registry |
|
|
|
|
## STRIDE Threat Register
|
|
|
|
| Threat ID | Category | Component | Severity | Disposition | Mitigation Plan |
|
|
|-----------|----------|-----------|----------|-------------|-----------------|
|
|
| T-09-14 | Spoofing / Elevation | duplicate controller registry entries | high | mitigate | Reject duplicate IDs/routes/models and conflicting permission maps at activation; assert tracer identity and denial ordering remain exact. |
|
|
| T-09-SC | Tampering | npm/pip/cargo installs | high | mitigate | No npm/pip/cargo install occurs; existing Go dependencies only, so the package-legitimacy gate remains closed. |
|
|
</threat_model>
|
|
|
|
<verification>
|
|
Run `(cd ../fonoteka.go && go test ./plugins/golem15/fonoteka -run '^TestGenresAdmin' -count=1)`; it fails on non-zero exit, zero matched tests, duplicate-registry acceptance, tracer contract drift, source omission, or inherited edge/lifecycle failure.
|
|
</verification>
|
|
|
|
<success_criteria>
|
|
- The one production Genre tracer becomes the complete controller rather than a parallel implementation.
|
|
- Duplicate registry identity cannot replace its model, route, or permissions.
|
|
- Complete form/list source parity and ADMIN-01/02/04 edges pass on assembled routes.
|
|
</success_criteria>
|
|
|
|
<output>
|
|
Create `.planning/phases/09-backend-admin-authentication-and-schema-pipeline/09-08-SUMMARY.md` when done.
|
|
</output>
|