Effective access explorer
Open Authz → Effective Access (/authz/effective-access), paste a user UUID, hit Resolve.
What you'll see
Every role binding currently affecting the user, with:
- Role — name and ID of the role the user holds.
- Subject — how they hold it: Direct (user), Via group, or Service account.
- Scope — what the binding applies to: tenant-wide, a specific resource server, or a sub-scope.
- Expires — when the binding auto-expires, or "—" if perpetual.
- Binding ID — for cross-referencing with audit logs and decision traces.
What it doesn't show (yet)
Phase A only surfaces bindings. It doesn't run the full PDP — conditions (MFA, allowed IPs, allowed repos), tool policy, and OAuth-scope intersection are evaluated at decision time. The full would this call succeed? simulator lands in Phase B as the Decision Trace page.
Common queries
- "Why does this user get a 403 on
github-mcp?" Resolve their UUID. If no bindings target the resource server (and no tenant-wide bindings exist), they have no access. If bindings exist but the user still gets denied, the cause is in conditions or token scope — check the decision trace. - "What does removing this group do?" Resolve a user in the group and see which rows show Via group. Removing them from the group drops exactly those rows from their effective access.
- "What does this contractor still have access to?" Resolve their UUID. Anything with an
Expiresvalue is on a timer; perpetual bindings need explicit revocation.
Performance note
The explorer runs a UNION query across direct user bindings and group-mediated bindings (via user_groups). It's cheap up to ~10k bindings per user. The indexes added in Phase A (idx_rb_tenant_group, idx_ug_tenant_user) keep it fast.
API reference
GET /uflow/v2/users/:user_id/effective-access returns {items, count} where each item is {binding_id, role_id, role_name, subject, subject_id, scope_type, scope_id, expires_at}.