docs(19.6.1-04): complete gap-closure plan

This commit is contained in:
Jakub Zych
2026-10-22 13:37:26 +02:00
parent e62086084b
commit 6bd2506db6
2 changed files with 184 additions and 3 deletions

View File

@@ -1423,7 +1423,7 @@ Plans:
2. Privilege rules hold on the server: only a superuser can create, edit or grant superuser; an admin cannot raise their own role or permissions; the last active superuser cannot be deactivated, demoted or deleted.
3. The record-action seam on the Administrators list is usable by plugins (19.7's link action), and unit tests cover the privilege rules.
**Plans:** 4 plans
**Plans:** 4/4 plans executed
Plans:
**Wave 1**
@@ -1436,7 +1436,7 @@ Plans:
- [x] 19.6.1-03-PLAN.md — unit, Postgres and SPA tests for every rule (incl. the held-lock last-superuser race), the seam and D-21, plus the check-phase19.6.1.sh gate
**Wave 4** *(gap closure)*
- [ ] 19.6.1-04-PLAN.md — close CR-01 (role-code capture onto code-declared grants) and WR-03 (wrap contributed Administrators actions with guardOutranked)
- [x] 19.6.1-04-PLAN.md — close CR-01 (role-code capture onto code-declared grants) and WR-03 (wrap contributed Administrators actions with guardOutranked)
### Phase 19.7: Generic MCP module (INSERTED)
@@ -1591,7 +1591,7 @@ Phases execute in numeric order: 1 → 2 → 3 → 4 → 5 → 6 → 7 → 8 →
| 19.4.1. Early public demo on demo.summercms.io | 5/5 | In Progress| |
| 19.5. Social login in sm-user-plugin | 5/5 | Complete | 2026-10-21 |
| 19.6. Two-factor auth and device flow in sm-user-plugin | 0/TBD | Not started | - |
| 19.6.1. Backend Administrators screen (INSERTED) | 3/3 | In Progress| |
| 19.6.1. Backend Administrators screen (INSERTED) | 4/4 | In Progress| |
| 19.7. Generic MCP module | 0/TBD | Not started | - |
| 19.8. Console commands overhaul (INSERTED) | 6/6 | In Progress| |
| 20. Demo instance with every shared plugin | 0/TBD | Not started | - |

View File

@@ -0,0 +1,181 @@
---
phase: 19.6.1-backend-administrators-screen
plan: 04
subsystem: auth
tags: [cabana, roles, administrators, privilege-ceiling, pact, postgres]
requires:
- phase: 19.6.1-01
provides: Roles and Administrators hooks, compileActionExtensions, guardOutranked, AdministratorsControllerID
- phase: 19.6.1-02
provides: permission locks and the Roles form that still posts a fillable code
- phase: 19.6.1-03
provides: screensEnv harness, TestRolesLifecycle, TestActionExtensionRun, check-phase19.6.1.sh
provides:
- refuseCodeDeclaredCode on Roles create and update so a submitted code with code-declared grants is 422 user.role.code_locked
- wrapAdministratorsContributedRun so cabana runs guardOutranked before a contributed Administrators Run
- TestRolesCodeDeclaredCodeRefused and TestActionExtensionOutranked on Postgres
- DOCKER_TESTS REQUIRE names for both tests
- AdminActionExtension docs that cabana, not the contributor, owns the outranking check
affects: [19.6.1 verify-work, 19.6 D-15, 19.7 link action on Administrators]
actuals:
tokens: 6357
tasks: 3
commits: 4
plan_head_before: 422bd1e01f4f3cb87252732eb273c14fbfcaa126
plan_head_after: e62086084b9d509b05b1e1eea510390753fe0ed8
tech-stack:
added: []
patterns:
- "Roles hooks consult rolePermissions of the submitted code, not only the stored one"
- "compileActionExtensions wraps contributed Administrators Runs in cabana so guardOutranked runs inside the action transaction"
key-files:
created: []
modified:
- modules/cabana/backend_roles_admin.go
- modules/cabana/action_extensions.go
- modules/cabana/action_extensions_test.go
- modules/cabana/roles_postgres_test.go
- modules/cabana/action_extensions_postgres_test.go
- modules/pact/capabilities.go
- modules/pact/README.md
- modules/cabana/README.md
- docs/backend/admin-controllers.md
- scripts/check-phase19.6.1.sh
key-decisions:
- "Roles create and update refuse any new code that rolePermissions attaches grants to, including when the editor is a superuser"
- "cabana wraps contributed Administrators Runs; guardOutranked stays unexported and contributors do not own the check"
patterns-established:
- "A code-declared system role cannot be created or captured through the Roles screen; 422 code_locked leaves the row unchanged"
- "A contribution to summercms.cabana.users is 403 user.outranked when the target outranks the caller, before Run"
requirements-completed: [SC-2, D-07, D-16, D-19]
coverage:
- id: D1
description: "Roles create and rename refuse a code that pact.Permission.Roles attaches grants to (CR-01 / G-19.6.1-1)"
requirement: "D-16"
verification:
- kind: integration
ref: "modules/cabana/roles_postgres_test.go#TestRolesCodeDeclaredCodeRefused"
status: pass
human_judgment: false
- id: D2
description: "Contributed Administrators record actions run guardOutranked before Run (WR-03 / G-19.6.1-2)"
requirement: "D-19"
verification:
- kind: integration
ref: "modules/cabana/action_extensions_postgres_test.go#TestActionExtensionOutranked"
status: pass
human_judgment: false
- id: D3
description: "Phase docker gate REQUIREs both new Postgres tests by name"
requirement: "D-18"
verification:
- kind: other
ref: "bash scripts/check-phase19.6.1.sh --docker"
status: pass
human_judgment: false
- id: D4
description: "AdminActionExtension docs state that cabana applies user.outranked before Run"
requirement: "D-19"
verification:
- kind: unit
ref: "cmd/summer#TestDocsTree"
status: pass
- kind: other
ref: "go run ./cmd/summer docs:build --check"
status: pass
human_judgment: false
duration: 18 min
completed: 2026-10-22
status: complete
---
# Phase 19.6.1 Plan 04: Gap closure CR-01 and WR-03 Summary
**Roles create/rename cannot capture a code-declared code; cabana wraps contributed Administrators Runs with guardOutranked before the contributor runs**
## Performance
- **Duration:** 18 min
- **Started:** 2026-10-22T11:18:00Z
- **Completed:** 2026-10-22T11:36:05Z
- **Tasks:** 3
- **Files modified:** 10
## Accomplishments
- `refuseCodeDeclaredCode` on Roles create and update: a submitted code with code-declared grants is 422 `user.role.code_locked`, including for a superuser; a same-code save of a system role still succeeds
- `wrapAdministratorsContributedRun` in `compileActionExtensions`: a contribution to `AdministratorsControllerID` is 403 `user.outranked` when the target outranks the caller, and Run is not called
- `TestRolesCodeDeclaredCodeRefused` and `TestActionExtensionOutranked` are in `DOCKER_TESTS`; `scripts/check-phase19.6.1.sh --docker` passed
- pact/cabana/docs state that cabana, not the contributor, applies the Administrators outranking rule
## Task Commits
Each task was committed atomically:
1. **Task 1: refuse a Roles code-declared capture and wrap contributed Administrators Runs** - `068adaa` (fix)
2. **Task 2: Document the Administrators privilege rule on the D-14 seam** - `cb460b6` (docs)
3. **Task 3: Require the two new Postgres tests in the phase gate** - `e620860` (chore)
**Plan metadata:** (this commit) (docs: complete plan)
## Files Created/Modified
- `modules/cabana/backend_roles_admin.go` - `refuseCodeDeclaredCode` on create and update
- `modules/cabana/action_extensions.go` - wrap contributed Administrators Runs with `guardOutranked`
- `modules/cabana/action_extensions_test.go` - boot smoke still compiles a superuser principal
- `modules/cabana/roles_postgres_test.go` - `TestRolesCodeDeclaredCodeRefused`
- `modules/cabana/action_extensions_postgres_test.go` - `TestActionExtensionOutranked`
- `modules/pact/capabilities.go` - AdminActionExtension comment names `user.outranked`
- `modules/pact/README.md` - contribution to `summercms.cabana.users` is refused when the target outranks the caller
- `modules/cabana/README.md` - contributions targeting `AdministratorsControllerID` run `guardOutranked` before Run
- `docs/backend/admin-controllers.md` - cabana applies the outranking check before Run
- `scripts/check-phase19.6.1.sh` - DOCKER_TESTS REQUIRE both new names
## Decisions Made
- Roles create and update refuse any new code that `rolePermissions` attaches grants to, including when the editor is a superuser
- cabana wraps contributed Administrators Runs; `guardOutranked` stays unexported and contributors do not own the check
## Deviations from Plan
### Auto-fixed Issues
**1. [Safe resume] Interrupted executor left SUMMARY unwritten**
- **Found during:** Orchestrator resume after the Task spawn was cut off
- **Issue:** Tasks 1–2 were committed (`068adaa`, `cb460b6`) and the Task 3 gate-script edit was uncommitted; no SUMMARY existed. Re-dispatch would duplicate the privilege fixes.
- **Fix:** Closed out Task 3 and this SUMMARY on the main tree instead of spawning a second executor
- **Files modified:** `scripts/check-phase19.6.1.sh`, this SUMMARY
- **Verification:** named Postgres tests, docs checker, and `check-phase19.6.1.sh --docker` all passed
- **Committed in:** `e620860` (Task 3) and the metadata commit
**2. [Plan files] `action_extensions_test.go` needed a superuser principal**
- **Found during:** Task 1
- **Issue:** wrapping Administrators Runs made the existing boot smoke fail unless the compile-time principal is a superuser
- **Fix:** keep the boot smoke callable with a superuser principal (noted in the Task 1 commit body)
- **Files modified:** `modules/cabana/action_extensions_test.go`
- **Verification:** `go test -short ./modules/cabana/...` passed
- **Committed in:** `068adaa` (Task 1)
---
**Total deviations:** 2 auto-fixed (safe resume, boot-smoke principal)
**Impact on plan:** No scope change. CR-01 and WR-03 shipped as specified.
## Issues Encountered
The first executor spawn was interrupted after Tasks 1–2 committed. Close-out completed Task 3 and this SUMMARY without re-applying the hook/wrap changes.
## User Setup Required
None - no external service configuration required.
## Next Phase Readiness
Phase 19.6.1 gap closure is on disk. Ready for phase verification / UAT re-check of G-19.6.1-1 and G-19.6.1-2.
---
*Phase: 19.6.1-backend-administrators-screen*
*Completed: 2026-10-22*