---
path: /studio/accessibility-governance
surface: studio
domain: governance
auth: signed-in + studio entitlement
source: apps/oshun/web/src/app/studio/accessibility-governance/page.tsx
status: walked
last_walked:
  '2026-07-03 real-dev-infra Playwright addendum — focused route journey
  verified direct admin navigation, live BFF catalog, seeded and edited WCAG
  contrast audits, relaxed large-text thresholds, client-only JSON validation,
  live BFF 400 details, pending-submit lockout, malformed/offline fail-closed
  paths, catalog loading/error, non-admin fail-closed auth, direct BFF
  auth/schema gates, quick-action affordances, shared axe, mobile containment,
  and anonymous redirect. Evidence:
  WALKTHROUGH/results/v1-real-infra-run-2026-06-22.md §264;
  apps/oshun/web/e2e/studio-accessibility-governance.spec.ts. Previous:
  2026-05-29 automated runtime walk (Playwright headless) — render, /v1 data
  (2xx), console/page-errors, expected content, screenshot verified.'
---

# Studio · Accessibility Governance

## Purpose

Audit colour contrast with the real WCAG 2.x auditor: the WCAG Contrast Lane
computes sRGB relative-luminance contrast ratios and reports AA/AAA conformance
with the relaxed large-text thresholds. It is a live admin console wired to
`/v1/admin/studio/wcag-contrast`, not an in-page simulation.

## Entry points

- **Direct URL / bookmark** — `/studio/accessibility-governance` (signed-in +
  studio entitlement; admin scope required to audit)
- **Sibling Studio routes** — reached via the quick-action panel on
  internationalization-localization, experimentation-feature-flags, and other
  governance/operations pages

## Layout regions

`page.tsx` mounts `<ShellLayout active="studio">` and renders
`<StudioAccessibilityGovernanceWorkspace />` 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
  Accessibility Governance", followed by the
  `data-accessibility-governance-summary` paragraph
- **WCAG Contrast Lane**: an `<h2>` `data-wc-lane-heading` ("WCAG Contrast
  Lane") section with the load states and, when ready, the audit form and result
  table
- **Quick-actions panel**: `data-wc-quick-actions`
  `data-wc-quick-action-count="5"` wraps 5 sibling `quickAction` `Link`s:
  `data-wc-quick-action="internationalization-localization"`,
  `performance-budgets`, `experimentation-feature-flags`,
  `observability-operational-dashboards`, and
  `metrics-analytics-instrumentation`. No self-link and no Route Map panel.

## States

- [x] **Loading** — `data-wc-loading` ("Loading contrast auditor…")
- [x] **Unauthorized** — `data-wc-unauthorized` ("Access restricted.") on
      401/403
- [x] **Error** — `data-wc-error` ("Could not load the contrast auditor.")
- [x] **Ready / form** — `data-wc-enums` ("N conformance levels") plus the
      `data-wc-form` audit form seeded with `DEFAULT_PAYLOAD` and
      `data-wc-form-state="idle|pending"`
- [x] **Pending submit** — `data-wc-submit-state="pending"`, disabled,
      `aria-disabled="true"`, and `aria-busy="true"` while the audit POST is in
      flight
- [x] **Result** — `data-wc-result` headline (`data-wc-headline` with
      `data-wc-aa-count`, `data-wc-aaa-count`, `data-wc-fail-count`) and the
      `data-wc-pairs` table of `data-wc-pair-row` rows (`data-wc-pair-ratio`,
      `data-aa-threshold`, `data-aaa-threshold`, `data-aa-pass`,
      `data-aaa-pass`)
- [x] **Audit error** — `data-wc-audit-error` for invalid JSON, a non-200
      response, an offline audit POST, or a malformed 200 success payload
- [x] **Offline** — catalog GET fails closed to the error panel; the audit POST
      surfaces the generic error when the network is unreachable
- [x] **Gated** — admin scope denied → `data-wc-unauthorized`; the route itself
      is proxy-gated to signed-in + studio
- [ ] **Standalone PWA** — renders within the shell; no URL-bar dependency

## Interactions

- [x] **Colour pairs (JSON)** — `textarea` `data-wc-payload`,
      `aria-label="contrast pairs json"`, seeded with
      `{ pairs[{ pairId,     foreground, background, largeText }] }`
- [x] **Audit contrast** — `button` `data-wc-submit` (`type="submit"`); POSTs
      the parsed JSON to `/v1/admin/studio/wcag-contrast/audit`, setting
      `data-wc-result` on a 200 with a valid `result`, or `data-wc-audit-error`
      otherwise
- [x] **Quick-action links** — each `quickAction` `Link` navigates to its
      sibling Studio route (see Layout regions for the 5 targets)

## Data & contracts

- **Reads**: `GET /v1/admin/studio/wcag-contrast` on mount — returns the catalog
  (`conformanceLevels[]`)
- **Writes**: `POST /v1/admin/studio/wcag-contrast/audit` — returns
  `{ result: { pairs[], summary{ aaPassCount, aaaPassCount, failCount } } }`
- **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

## E2E coverage

- `apps/oshun/web/e2e/studio-accessibility-governance.spec.ts` forwards
  `GET /v1/admin/studio/wcag-contrast` and
  `POST /v1/admin/studio/wcag-contrast/audit` to the live dev BFF with explicit
  admin and non-admin dev bearers. It covers direct admin navigation, catalog
  bearer forwarding, exact seeded ratios (`21`, `4.54`, `2.85`, `8.59`), AA/AAA
  summaries, relaxed large-text thresholds, low-contrast failures, malformed
  JSON zero-POST rejection, live BFF invalid-payload details, pending-submit
  lockout, catalog loading/error, malformed catalog, malformed 200 audit
  success, network-unreachable audit error, non-admin fail-closed state, direct
  BFF auth/schema gates, quick-action href/touch targets, shared axe, anonymous
  redirect, and mobile containment.

## Cross-references

- Parent: [`../studio-overview.md`](../studio-overview.md)
- Sibling:
  [`studio-internationalization-localization.md`](./studio-internationalization-localization.md),
  [`studio-experimentation-feature-flags.md`](./studio-experimentation-feature-flags.md)
- Component source:
  `apps/oshun/web/src/components/studio/StudioAccessibilityGovernanceWorkspace.tsx`
- BFF store: `apps/oshun/bff/src/studio/` WCAG contrast auditor behind
  `/v1/admin/studio/wcag-contrast`

## Open questions / known gaps

- [x] Confirm whether the page will gain a breadcrumb/Route Map panel like other
      Studio surfaces, or keep the flat quick-action panel — current `page.tsx`
      keeps the flat quick-action panel with no self-link and no Route Map panel
      as of 2026-07-03.
- [ ] Document whether keyboard/screen-reader/semantic accessibility lanes will
      join the single contrast lane once the auditor expands. Current V1 browser
      behavior audits caller-supplied contrast pairs through the real
      deterministic BFF auditor; richer AT/semantic lane ingestion remains a
      product source expansion gap, not a browser interaction gap.
