Context. surface operator · domain operator (review, safety, support, persona/model/rights/provenance, incidents, launch) · route /operator · auth signed-in · source apps/oshun/web/src/app/operator/page.tsx
Last walked. 2026-06-25 operator-index route-state addendum — Playwright real-dev-infra coverage now proves the top operator bar product/section/breadcrumb are non-interactive, the page count/title/rule/eyebrow anchors, every surface code/title/description/open label and stable href, focused-link affordance, and the mobile one-column grid with no horizontal overflow. Evidence: WALKTHROUGH/results/v1-real-infra-run-2026-06-22.md §101; spec: apps/oshun/web/e2e/operator-surfaces.spec.ts. Previous: 2026-06-25 operator-surfaces direct-route addendum — Playwright real-dev-infra coverage for signed-in /operator render, anonymous proxy redirect, all four shipped surface links/codes/hrefs, 44 px link targets, and keyboard Enter activation into /operator/tenant. Evidence: WALKTHROUGH/results/v1-real-infra-run-2026-06-22.md §81; spec: apps/oshun/web/e2e/operator-surfaces.spec.ts.
Purpose#
The operator product's index page — "Plate of record. Four operator surfaces."
Surfaces the four distinct operator products (Studio, Tenant, Admin, etc.) as
cards routed from getOperatorIndex(). Robots-noindex (metadata.robots). See
V1/features.md and V1/ARCHITECTURE.md's Operator
surfaces section.
Entry points#
- Profile menu → Operator — primary entry
- Direct URL — session-gated only (
proxy.tsredirects sessionless →/welcome?redirect=); no operator-role gate in the proxy - Operator deep link from internal docs / runbooks
- Cross-product link when an admin needs to switch operator surfaces
Not entered from public/discovery surfaces.
robots: { index: false, follow: false } ensures it never appears in external
SEO.
Layout regions#
The page uses Lilith design-system primitives directly (LGraphPaper,
LOperatorBar, L, SERIF_L) rather than ShellLayout. Visually it adopts
the "plate of record" cream-paper-with-rules look.
- Top:
LOperatorBar— product="OSHUN", section="Operator", breadcrumb="Index" - Eyebrow: "Plate of record" (accent color)
- H1-like title: "Four operator surfaces." (Garamond 36 px)
- Main grid (max-width 960, centered):
- Auto-fit/minmax grid of operator surface entries, drawn from
data.surfaces; desktop presents as a ledger grid and mobile collapses to one column without horizontal document overflow - Each surface is
{ href, code, title, desc }; the cell renders anLCodecodebadge, thetitle, an italicdesc, and an "Open ↗" eyebrow (operator/page.tsx:53-95; operator-depth.ts:30-59)
- Auto-fit/minmax grid of operator surface entries, drawn from
States#
- Loading — no route
loading.tsx;getOperatorIndex()is a server-side static fixture and the page blocks until it renders - Anonymous user — redirected to
/welcome?redirect=(proxy.ts); never sees this - Signed-in user — full index renders (session-gated only; no operator-role gate in the proxy)
-
getOperatorIndex()fails — no routeerror.tsxexists underapps/oshun/web/src/app/operator; a render crash falls through to the nearest parent/global boundary - Offline — operator work is write-heavy and audit-stamped; offline mode disables most actions with a clear banner
- Different operator persona (e.g., safety operator vs. persona ops) — surfaces filtered to the role's permissions
Interactions#
LOperatorBar#
The shared operator bar at the top. Walk it as part of operator chrome:
- Product label —
OSHUN; non-interactive - Section label —
Operator; non-interactive - Breadcrumb —
Index; non-interactive on the index - No back/up affordance on the index — the bar exposes no link or button target
Surface grid#
For each cell in data.surfaces:
-
codebadge (LCode) — short code label (STUDIO,TENANT,ADMIN,METIS) - Surface title — Garamond display text
- Surface
desc— italic concise line from the index fixture - Surface link (whole cell is the
Link)- Function: navigates to the operator sub-surface
- Keyboard: Enter activates
- SR: announces surface name
- Touch ≥ 44×44 px
- Surface click telemetry —
operator_index_surface_clicked, surface= - Hover state — pulses or underlines per Lilith design
- Focus state — keyboard focus lands on the whole-cell link and keeps a
visible focus affordance; no
outline: none/shadowless regression
Page chrome#
- Eyebrow — color is set from
L.accent; Playwright verifies the stable eyebrow text/region - Title border — 1 px bottom border
L.ink; spacing correct at all widths - Grid —
auto-fit/minmax(min(100%, 360px), 1fr); Playwright proves one-column stacking and no horizontal overflow at 390 px width
E2E coverage#
apps/oshun/web/e2e/operator-surfaces.spec.ts— signed-in/operatorrender, top operator bar non-interactivity, index surface count/title/rule/eyebrow anchors, all four shipped surface links/codes/hrefs/descriptions/open labels, 44 px link target floor, visible focus affordance, keyboard Enter activation into/operator/tenant, mobile one-column/no-overflow grid behavior, click navigation into/operator/admin, incident-queue smoke, tenant directory/console detail checks, and anonymous redirect-before-render for/operator.
Data & contracts#
- Reads:
getOperatorIndex()from@/lib/lilith-data/operator-depth— returns{ surfaces: Array<{...}> }. NOTE: this is a static in-process fixture (returnsgetOperatorIndexFixture()directly), not a BFF call — the module is headed "fixture today, BFF tomorrow" - Writes: none on the index
- Realtime: none on the index
- Caching: server-rendered; cache headers from BFF; SW excludes operator surfaces from runtime cache (verify)
- Auth/role check: session-gated only (
proxy.tsredirects sessionless →/welcome?redirect=); no operator-role gate in the proxy, andsurfaces[]is not role-filtered
Cross-references#
- Shell:
shell/04-auth-session.md— role gates - Operator sub-routes (one file per route in this folder):
- (list grows as files are authored)
- Feature spec:
V1/features.md - Architecture:
V1/ARCHITECTURE.md
Open questions / known gaps#
- Enumerate the shipped
/operator/*routes and author walkthrough files for each — current route files cover admin, audit, incidents, lms, metis, personas, sso, studio, tenant, tenants, and admin/isis/provenance - Confirm the
surfaces[]returned bygetOperatorIndex()at each operator role and snapshot expected counts - Determine whether
apps/oshun/adminandapps/oshun/admin-mobileare also "operator" — if so, they need their own WALKTHROUGH branches - Document audit log behavior: every operator click should leave a trail
- An operator-role gate appears absent —
proxy.tsonly redirects sessionless users to/welcome; no role check in the proxy, operatorlayout.tsx(none exists), or the page components (possible gap vs intended scope)