---
path: /studio/resilience-error-ux
surface: studio
domain: operations
auth: signed-in + studio entitlement
source: apps/oshun/web/src/app/studio/resilience-error-ux/page.tsx
status: walked
last_walked:
  '2026-05-29 automated runtime walk (Playwright headless) — render, /v1 data
  (2xx), console/page-errors, expected content, screenshot verified; live
  screen-reader, touch, offline, and telemetry-delivery checks pending a manual
  AT pass. Evidence: WALKTHROUGH/results/runtime-sweep-2026-05-29.md; body
  re-derived 2026-06-03 from current source (lane-console architecture)'
---

# Studio · Resilience and Error UX

## Purpose

Drive the circuit-breaker state machine with the real breaker evaluator: per
service it computes the error rate and the next closed / open / half-open state
— tripping closed→open when the error rate clears the threshold over the volume
threshold, probing open→half-open after the cooldown elapses, and recovering
half-open→closed after enough consecutive probe successes — with a fleet rollup
of closed / open / half-open / tripped counts. The workspace
(`StudioResilienceErrorUxWorkspace`) is an admin lane console that loads the
breaker catalog on mount and posts a services payload for evaluation.

## Entry points

- **Studio root** (`/studio`) — discoverable as an operations workspace
- **Sibling quick actions** — Metrics and Analytics Instrumentation, Background
  Jobs and Progress UX, Asset Preview Pipeline, File and Media Ingestion, and
  Activity and Change Feeds workspaces link in/out
- **Direct URL / bookmark** — yes

## Layout regions

`page.tsx` mounts `ShellLayout active="studio"`, renders
`StudioResilienceErrorUxWorkspace`, then a single `panel` of 5 `quickAction`
links. There is no breadcrumb and no Route Map panel on this route.

- **Workspace heading** (`<h1>` via `WorkspaceHeading`): "Studio Resilience &
  Error UX"
- **Summary** (`data-resilience-error-summary`): trip / probe / recover
  transitions
- **Circuit Breaker Lane** (`<h2>` `data-cb-lane-heading`): the load-states +
  evaluation form + result region
- **Footer quick actions** (`panel`): 5 sibling `quickAction` links

## States

- [ ] **Loading** — `data-cb-loading` "Loading breaker evaluator…" while the
      catalog request is in flight
- [ ] **Unauthorized** — `data-cb-unauthorized` "Access restricted." on a
      401/403 (admin scope required)
- [ ] **Error** — `data-cb-error` "Could not load the breaker evaluator." on a
      non-OK catalog response or network failure
- [ ] **Ready (form)** — catalog loaded: `data-cb-enums` breaker-states /
      transitions counts + the `data-cb-form` JSON form
- [ ] **Result** — `data-cb-result` with the closed / open / half-open / tripped
      headline and the per-service transition table
- [ ] **Validation** — `data-cb-evaluate-error` for invalid JSON or a non-200
      evaluate response

## Interactions

### Circuit Breaker Lane (form)

- [ ] **Breakers JSON** (`textarea` `data-cb-payload`, `aria-label` "breakers
      json") — payload of `{ policy{ errorRateThreshold, volumeThreshold,
      cooldownSeconds, halfOpenSuccessThreshold }, services[{ serviceId,
      totalRequests, failedRequests, currentState, consecutiveSuccesses,
      secondsSinceOpened }] }`
- [ ] **Evaluate breakers** (`button` `data-cb-submit`, `type=submit`) — POSTs
      the parsed payload to `\`${CB_ENDPOINT}/evaluate\``

### Result region

- [ ] **Headline** (`data-cb-headline`) — `data-cb-count` spans for closed /
      open / half_open / tripped
- [ ] **Services table** (`data-cb-services`) — rows `data-cb-service-row` with
      `data-next-state` + `data-transition`, cells `data-cb-error-rate`,
      current→next state, and `data-cb-transition`

### Footer quick actions

- [ ] **Open Metrics and Analytics Instrumentation workspace** →
      `/studio/metrics-analytics-instrumentation`
- [ ] **Back to Background Jobs and Progress UX workspace** →
      `/studio/background-jobs-progress-ux`
- [ ] **Back to Asset Preview Pipeline workspace** →
      `/studio/asset-preview-pipeline`
- [ ] **Back to File and Media Ingestion workspace** →
      `/studio/file-media-ingestion`
- [ ] **Back to Activity and Change Feeds workspace** →
      `/studio/activity-change-feeds`

## Data & contracts

- **Reads**: GET `/v1/admin/studio/resilience-circuit-breakers` (catalog:
  `breakerStates`, `transitions`) on mount
- **Writes**: POST `/v1/admin/studio/resilience-circuit-breakers/evaluate`
- **Realtime**: none
- **Client fetch**: `buildBffAuthHeaders()`, `cache: 'no-store'`,
  abort-on-unmount
- **Auth/role check**: admin-scoped, fail-closed (401/403 → unauthorized); route
  is signed-in + studio via the proxy gate

## Cross-references

- Parent: [`../studio-overview.md`](../studio-overview.md)
- Sibling:
  [`studio-metrics-analytics-instrumentation.md`](./studio-metrics-analytics-instrumentation.md),
  [`studio-background-jobs-progress-ux.md`](./studio-background-jobs-progress-ux.md),
  [`studio-observability-operational-dashboards.md`](./studio-observability-operational-dashboards.md)
- Source:
  `apps/oshun/web/src/components/studio/StudioResilienceErrorUxWorkspace.tsx`

## Open questions / known gaps

- [ ] Confirm where the `/v1/admin/studio/resilience-circuit-breakers` BFF route
      sources its evaluator (module + which `admin:*` scopes)
- [ ] Document whether the computed next-state is ever persisted as live breaker
      state anywhere downstream
