docs(09-11): complete admin metadata and settings plan

This commit is contained in:
Jakub Zych
2026-09-26 23:08:06 +02:00
parent 10ca7a02e3
commit 13760e3a1a
3 changed files with 213 additions and 12 deletions

View File

@@ -0,0 +1,200 @@
---
phase: 09-backend-admin-authentication-and-schema-pipeline
plan: 11
subsystem: admin
tags: [permissions, navigation, settings, postgres, authorization, metadata]
requires:
- phase: 09-backend-admin-authentication-and-schema-pipeline
provides: Backend guard, compiled controllers, forms, lists, CRUD, and relations
provides:
- Exact Fonoteka permission catalog with source role assignments
- Stable permission-filtered navigation and settings discovery endpoints
- Localized singleton settings schema plus transactional GET/PUT service
affects: [09-backend-admin-authentication-and-schema-pipeline, phase-10-spa, admin-api]
actuals:
tokens: 30000
tasks: 3
commits: 3
tech-stack:
added: []
patterns:
- "Plugin permission contributions are compiled once and validate every controller, relation, navigation, and settings reference"
- "Backend role defaults are merged at principal resolution without mutating role rows"
- "Settings replay compares projected values and skips persistence when unchanged"
key-files:
created:
- cabana/navigation.go
- cabana/settings.go
- cabana/metadata_settings_test.go
- ../fonoteka.go/plugins/golem15/fonoteka/admin_permissions.go
- ../fonoteka.go/plugins/golem15/fonoteka/admin_navigation.go
- ../fonoteka.go/plugins/golem15/fonoteka/admin_settings.go
- ../fonoteka.go/plugins/golem15/fonoteka/models/settings/fields.yaml
- ../fonoteka.go/plugins/golem15/fonoteka/admin_metadata_test.go
- ../fonoteka.go/plugins/golem15/fonoteka/admin_settings_test.go
modified:
- cabana/registry.go
- cabana/http.go
- cabana/auth.go
- bouncer/context.go
- pact/capabilities.go
- ../fonoteka.go/plugins/golem15/fonoteka/admin.go
key-decisions:
- "Developer receives all seven source-declared Fonoteka permissions; publisher receives no implicit Fonoteka grant and superuser retains framework bypass"
- "Backend principals carry an explicit domain marker, preventing a frontend principal with matching identifiers or grants from entering Cabana"
- "Missing singleton GET returns schema defaults without creating a row; first valid PUT creates ID 1 and identical replay leaves updated_at unchanged"
patterns-established:
- "Pattern: filter metadata entries before constructing response values so denied labels and targets never serialize"
- "Pattern: compile settings writable fields as the intersection of schema scalars, model columns, and Fillable"
requirements-completed: [AUTH-08, ADMIN-05]
coverage:
- id: D1
description: "The exact permission catalog is unique, role-assigned, reference-valid, wildcard-aware, and restricted to backend principals."
requirement: AUTH-08
verification:
- kind: integration
ref: plugins/golem15/fonoteka/admin_metadata_test.go#TestAdminMetadataPermissions
status: pass
- kind: integration
ref: plugins/golem15/fonoteka/admin_metadata_test.go#TestAdminMetadataFiltering
status: pass
- kind: integration
ref: plugins/golem15/fonoteka/admin_metadata_test.go#TestAdminMetadataRejectsFrontendPrincipal
status: pass
human_judgment: false
- id: D2
description: "Navigation and settings discovery preserve source metadata, stable ordering, localization keys, non-null empty arrays, and whole-entry permission filtering."
requirement: AUTH-08
verification:
- kind: integration
ref: plugins/golem15/fonoteka/admin_metadata_test.go#TestAdminMetadataNavigation
status: pass
- kind: integration
ref: plugins/golem15/fonoteka/admin_metadata_test.go#TestAdminMetadataSettingsList
status: pass
- kind: integration
ref: plugins/golem15/fonoteka/admin_metadata_test.go#TestAdminMetadataFiltering
status: pass
human_judgment: false
- id: D3
description: "Fonoteka settings expose a localized required schema and side-effect-free missing read followed by singleton creation and idempotent replay."
requirement: ADMIN-05
verification:
- kind: integration
ref: plugins/golem15/fonoteka/admin_settings_test.go#TestAdminSettingsSchema
status: pass
- kind: integration
ref: plugins/golem15/fonoteka/admin_settings_test.go#TestAdminSettingsMissingRead
status: pass
- kind: integration
ref: plugins/golem15/fonoteka/admin_settings_test.go#TestAdminSettingsIdempotentUpdate
status: pass
human_judgment: false
- id: D4
description: "Settings PUT is permission-first, schema-projected, Fill/Validate-backed, transactional, and rolls back invalid required or typed values."
requirement: ADMIN-05
verification:
- kind: integration
ref: plugins/golem15/fonoteka/admin_settings_test.go#TestAdminSettingsPermissionOrder
status: pass
- kind: integration
ref: plugins/golem15/fonoteka/admin_settings_test.go#TestAdminSettingsProjection
status: pass
- kind: integration
ref: plugins/golem15/fonoteka/admin_settings_test.go#TestAdminSettingsValidation
status: pass
- kind: integration
ref: plugins/golem15/fonoteka/admin_settings_test.go#TestAdminSettingsRollback
status: pass
human_judgment: false
duration: 1h 15m
completed: 2026-09-26
status: complete
---
# Phase 9 Plan 11: Permissions, Navigation, and Singleton Settings Summary
**Cabana now compiles a source-exact permission catalog, exposes only authorized discovery metadata, and serves validated replay-safe singleton settings.**
## Performance
- **Duration:** 1h 15m
- **Started:** 2026-09-26T21:35:00+02:00
- **Completed:** 2026-09-26T22:50:00+02:00
- **Tasks:** 3
- **Files modified:** 21
## Accomplishments
- Registered all seven Fonoteka permissions with developer-only source assignments and activation-time reference validation.
- Added stable localized navigation/settings discovery that removes unauthorized entries before serialization.
- Added permission-first settings schema/GET/PUT routes with default-only missing reads, projected Fill/Validate writes, rollback, and idempotent replay.
- Added an explicit backend-principal domain marker so frontend identities cannot satisfy Cabana authorization.
## Task Commits
1. **Task 1: Register exact permissions and validate every operation reference** - `10ca7a0`, `fdf1d24`
2. **Task 2: Serve exact permission-filtered navigation and settings metadata** - `10ca7a0`, `c0a7043`
3. **Task 3: Serve permissioned singleton settings through Fill and Validate** - `10ca7a0`, `fdf1d24`, `c0a7043`
## Decisions Made
- Role assignments are merged when a backend principal is resolved, avoiding boot-time database mutation while preserving exact plugin defaults.
- The parent Fonoteka navigation entry is visible when the principal can use at least one child, even when grants are exact rather than wildcard.
- Required boolean settings validate request presence independently from the model value, because `false` is a valid supplied value.
## Deviations from Plan
### Auto-fixed Issues
**1. [Rule 2 - Missing Critical] Added explicit backend principal domain marker**
- **Found during:** Task 1 identity isolation review.
- **Issue:** A raw `bouncer.Principal` had no provenance marker, so a directly injected frontend principal with copied grants was indistinguishable after middleware.
- **Fix:** Added `Principal.Backend`, set it only during backend-user resolution, and required it at Cabana authorization/metadata boundaries.
- **Verification:** Frontend-audience token and unmarked-principal tests fail closed.
- **Committed in:** `10ca7a0`.
**2. [Rule 1 - Bug] Rejected nested values for known required settings fields**
- **Found during:** Task 3 rollback verification.
- **Issue:** A nested value for a known scalar was dropped by projection, allowing an unchanged 200 response instead of validation failure.
- **Fix:** Required-input validation now rejects nested values before Fill and the transaction preserves prior data.
- **Verification:** `TestAdminSettingsRollback` passes against PostgreSQL.
- **Committed in:** `10ca7a0`.
---
**Total deviations:** 2 auto-fixed (1 security boundary, 1 validation bug)
**Impact on plan:** Both fixes enforce the plan's stated identity and rollback guarantees without expanding product scope.
## Issues Encountered
- The fresh migration seeds settings row ID 1, while ADMIN-05 also requires missing-row behavior. Tests explicitly delete the singleton before proving side-effect-free GET and first PUT creation.
## User Setup Required
None - no external service configuration required.
## Next Phase Readiness
- All Phase 9 runtime capabilities are implemented.
- Ready for 09-12 whole-phase security, PostgreSQL, OpenAPI, and evidence gates.
## Self-Check: PASSED
- `go test ./cabana -count=1`
- `go test ./plugins/golem15/fonoteka -run '^(TestAdminMetadata|TestAdminSettings)' -count=1`
---
*Phase: 09-backend-admin-authentication-and-schema-pipeline*
*Completed: 2026-09-26*