Files
summercms/.planning/phases/09-backend-admin-authentication-and-schema-pipeline/09-DISCUSSION-LOG.md
2026-09-23 10:24:22 +02:00

7.3 KiB

Phase 9: Backend admin authentication and schema pipeline - Discussion Log

Audit trail only. Do not use as input to planning, research, or execution agents. Decisions are captured in CONTEXT.md — this log preserves the alternatives considered.

Date: 2026-09-23 Phase: 09-backend-admin-authentication-and-schema-pipeline Areas discussed: Admin identity and login, Schema pipeline shape, Admin CRUD API contract, Relation manager and settings


Admin identity and login

Option Description Selected
Winter-shaped tables backend_users + backend_user_roles, groups skipped, is_superuser and role codes kept ✓
Lean admin model One summer_admins table with role string and permissions JSON
Reuse frontend users table with a flag is_backend + role on users

User's choice: Winter-shaped tables

Option Description Selected
JWT via a backend bouncer guard Second guard beside jwt, own secret and audience, reuses Phase 7 mint/verify/blacklist ✓
Cookie sessions with scs HttpOnly cookie, Postgres session store, CSRF
You decide

User's choice: JWT via a backend bouncer guard

Option Description Selected
Winter strings with wildcard HasPermissions in registerPermissions shape, is_superuser, role JSON, .* prefix match, RequiredPermissions() enforced by framework ✓
Flat permission list, no wildcards Exact match only
You decide

User's choice: Winter strings with wildcard

Option Description Selected
Console command summer admin:create + admin:reset-password ✓
Seeded from config Boot-time superuser from YAML/env
Both Command canonical, env seed opt-in

User's choice: Console command


Schema pipeline shape

Option Description Selected
Winter layout config_form/config_list point at models//fields.yaml and columns.yaml; scaffold updated ✓
Scaffold layout Keep controllers//fields.yaml as Phase 4 emits
You decide

User's choice: Winter layout

Option Description Selected
Typed schema, Winter key names Go structs per field type, unknown keys fail, Winter spelling in JSON ✓
Pass-through map Generic map served as-is
Typed schema, normalized names snake_case house style

User's choice: Typed schema, Winter key names

Option Description Selected
Resolved server-side phrasebook resolves labels in the admin's locale; SPA gets strings ✓
Raw keys plus a lang bundle endpoint SPA resolves locally
Both fields label and labelKey side by side

User's choice: Resolved server-side

Option Description Selected
Options provider interface on the model DropdownOptions(field) []Option; static YAML maps also work ✓
Registry keyed by method name Controller registers a map of func by name
You decide

User's choice: Options provider interface on the model


Admin CRUD API contract

Option Description Selected
/_admin/api/v1, plain JSON, no envelope Plain resource bodies, {message, errors} errors
Reuse the fonoteka house envelope Same helpers as /_fonoteka/api/v1
You decide

User's choice: Free text: "Do you really recommend 1? Our chance to introduce nice and consistent api layer." Claude proposed a framework-wide layer (plugin-namespaced paths, one envelope with a fixed error-code vocabulary, one list contract, one verb set, relation endpoints under the record, swag-annotated framework package). User: "Yes, let's proceed with that." Notes: Recorded as D-09 to D-11.

Option Description Selected
Winter list features only search, sort, dir, page, recordsPerPage, relation columns
Add per-column filters filter[column]=value exact matches
You decide

User's choice: Free text: "Filters in Winter are done with config_filters.yaml we need filters like that here." Claude found the user and journal plugins' config_filter.yaml files (switch, daterange, model-backed scope) and asked about scope coverage and raw SQL conditions:. User: "Port 3 shapes now, note for future phases that this will be extended and all shapes will be introduced in time. Model scope methods instead of SQL strings are fully acceptable." Notes: Recorded as D-12; remaining scope types deferred.

Option Description Selected
Optional interfaces on the controller Type-asserted hooks with admin principal in context; bulk delete per record ✓
Struct of func fields Optional func fields on AdminController
You decide

User's choice: Optional interfaces on the controller

Option Description Selected
Port the email mapping Admin email must match exactly one frontend user; reuse its active collection; 422 otherwise ✓
Explicit collection picker SPA header on every request
Both Mapping default, header override for superusers

User's choice: Port the email mapping


Relation manager and settings

Option Description Selected
config_relation.yaml as a first-class schema Typed relation schema; type: relation-manager replaces partial ✓
Keep partial as an alias Map partial to relation manager
You decide

User's choice: config_relation.yaml as a first-class schema

Option Description Selected
Pivot fields stamped by the framework hook RelationBeforeLink stamps role, granted_at, granted_by; unlink deletes pivot ✓
Bare pivot insert Only the two foreign keys
You decide

User's choice: Pivot fields stamped by the framework hook

Option Description Selected
HasSettings capability + singleton model registerSettings shape, /settings/{code} GET/PUT via Fillable ✓
Settings as an ordinary admin controller Form with no list, hand-written per page
You decide

User's choice: HasSettings capability + singleton model

Option Description Selected
HasNavigation in Winter's shape, URL becomes a route key url replaced by controller ID; /navigation filtered by permissions ✓
Winter shape with literal URLs Keep url strings
You decide

User's choice: HasNavigation in Winter's shape, URL becomes a route key


Claude's Discretion

  • Package naming and layout for the admin API and schema packages.
  • YAML parse timing (boot vs lazy), rules: in fields.yaml vs model Rules().
  • Admin login throttling and password policy.
  • Soft-deleted rows in admin lists; settings row creation timing; relation candidate pagination.

Deferred Ideas

  • Remaining Winter filter scope types.
  • backend_user_groups, preferences, access logs.
  • Policy-based row/field-level permissions.
  • Boot-time admin seed from environment.