Files
summercms/.planning/phases/09-backend-admin-authentication-and-schema-pipeline/09-SECURITY-REVIEW.md
Jakub Zych 92fb6e323f docs(09-12): record the phase 9 acceptance evidence
- Security review names the test that fails if each high control is removed.
- Validation rows now point at the phase gate commands.
- Roadmap shows 12/12 plans executed.
2026-09-27 03:03:09 +02:00

5.2 KiB

phase, reviewed, threats_open
phase reviewed threats_open
09 2026-09-27 0

Phase 09 Security Review

Fresh review of the backend admin surface after plan 09-12. A high threat is mitigated only when the named test fails if that control is removed.

Threat Severity Disposition Production control Executable evidence Result
T-09-01 high mitigated Separate frontend and backend secrets, required audience, and distinct guard registries go test ./bouncer -run '^TestPhase09GuardIsolation$' -count=1 pass
T-09-02 high mitigated Backend guard, then controller lookup, then permission, before schema or query work go test ./cabana -run '^TestPhase09PermissionMatrix$' -count=1 pass
T-09-03 high mitigated Auth logs record outcome, method, path, remote, and admin id only go test ./cabana -run '^TestPhase09SecurityCoverage$' -count=1 pass
T-09-04 medium mitigated Create and reset commands validate role codes and do not echo passwords `go test ./cabana -run 'Test(AdminCreate ResetPassword)' -count=1`
T-09-05 high mitigated Strict form compiler rejects unknown keys, types, partials, and providers `go test ./cabana -run '^TestFormSchema(Compile Rejects)' -count=1`
T-09-06 medium mitigated Schema locale comes from the request, not a shared cache of translated text go test ../fonoteka.go/plugins/golem15/fonoteka -run '^TestPhase09AssembledAcceptance$' -count=1 pass
T-09-07 high mitigated List identifiers are compiled allowlists; injected sort and path ids fail closed go test ./cabana -run '^TestPhase09SecurityCoverage$' -count=1 pass
T-09-08 medium mitigated Page size must be a compiled option; adjacent pages stay stable go test ../fonoteka.go/plugins/golem15/fonoteka -run '^TestPhase09AssembledAcceptance$' -count=1 pass
T-09-09 high mitigated Writable projection drops protected, unknown, case-variant, and nested keys go test ./cabana -run '^TestPhase09SecurityCoverage$' -count=1 pass
T-09-10 high mitigated Hook failure aborts the create and leaves no row go test ./cabana -run '^TestPhase09SecurityCoverage$' -count=1 pass
T-09-11 high mitigated Album lookup is collection-scoped on the server go test ../fonoteka.go/plugins/golem15/fonoteka -run '^TestAlbumsAdmin(CollectionMatch|CrossCollection)$' -count=1 owned by 09-06; not re-run in 09-12
T-09-12 high mitigated Normalized email association requires exactly one active match go test ../fonoteka.go/plugins/golem15/fonoteka -run '^TestAlbumsAdminAmbiguousEmail$' -count=1 owned by 09-06; not re-run in 09-12
T-09-13 high mitigated Every generated artists route is inside the backend group and denies an empty grant go test ../fonoteka.go/plugins/golem15/fonoteka -run '^TestPhase09Security' -count=1 pass
T-09-14 high mitigated Duplicate controller ids and routes fail activation go test ./party -run '^TestActivateDuplicateIDRejected$' -count=1 and go test ../fonoteka.go/plugins/golem15/fonoteka -run '^TestStylesAdminDuplicateRegistration$' -count=1 owned by 09-08; not re-run in 09-12
T-09-15 medium mitigated Style option values keep their YAML kinds go test ../fonoteka.go/plugins/golem15/fonoteka -run '^TestStylesAdminTypedOptions$' -count=1 owned by 09-09; not re-run in 09-12
T-09-16 high mitigated Relation mutations reject unknown pivot fields go test ./cabana -run '^TestPhase09SecurityCoverage$' -count=1 pass
T-09-17 high mitigated Relation reads and writes require the operation permission before SQL `go test ../fonoteka.go/plugins/golem15/fonoteka -run '^TestCollectionsAdmin(RelationPermissions CrossScope
T-09-18 high mitigated Settings writes are permission-first and fillable-only go test ../fonoteka.go/plugins/golem15/fonoteka -run '^TestAdminSettings' -count=1 owned by 09-11; not re-run in 09-12
T-09-19 medium mitigated Navigation and settings lists are filtered to granted entries go test ./cabana -run '^TestPhase09PermissionMatrix$' -count=1 pass
T-09-20 high mitigated The phase gate rejects skipped tests and zero-test runs scripts/check-phase9.sh --self-test pass
T-09-21 high mitigated Fresh admin migration rollback keeps other histories, and OpenAPI lists every D-09 route scripts/check-phase9.sh --postgres and scripts/check-phase9.sh --openapi pass
T-09-SC high mitigated No package was added. OpenAPI generation reuses pinned swag v1.16.6 and openapi-typescript 7.13.0 scripts/check-phase9.sh --openapi pass

Residual risk

Browser rendering of these schemas is Phase 10. This review does not claim a visual check.

Removal check

Removing the backend audience check fails TestPhase09GuardIsolation. Mounting a protected route without the backend middleware fails TestPhase09PermissionMatrix and TestPhase09SecurityRoutes. Dropping an admin path from the OpenAPI document fails TestPhase09ContractInventory. A skipped PostgreSQL test fails scripts/check-phase9.sh.