Context. surface operator · domain operator (isis provenance — hash-chain ledger inspector) · route /operator/admin/isis/provenance · auth signed-in · source apps/oshun/web/src/app/operator/admin/isis/provenance/page.tsx
Last walked. 2026-06-25 provenance route-state addendum — direct clean, empty, unavailable, unknown-bundle, broken-tenant, tenant-preserving link, anonymous redirect, bundle-row timestamp, and generated-artifact inspector states are covered in citation-drift-resolution.spec.ts. Earlier: 2026-05-29 automated runtime walk (Playwright) — defect fixed & re-verified: render+data OK, 0 page/console errors; live SR/touch/offline/telemetry pending manual AT pass. Evidence: WALKTHROUGH/results/runtime-sweep-2026-05-29.md; content re-verified 2026-06-03 against current source
Purpose#
Inspect per-generation provenance bundles and verify the immutable Isis ledger
hash chain. The page composes two inspectors stacked: the
IsisProvenanceInspector (bundle index + verification verdict + per- bundle
field detail) and the GeneratedArtifactProvenanceInspector (artifact-side
provenance for operator-editorial surfaces). Robots-noindex.
Entry points#
- From
/operator/admin(the admin inbox) — citation-drift incident detail links here with?inc=<INC>; current bundle selection happens in the inspector - Direct URL with
?tenant=Xand/or?bundle=Yquery params — parameters driveloadIsisProvenanceData({ tenantId, selectedBundleId }) - Deep link from incident detail — INC tickets referencing citation drift /
model lineage hand off here;
INC-2041is covered incitation-drift-resolution.spec.ts - Internal docs / runbooks linking to specific bundle IDs
Layout regions#
The page is two stacked <article> regions inside a <> fragment, with the
inspector following the artifact provenance inspector below.
IsisProvenanceInspector(server-data-driven, presentational):- Header (
<header>) — h2 "Isis provenance inspector" + intro paragraph - Verification card
(
<article aria-live="polite" data-verification-ok="true|false">) — h3 "Ledger verification" with a<dl>:- Status —
"CLEAN — hash chain intact"OR"BROKEN at index N" - Tenant scope — tenantId or
(no tenant — platform ledger) - Chain length — integer
- Last checked — ISO timestamp
<time>element
- Status —
- Recent bundles index (
<article>) — h3 "Recent bundles":- If empty:
data-testid="isis-provenance-empty-state"paragraph - Otherwise:
<ol>of bundle rows; each row has<a href={searchHref(bundle.bundleId)}>linking back with preserved tenant param - Row content: bold bundle ID +
model@version (modality) · ISO time
- If empty:
- Selected bundle detail (
<article data-bundle-id=...>) — h3 = bundle ID:<dl>of 16 fields fromFIELD_LABELS: Bundle ID, Generation ID, Invoking user, Tenant, Consent ID, Prompt hash, Model ID, Model version, Modality, Watermark hash, Endpoint, Region, Bundle fingerprint, Chain fingerprint, Prior fingerprint, Sequence- Plus computed "Emitted at" — ISO from
emittedAtUnixSeconds * 1000 - Each
<dd>hasdata-testid="isis-provenance-field-<key>"for ctrl-F-able testing hooks - If no selection: empty detail article with prompt copy
- Header (
GeneratedArtifactProvenanceInspector— artifact-side surface (surfaceId="operator-isis-provenance",surfaceRole="editorial",title="Operator artifact provenance"). Inspect this component separately when authoring per-artifact walkthroughs.
States#
- Loading — source-verified: page is RSC; awaits
loadIsisProvenanceDataserver-side; no client skeleton - Anonymous user — Playwright verifies sessionless users redirect to
/welcomebefore either provenance inspector renders - Signed-in user — renders (session-gated only; no operator-role gate in the proxy)
- No tenant query param — Playwright verifies platform-ledger scope
text:
"(no tenant — platform ledger)" - Tenant param + bundle param — Playwright verifies tenant-preserving bundle links navigate to a full detail pane
- Tenant param, no bundle — Playwright verifies the bundles list renders and the detail pane prompts "Select a bundle..."
- Unknown bundle param — Playwright verifies the platform index remains visible and the detail pane falls back to the empty selection prompt
- Empty bundles —
data-testid="isis-provenance-empty-state"paragraph: "No provenance bundles persisted for this tenant yet." - Chain verification OK —
data-verification-ok="true"; announces "CLEAN — hash chain intact" viaaria-live="polite" - Chain verification broken —
data-verification-ok="false"; announces "BROKEN at index N" -
loadIsisProvenanceDatafails — page catches loader errors and renders the accessible "Provenance ledger unavailable" retry state
Interactions#
Verification card#
-
aria-live="polite"region — Playwright verifies the verification article carriesaria-live="polite"; no recheck action exists yet -
<time>element —dateTimeattribute is the ISO ofverification.checkedAt
Bundles index <ol>#
- Each bundle row link (
<a href={searchHref(bundle.bundleId)}>)- Function: navigates to same page with
?bundle=X(and preservestenant=) - Keyboard: native anchor tab/enter behavior
- SR: announces bundle ID as the accessible name
- Touch: native text link; no custom 44 px target treatment
- Telemetry: none on the page; tracking via server logs
- Function: navigates to same page with
-
<time>per row —dateTimeattribute is the ISO derived fromemittedAtUnixSeconds
Selected bundle detail <dl>#
- Non-interactive read-only listing; copy operations work via the browser's native text selection
- Test hooks:
data-testid="isis-provenance-field-<key>"for each field; useful for automated provenance verification flows - Watermark hash — when present, shown verbatim; absence reflected as
— - Prior fingerprint — first bundle in chain shows
—; others show prior bundle's fingerprint
GeneratedArtifactProvenanceInspector#
- Inspect separately. Its surfaceId is
operator-isis-provenanceand surfaceRole iseditorial.
Data & contracts#
- Reads:
loadIsisProvenanceData({ tenantId, selectedBundleId })from@/lib/server/isis-provenance-loader— returns{ bundles[], selectedBundle, verification } - Writes: none on this page (ledger is append-only; writes happen via the generation API in Isis)
- Realtime: none on this page; ledger updates are eventually- consistent
- Caching: page is RSC; awaits server data;
searchParamsis aPromise<>(Next.js 15 pattern); no SW caching for/operator/* - Auth/role check: session-gated only (
proxy.tsredirects sessionless →/welcome?redirect=); no operator-role gate in the proxy
Provenance bundle contract#
The IsisProvenanceBundleView interface defines 17 fields: bundleId,
generationId, invokingUserId, tenantId, consentId, promptHash,
modelId, modelVersion, modality (text | image | audio | video |
3d-mesh | embedding), watermarkHash, endpointId, region,
emittedAtUnixSeconds, fingerprint, chainFingerprint, priorFingerprint,
sequence.
IsisProvenanceVerification has ok, brokenAtIndex, checkedAt, tenantId,
chainLength.
Cross-references#
- Parent:
operator-overview.md,operator-admin.md - Component sources:
apps/oshun/web/src/components/admin/IsisProvenanceInspector.tsx(167 lines)apps/oshun/web/src/components/provenance/GeneratedArtifactProvenanceInspector.tsx
- Data:
apps/oshun/web/src/lib/server/isis-provenance-loader.ts - Tests:
apps/oshun/web/src/components/admin/__tests__/IsisProvenanceInspector.test.tsx,apps/oshun/web/e2e/citation-drift-resolution.spec.ts - Feature spec:
V1/features.md - Architecture:
V1/ARCHITECTURE.md
Open questions / known gaps#
- Runtime walk (2026-05-29) — defect FIXED & verified: the page crashed
to the generic error boundary when the provenance ledger store was
unconfigured/unreachable (loadIsisProvenanceData threw, server component
had no catch). Now wrapped in try/catch with a clear, accessible
"provenance ledger unavailable" + retry state. Re-walked: no error
boundary, HTTP 200. rendered. Status kept
drafteduntil fixed. - Document the recheck affordance (if any) that re-runs hash-chain verification — current code only renders the verdict from server data
- Confirm how the page is reached: the
/operator/admincitation-drift detail card now exposes "Open provenance" withdata-operator-incident-provenance-link="INC-2041"and the E2E clicks through to/operator/admin/isis/provenance?inc=INC-2041. - Walk
GeneratedArtifactProvenanceInspectorseparately when authoring artifact-side provenance walkthroughs (it appears on multiple operator surfaces) - Test what happens with unknown
?bundle=— current server loader keeps the bundle index visible and gracefully shows the empty detail prompt - 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)