Context. surface operator · domain operator (house — incident triage) · route /operator/incidents · auth signed-in · source apps/oshun/web/src/app/operator/incidents/page.tsx
Last walked. 2026-06-25 incident-triage row-cell addendum — Playwright real-dev-infra coverage for signed-in /operator/incidents render, generatedAt anchor, exact 1-open/1-closed masthead tally, lane/list counts, row IDs, row metadata attributes, severity/summary/meta/mitigation cells, all footer targets, and anonymous redirect-before-render. Evidence: WALKTHROUGH/results/v1-real-infra-run-2026-06-22.md §89; spec: apps/oshun/web/e2e/incident-triage.spec.ts.
Purpose#
The incident clipboard: open and recently-closed incidents from
GET /v1/incidents, split into two lanes. Each row is severity colour-coded
(p0–p3) and shows the opener time, acknowledger, and mitigation state. A
read-only triage view — there are no acknowledge/escalate controls in this code.
Entry points#
- From
/operator(hub) — operator-surface card; foot row "← Operator hub" returns there - Cross-links from siblings —
/operator/auditfoot row links here; this page links onward to/operator/auditand/operator/tenants - Auto-routed alerts — auto-generated incidents land in the feed (verify deep link to a specific incident; no per-incident route observed)
- Direct URL — session-gated only (
proxy.tsredirects sessionless →/welcome?redirect=); no operator-role gate in the proxy - Bookmark —
canonical = '/operator/incidents'
Layout regions#
page.tsx is an async server component:
await bffGet<IncidentsResponse>( '/v1/incidents') (falling back to
{ incidents: [] }), partitioned into open (mitigationState open or
investigating) and recent (everything else), rendered inside
<LWebShell top={<LCustomerNav active="library" />}> (reuses the customer
nav, Library active). Centered column maxWidth: 1080.
- Header:
LCustomerNav(Library highlighted — verify intended chrome) - Page anchor: outer content column exposes
data-operator-incidents-pageanddata-operator-incidents-generated-at - Masthead:
LMastheadwrapped bydata-operator-incidents-mastheadwithdata-operator-incidents-open-countanddata-operator-incidents-recent-count; visible copy is left "Operator · incidents", right${open.length} open · ${recent.length} closed, kicker "The clipboard", title "The incident queue." - "Open" lane:
IncidentTable title="Open"—<section data-operator-incidents-lane="open" data-operator-incidents-lane-count>withLEyebrow+ list of rows - "Recently closed" lane:
IncidentTable title="Recently closed"—<section data-operator-incidents-lane="recent" data-operator-incidents-lane-count> - Lane list: populated lanes expose
data-operator-incidents-listplusdata-operator-incidents-list-count - Incident row:
<li data-operator-incident-row>grid60px 1fr auto— stable attributes exposedata-operator-incident-id,data-operator-incident-severity,data-operator-incident-mitigation,data-operator-incident-opened-at, anddata-operator-incident-acknowledged-by; visible cells are severity pill (colour fromSEVERITY_COLOUR), summary + "opened - Footer action row:
LBtnghost "← Operator hub" (/operator),LBtnghost "Audit log" (/operator/audit),LBtnprimary "Tenants" (/operator/tenants)
States#
- Loading — source-verified 2026-06-25: no route-level
loading.tsx; server-sideawait bffGetblocks render, so there is no skeleton state - Anonymous user — Playwright 2026-06-25: sessionless
/operator/incidentsredirects to/welcome?...before[data-operator-incidents-page]or[data-operator-incident-row]render - Signed-in user — renders (session-gated only; no operator-role gate in
the proxy and no in-page guard); Playwright pins the current real fixture
partition at 1 open (
investigating) and 1 closed (mitigated) - Both lanes empty — source-verified 2026-06-25: each
IncidentTableshows[data-operator-incidents-empty]with "Nothing in this lane." Masthead right reads "0 open · 0 closed". Dedicated empty-route E2E is still pending because the server-component fetch cannot be page-routed - Open populated, closed empty (and vice versa) — only the populated lane lists rows
- Severity render — Playwright pins the current p1 and p2 fixture badges; a full p0–p3 diversity matrix is not present in the current fixture
- Mitigation render — Playwright pins the current
investigatingandmitigatedfixture states; full mitigation diversity is not present in the current fixture - BFF unreachable / non-2xx — source-verified 2026-06-25:
bffGetreturningnullsubstitutes{ incidents: [] }→ both lanes empty (no fabricated incidents). Dedicated outage-route E2E remains pending - Offline — RSC fetch (
revalidate 60); operator SW policy TBD - Standalone PWA — renders; verify robots/no-index (no
robotsexport here)
Interactions#
Masthead#
- Masthead labels — non-interactive; Playwright asserts the queue heading, "The clipboard", exact "1 open · 1 closed" text, and matching stable count attributes
Incident row (per row in each lane)#
- Severity pill (text badge) —
row.severity(p0–p3); background fromSEVERITY_COLOUR; non-interactive - Summary + meta (text) —
row.summary, then "opened· ack "; non-interactive - Mitigation-state label (accent text) —
MITIGATION_LABEL[row.mitigationState]; non-interactive - Row — Playwright asserts real row ids and stable severity/mitigation attributes, lane membership, opened-at/acknowledged-by metadata attributes, and visible severity/summary/meta/mitigation cells; source confirms no click handler / drill-in / acknowledge control wired in this route
Footer actions#
- "← Operator hub" (
LBtnghost, link) →/operator - "Audit log" (
LBtnghost, link) →/operator/audit - "Tenants" (
LBtnprimary, link) →/operator/tenants
Data & contracts#
- Reads:
bffGet<IncidentsResponse>('/v1/incidents')—{ generatedAt: string; incidents: Incident[] }whereIncident = { id, severity: 'p0'|'p1'|'p2'|'p3', summary, openedAtIso, acknowledgedBy, mitigationState: 'open'|'investigating'|'mitigated'|'resolved' }. Onnullsubstitutes an empty list. Partitioning into open/recent is done client-side - Writes: None observed in this view. (acknowledge / escalate / close are not wired here — triage actions presumably live elsewhere or are a gap)
- Realtime: None observed. (verify whether new incidents stream in via a
push channel — see
operator-admin.mdopen questions) - Caching: RSC fetch,
next.revalidate = 60, 5 s abort - Auth/role check: session-gated only (
proxy.tsredirects sessionless →/welcome?redirect=); no operator-role gate in the proxy and no in-page guard
E2E coverage#
apps/oshun/web/e2e/operator-surfaces.spec.ts— signed-in/operator/incidentsrender, queue masthead/tally, at least one incident row, severity text badge, and mitigation-state label.apps/oshun/web/e2e/incident-triage.spec.ts— direct/operator/incidentssigned-in render, stable page/masthead/lane/ list/row-cell/footer anchors, generatedAt ISO attribute, exact 1-open/1-closed tally, exact lane/list counts, real BFF fixture row IDsinc-2026-05-23-bff-503andinc-2026-05-25-themis-queue, row severity/mitigation/opened-at/acknowledged-by attributes, visible severity/summary/meta/mitigation cells, footer hrefs, and anonymous redirect-before-render. It also covers the richer/operator/adminincident lifecycle actions over the real BFF.- Still not browser-covered on this server-component route: forced empty lanes, forced BFF-unreachable fallback, offline/standalone/SW policy, and unbuilt row drill-in/actions.
Cross-references#
- Parent:
operator-overview.md - Sibling operator routes:
operator-audit.mdoperator-tenants.mdoperator-sso.mdoperator-admin.md— richer inbox triage with a detail pane (theAdminInboxcomponent)
- Feature spec:
V1/features.md - Architecture:
V1/ARCHITECTURE.md - Journeys traversing this view:
Open questions / known gaps#
- No acknowledge / investigate / mitigate / resolve actions on rows — an
operator can read but not act. Confirm whether triage actions belong here
or only on
/operator/admin(theAdminInboxdetail card) - No per-incident detail route / row drill-in observed; document where an operator opens the full incident record
- No realtime channel wired; document how the queue refreshes (only RSC
revalidate 60) - This operator route renders the customer
LCustomerNav(Library active) and has norobots: { index: false }— confirm intended chrome and SEO gating - An operator-role gate appears absent —
proxy.tsonly redirects sessionless users to/welcome; no role check in the proxy or page component (possible gap vs intended scope)