---
path: /studio/rbac-permission-policy
surface: studio
domain: governance
auth: signed-in + studio entitlement
source: apps/oshun/web/src/app/studio/rbac-permission-policy/page.tsx
status: walked
last_walked:
  '2026-07-03 real-infra Playwright walk — anonymous redirect, admin catalog
  load, live RBAC evaluation, deny override, wildcard allow, default deny,
  unknown-role issues, client JSON validation, live BFF 400 detail,
  loading/503/malformed/network failures, pending-submit lockout, non-admin
  fail-closed auth, quick-action targets, 44 px controls, and mobile containment
  verified in Chromium. Evidence:
  apps/oshun/web/e2e/studio-rbac-permission-policy.spec.ts and
  WALKTHROUGH/results/v1-real-infra-run-2026-06-22.md'
---

# Studio · RBAC and Permission Policy UX

## Purpose

Evaluate access requests with the real RBAC policy evaluator: the Policy
Evaluation Lane applies role-inheritance closure, action wildcard matching, and
deny-override precedence (explicit deny beats allow; no matching rule is a
default deny). It is a live admin console wired to
`/v1/admin/studio/rbac-policy`, not an in-page simulation.

## Entry points

- **Direct URL / bookmark** — `/studio/rbac-permission-policy` (signed-in +
  studio entitlement; admin scope required to evaluate)
- **Sibling Studio routes** — reached via the quick-action panel on
  color-system, authentication-architecture, enterprise-tenant-isolation, and
  other governance pages

## Layout regions

`page.tsx` mounts `<ShellLayout active="studio">` and renders
`<StudioRbacPermissionPolicyUxWorkspace />` followed by a single `panel` of
quick-action links.

- **Shell**: `ShellLayout` chrome with the Studio tab active
- **Workspace heading**: `WorkspaceHeading` renders the page `<h1>` "Studio RBAC
  Permission Policy", followed by the `data-rbac-permission-policy-ux-summary`
  paragraph
- **Policy Evaluation Lane**: an `<h2>` `data-rbac-lane-heading` ("Policy
  Evaluation Lane") section with the load states and, when ready, the evaluate
  form and result
- **Quick-actions panel**: 7 sibling `quickAction` `Link`s — Enterprise Tenant
  Isolation, Audit and Compliance Surfaces, Notification Center, Activity and
  Change Feeds, "Back to Session and Device Management workspace", "Back to
  Authentication Architecture workspace", and "Back to Multi-Project Operations
  workspace". No self-link and no Route Map panel.

## States

- [x] **Loading** — `data-rbac-loading` ("Loading policy evaluator…")
- [x] **Unauthorized** — `data-rbac-unauthorized` ("Access restricted.") on
      401/403
- [x] **Error** — `data-rbac-error` ("Could not load the policy evaluator.")
- [x] **Ready / form** — `data-rbac-enums` ("N effects · M decision reasons")
      plus the `data-rbac-form` evaluate form
- [x] **Pending evaluate** — `data-rbac-form-state="pending"`,
      `data-rbac-submit-state="pending"`, disabled submit, `aria-busy="true"`
- [x] **Result** — `data-rbac-result` headline (`data-rbac-headline` with
      `data-rbac-allow-count`, `data-rbac-deny-count`), the
      `data-rbac-decisions` table of `data-rbac-decision-row` rows
      (`data-rbac-decision-reason`), and an optional `data-rbac-issues` list of
      `data-rbac-issue-row` items
- [x] **Evaluate error** — `data-rbac-evaluate-error` for invalid JSON or a
      non-200 response

## Interactions

- [x] **Policy (JSON)** — `textarea` `data-rbac-payload`,
      `aria-label="rbac policy json"`, seeded with roles containing
      `{ roleId, permissions[{ action, effect }], inherits[] }` and requests
      containing `{ requestId, subjectRoles[], action }`
- [x] **Evaluate policy** — `button` `data-rbac-submit` (`type="submit"`); POSTs
      the parsed JSON to `/v1/admin/studio/rbac-policy/evaluate`, setting
      `data-rbac-result` on a 200 with a valid `result`, or
      `data-rbac-evaluate-error` otherwise; disabled and busy while the POST is
      pending
- [x] **Quick-action links** — each `quickAction` `Link` navigates to its
      sibling Studio route (see Layout regions for the 7 targets)
- [x] **Mobile containment** — 390 px viewport has no horizontal overflow;
      policy textarea, submit, and quick actions meet 44 px minimum target size

## Data & contracts

- **Reads**: `GET /v1/admin/studio/rbac-policy` on mount — returns the catalog
  (`permissionEffects[]`, `decisionReasons[]`)
- **Writes**: `POST /v1/admin/studio/rbac-policy/evaluate` — returns
  `{ result: { results[], allowCount, denyCount, issues[] } }`
- **Realtime**: none
- **Caching**: client `fetch` with `cache: 'no-store'`; `buildBffAuthHeaders()`
  attaches the bearer token
- **Auth/role check**: admin-scoped fail-closed — `admin:*` or `admin:studio`,
  401/403 under the studio workspace gate

## Cross-references

- Parent: [`../studio-overview.md`](../studio-overview.md)
- Sibling:
  [`studio-authentication-architecture.md`](./studio-authentication-architecture.md),
  [`studio-enterprise-tenant-isolation.md`](./studio-enterprise-tenant-isolation.md),
  [`studio-audit-compliance-surfaces.md`](./studio-audit-compliance-surfaces.md)
- Component source:
  `apps/oshun/web/src/components/studio/StudioRbacPermissionPolicyUxWorkspace.tsx`
- BFF store: `apps/oshun/bff/src/studio/rbac-policy-store.ts` behind
  `/v1/admin/studio/rbac-policy`

## Open questions / known gaps

- [ ] Confirm whether the page will gain a breadcrumb/Route Map panel like other
      Studio surfaces, or keep the flat quick-action panel
- [ ] Document the live role catalog the evaluator should be seeded from once
      the lane drives production RBAC decisions
