feat(proxy): groups.<name> synthetic claims + auto-managed admin group; deprecate admin claim #44
No reviewers
Labels
No labels
prio_critical
prio_low
type_bug
type_contact
type_issue
type_lead
type_question
type_story
type_task
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
lhumina_code/hero_proxy!44
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "development_lee_admin_group"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The proxy now emits
groups.<name>for every group an authenticateduser belongs to (transitively, via the same BFS that resolves
role-derived claims). Symmetric with
users.<x>— both are factsabout the caller, both flow unconditionally, no per-route opt-in.
Backends that don't care about group membership simply don't reference
groups.*in their rules.To make
groups.adminimmediately useful, the proxy seeds a reservedgroup named
adminat startup and keeps membership in sync withusers.is_admin:user to the admin group
user from the admin group, so the invariant cannot be desynced
by hand (demote via users.update instead)
The legacy
adminsynthetic claim is now marked DEPRECATED 2026-05.It's still emitted whenever users.is_admin is true so existing rules
continue to match during the transition; new rules should use
groups.admininstead.docs/claims.md updated to drop the per-route opt-in language and
document the admin group's semantics.
Tests:
adminandgroups.admingroups.<name>and nothingelse admin-related
user-group counts
The proxy now emits `groups.<name>` for every group an authenticated user belongs to (transitively, via the same BFS that resolves role-derived claims). Symmetric with `users.<x>` — both are facts about the caller, both flow unconditionally, no per-route opt-in. Backends that don't care about group membership simply don't reference `groups.*` in their rules. To make `groups.admin` immediately useful, the proxy seeds a reserved group named `admin` at startup and keeps membership in sync with `users.is_admin`: - users.add(is_admin=true) and users.update(is_admin=true) add the user to the admin group - users.update(is_admin=false) removes them - a startup backfill covers any pre-existing is_admin users - groups.remove_member rejects manual removal of an is_admin=true user from the admin group, so the invariant cannot be desynced by hand (demote via users.update instead) The legacy `admin` synthetic claim is now marked DEPRECATED 2026-05. It's still emitted whenever users.is_admin is true so existing rules continue to match during the transition; new rules should use `groups.admin` instead. docs/claims.md updated to drop the per-route opt-in language and document the admin group's semantics. Tests: - admin group exists on a fresh server - admin user gets both `admin` and `groups.admin` - non-admin user in a custom group gets `groups.<name>` and nothing else admin-related - users.update(is_admin=false) drops both admin claims - groups.remove_member rejects desyncing the admin group - test_groups_crud updated to filter the admin group out of user-group counts