---
path: /operator/admin/isis/provenance
surface: operator
domain: operator (isis provenance — hash-chain ledger inspector)
auth: signed-in
source: apps/oshun/web/src/app/operator/admin/isis/provenance/page.tsx
status: walked
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'
---

# Operator · Isis provenance inspector

## 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=X` and/or `?bundle=Y` query params — parameters
  drive `loadIsisProvenanceData({ tenantId, selectedBundleId })`
- **Deep link from incident detail** — INC tickets referencing citation drift /
  model lineage hand off here; `INC-2041` is covered in
  `citation-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
  - **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`
  - **Selected bundle detail** (`<article data-bundle-id=...>`) — h3 = bundle
    ID:
    - `<dl>` of 16 fields from `FIELD_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>` has `data-testid="isis-provenance-field-<key>"` for
      ctrl-F-able testing hooks
    - If no selection: empty detail article with prompt copy
- **`GeneratedArtifactProvenanceInspector`** — artifact-side surface
  (`surfaceId="operator-isis-provenance"`, `surfaceRole="editorial"`,
  `title="Operator artifact provenance"`). Inspect this component separately
  when authoring per-artifact walkthroughs.

## States

- [x] **Loading** — source-verified: page is RSC; awaits
      `loadIsisProvenanceData` server-side; no client skeleton
- [x] **Anonymous user** — Playwright verifies sessionless users redirect to
      `/welcome` before either provenance inspector renders
- [x] **Signed-in user** — renders (session-gated only; no operator-role gate in
      the proxy)
- [x] **No tenant query param** — Playwright verifies platform-ledger scope
      text: `"(no tenant — platform ledger)"`
- [x] **Tenant param + bundle param** — Playwright verifies tenant-preserving
      bundle links navigate to a full detail pane
- [x] **Tenant param, no bundle** — Playwright verifies the bundles list renders
      and the detail pane prompts "Select a bundle..."
- [x] **Unknown bundle param** — Playwright verifies the platform index remains
      visible and the detail pane falls back to the empty selection prompt
- [x] **Empty bundles** — `data-testid="isis-provenance-empty-state"` paragraph:
      "No provenance bundles persisted for this tenant yet."
- [x] **Chain verification OK** — `data-verification-ok="true"`; announces
      "CLEAN — hash chain intact" via `aria-live="polite"`
- [x] **Chain verification broken** — `data-verification-ok="false"`; announces
      "BROKEN at index N"
- [x] **`loadIsisProvenanceData` fails** — page catches loader errors and
      renders the accessible "Provenance ledger unavailable" retry state

## Interactions

### Verification card

- [x] **`aria-live="polite"` region** — Playwright verifies the verification
      article carries `aria-live="polite"`; no recheck action exists yet
- [x] **`<time>` element** — `dateTime` attribute is the ISO of
      `verification.checkedAt`

### Bundles index `<ol>`

- [x] **Each bundle row link** (`<a href={searchHref(bundle.bundleId)}>`)
  - Function: navigates to same page with `?bundle=X` (and preserves `tenant=`)
  - 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
- [x] **`<time>` per row** — `dateTime` attribute is the ISO derived from
      `emittedAtUnixSeconds`

### Selected bundle detail `<dl>`

- [x] Non-interactive read-only listing; copy operations work via the browser's
      native text selection
- [x] Test hooks: `data-testid="isis-provenance-field-<key>"` for each field;
      useful for automated provenance verification flows
- [x] **Watermark hash** — when present, shown verbatim; absence reflected as
      `—`
- [x] **Prior fingerprint** — first bundle in chain shows `—`; others show prior
      bundle's fingerprint

### `GeneratedArtifactProvenanceInspector`

- Inspect separately. Its surfaceId is `operator-isis-provenance` and
  surfaceRole is `editorial`.

## 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; `searchParams` is a `Promise<>`
  (Next.js 15 pattern); no SW caching for `/operator/*`
- **Auth/role check**: session-gated only (`proxy.ts` redirects 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-overview.md),
  [`operator-admin.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`](../../V1/features.md#isis-generation-control)
- Architecture: [`V1/ARCHITECTURE.md`](../../V1/ARCHITECTURE.md#isis)

## Open questions / known gaps

- [x] **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 `drafted` until fixed.
- [ ] Document the recheck affordance (if any) that re-runs hash-chain
      verification — current code only renders the verdict from server data
- [x] Confirm how the page is reached: the `/operator/admin` citation-drift
      detail card now exposes "Open provenance" with
      `data-operator-incident-provenance-link="INC-2041"` and the E2E clicks
      through to `/operator/admin/isis/provenance?inc=INC-2041`.
- [ ] Walk `GeneratedArtifactProvenanceInspector` separately when authoring
      artifact-side provenance walkthroughs (it appears on multiple operator
      surfaces)
- [x] 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.ts` only redirects
      sessionless users to `/welcome`; no role check in the proxy or page
      component (possible gap vs intended scope)
