feat(10-01): harden the admin cookie session and prefix boot guards
- refresh and logout read the Bearer header first, then the summer_admin cookie; a cookie refresh rotates the cookie without a token in the body and logout always expires the cookie - backend.cookie_secure (default true) may drop Secure outside production only - activation rejects controller vendor segments api, assets, login, settings - BuildRouter rejects non-cabana routes at or under the admin prefix - SPA single-flights refresh on 401, replays once, and refreshes proactively at 80 percent of expires_in; dist rebuilt - scripts/check-admin-dist.sh rebuilds the SPA and fails on dist drift - tests: TestPhase10CookieAuth, TestPhase10CSRF, TestPhase10Prefix, TestPhase10AdminPrefixCollision, boardwalk serving and header tests
This commit is contained in:
@@ -34,6 +34,22 @@ func collectControllers(plugins []party.Plugin) ([]controllerRef, error) {
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// reservedVendorSegments are the first path segments under the admin prefix
|
||||
// that the SPA and API own. A controller ID maps to /{vendor}/{plugin}/..., so
|
||||
// a vendor with one of these names would collide with them.
|
||||
var reservedVendorSegments = map[string]bool{"api": true, "assets": true, "login": true, "settings": true}
|
||||
|
||||
func checkReservedSegments(items []controllerRef) error {
|
||||
for _, item := range items {
|
||||
id := item.ctl.ID()
|
||||
vendor, _, _ := strings.Cut(id, ".")
|
||||
if reservedVendorSegments[vendor] {
|
||||
return fmt.Errorf("cabana: controller %s uses the reserved admin path segment %q (reserved: api, assets, login, settings)", id, vendor)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func compileRegistry(items []controllerRef) (*Registry, error) {
|
||||
byID := make(map[string]*CompiledController, len(items))
|
||||
for _, item := range items {
|
||||
|
||||
Reference in New Issue
Block a user