Files
supabase/apps
Wen Bo Xie 56ef87a8df feat(studio): role-aware access feedback for scoped access tokens
Scoped PATs are enforced server-side as the intersection of the token's
granted scopes and the owner's live role, re-checked on every request. The
UI previously said nothing about this: any member could select any
permission scope for any resource, get no warning at creation, and the
token view kept rendering stored scopes as fact after the owner's access
changed. This adds advisory (never blocking) feedback across the whole
scoped-token flow so users learn at selection time -- not at their first
403 -- what a token can actually do.

Core (AccessToken.roles.ts, all pure and unit-tested):

- FGA_SCOPE_MINIMUM_ROLE: all 83 permission scopes transcribed from the
  OpenFGA model's role unions, mapped to the lowest base role that holds
  them. A drift-guard test pins the key set to the scope ids published in
  @supabase/shared-types, so upstream additions fail CI here with
  re-transcription instructions.
- estimateRoleLevel: derives the user's base role per org (or per project
  for project-invited members) from the ungated /platform/profile/
  permissions rows via four discriminating ABAC probes, verified against
  the platform's default_permissions seeds. Works for every member type
  with no permission-gated endpoint.
- computeTokenRoleContext + applySelectionToRoleContext: role resolution
  (expensive, memoized) is split from selection evaluation (cheap, re-run
  per permission toggle). Results carry per-resource failing roles,
  including per-project detail for members invited to projects rather
  than the org.

Creation form:

- Orgs where the user only has project-level access are disabled in
  org-scope mode, with an inline explanation.
- Permission rows and the review summary show a red "Exceeds your role"
  pill whose tooltip names the exact resources where requests would be
  denied, the required role, and the user's actual role there (spelling
  out per-project roles for project-invited members).
- The review admonition breaks exceeded permissions down per resource,
  organizations first; the risk badge is computed on the role-capped
  effective scope set.
- The immutability warning moved from a persistent admonition to
  micro-copy at the point of commitment; the permissions step links the
  access-control docs.

Token view sheet:

- Lost access is distinguished from deletion (deleting a project/org
  erases the token's FGA bindings; removal does not): bindings that
  vanished render a "resources no longer exist" state, while bindings the
  user can no longer reach show an anonymous count with a "No longer
  accessible" badge and a "removed from" admonition.
- Accessible resources list name plus ref/slug; capabilities carry the
  same exceeds-role pills; risk reflects what the owner's current role
  allows. Header now has separate Access control and API docs buttons
  (DocsButton gained a label prop).

All signals recompute from live org/project/permission queries, so the
view tracks membership changes without stored state, and everything
degrades to "no warnings" while data loads or on self-hosted.
2026-08-05 18:34:11 +07:00
..