Skip to main content

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 Expires value 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}.