V1 Web PWA · Surface walkthrough

Lilith Studio · authoring shell

A per-surface walkthrough of the V1 Web PWA customer surface: layout, states, interactions, data, and cross-references.

walked
8sections6 minread

On this page

Context. surface customer · domain lilith · route /lilith-studio · auth signed-in + role:v1_editorial_producer (default) · source apps/oshun/web/src/app/lilith-studio/page.tsx

Last walked. 2026-06-28 automated shell-contract walk (Playwright Chromium against real dev infra) — validated default/editorial and non-editorial access states, every V1 continuity lane link and entry id, every V3 authoring surface tab/route/provenance contract, provenance drawer open/close behavior, authoring-contract and release-check list presence, the full embedded provenance inspector, the V1 Studio entry link, and the now-built /lilith-studio/release route. Evidence: apps/oshun/web/e2e/lilith-studio-shell-smoke.spec.ts and apps/oshun/web/e2e/lilith-provenance-inspector-smoke.spec.ts. 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; content re-verified 2026-06-03 against current source

Purpose#

V3 authoring shell for editorial users — operates Lilith V3 authoring surfaces beside the V1 Studio editorial workflow, asset library, taxonomy, and release/versioning lanes. Lets editorial work in Lilith without leaving the Studio operating model. The page (apps/oshun/web/src/app/lilith-studio/page.tsx) returns <LilithStudioShell /> directly; the shell is supplied by the route's layout.tsx via <ShellLayout active="studio">, which also enforces the editorial scope gate (see Data & contracts).

Entry points#

  • Direct URL / bookmark — yes (signed-in)
  • From V1 Studio — verify navigation from /studio to /lilith-studio for editorial roles
  • From sub-surfaces — every sub-route under /lilith-studio/* has a back-link / "Open V1 Studio" link to this shell

Layout regions#

LilithStudioShell (apps/oshun/web/src/app/lilith-studio/LilithStudioShell.tsx) renders inside <ShellLayout active="studio"> — the shell mounted by the route's layout.tsx, not by the page — and has data-testid="lilith-studio-shell".

  • Aside (left rail, aria-label="Lilith Studio session"):
    • kicker "V3 authoring", title "Lilith Studio", summary copy
    • role pill with CheckCircle2 icon — "Signed in as " (default "V1 editorial producer")
    • meta list: Tenant tara-studio-editorial, Program project-lilith-v3, Workspace lilith-authoring-main
    • "Open V1 Studio" link → /studio (data-testid="lilith-v1-studio-link")
  • Main:
    • Header: eyebrow "V1 continuity with V3 surfaces", heading "Editorial can work in Lilith without leaving the Studio operating model.", lede; two header actions — "Review workflow" → /studio/review-approval-workflows and "Asset preview" → /studio/asset-preview-pipeline
    • Continuity lanes (data-testid="lilith-studio-v1-continuity", LILITH_STUDIO_V1_CONTINUITY_LANES): four lanes, each data-testid="lilith-studio-v1-lane":
      1. Editorial workflow (ListChecks) — 3 entries (program bootstrap, cross-domain pipeline, approval submission) → opens /studio/review-approval-workflows
      2. Asset library (Boxes) — 3 entries (tara venue, avatar + costume, saraswati media) → opens /studio/yemaya/asset-library
      3. Taxonomy (Tags) — 3 entries (tara room, persona + surface, music rights) → opens /studio/hathor/journal-and-codex
      4. Versioning (GitBranch) — 3 entries (draft branch, editorial candidate, release edition) → /studio/hathor/entity-version-management
    • V3 authoring surface grid:
      • Surface tabs (role="toolbar", data-testid="lilith-studio-surface-tab"): eight tabs from LILITH_STUDIO_V3_AUTHORING_SURFACES — Scene authoring, Avatar and costume, Asana authoring, Persona dossiers, Music authoring, Concert authoring, Provenance inspector, Release bridge
      • Surface detail (data-testid="lilith-studio-surface-detail") for the active tab — surface status "Shell ready", title, source- lane pill, description, route + provenance pills, "Open " link (data-testid="lilith-studio-open-active-surface"), authoring contract list, provenance summary aside with "Open provenance" button (data-testid="lilith-studio-open-provenance"), release- checks list
      • Provenance drawer (data-testid="lilith-studio-provenance-drawer") — role="dialog"; opens when "Open provenance" is clicked; shows Source lane, Route contract, Release branch chain; close button
    • LilithProvenanceInspector (full surface) — surface ID lilith-studio-shell, asset list = all 8 V3 surfaces
    • Status strip — four KPI tiles: Workflow entries, Asset lanes, Taxonomy entries, V3 surfaces

States#

  • Loading — client component; hydrates immediately; shell DOM and provenance inspector hydration are asserted in browser coverage.
  • Default rolev1_editorial_producer (LILITH_STUDIO_DEFAULT_ROLE); canOpenLilithStudioShell returns true for editorial roles. Covered by lilith-studio-shell-smoke.spec.ts.
  • Viewer role — signed-in non-editorial scope renders <LilithStudioAccessDenied /> with data-v1-editorial-role="false" and no authoring shell. Covered by lilith-studio-shell-smoke.spec.ts.
  • Default active surfacescene-authoring. Covered by lilith-studio-shell-smoke.spec.ts.
  • Surface tab switchedactiveSurfaceId updates; previously open provenance drawer closes. Covered for all eight tabs by lilith-studio-shell-smoke.spec.ts.
  • Provenance drawer open — drawer visible with data-open-provenance-id set. Covered by lilith-studio-shell-smoke.spec.ts.
  • Provenance drawer closed — drawer absent; "Open provenance" button visible. Covered by lilith-studio-shell-smoke.spec.ts.
  • Offline — page is mostly static client JSX with internal links; no fetch; renders offline

Interactions#

Aside#

  • "Open V1 Studio" link (data-testid="lilith-v1-studio-link") — href /studio

Header actions#

  • "Review workflow" link — href /studio/review-approval-workflows
  • "Asset preview" link — href /studio/asset-preview-pipeline

Continuity lanes (4 lanes)#

  • Workflow lane link (icon button) — href /studio/review-approval-workflows (aria-label "Open Editorial workflow")
  • Asset library lane link — href /studio/yemaya/asset-library
  • Taxonomy lane link — href /studio/hathor/journal-and-codex
  • Versioning lane link — href /studio/hathor/entity-version-management
  • Lane entry rows — read-only items per lane, all 12 stable data-lane-entry-id values asserted.

Surface tabs (8 tabs)#

  • Scene authoring tab (data-surface-id="scene-authoring", aria-pressed)
    • Function: sets activeSurfaceId='scene-authoring'; closes any open provenance
  • Avatar and costume tab (avatar-costume)
  • Asana authoring tab (asana-authoring)
  • Persona dossiers tab (persona-dossiers)
  • Music authoring tab (music-authoring)
  • Concert authoring tab (concert-authoring)
  • Provenance inspector tab (provenance-inspector)
  • Release bridge tab (release-bridge)

Surface detail panel#

  • "Open " link (data-testid="lilith-studio-open-active-surface") — href activeSurface.routeContract (e.g., /lilith-studio/scenes)
  • Authoring-contract list — read-only checklist with stable data-contract-count
  • "Open provenance" button (data-testid="lilith-studio-open-provenance")
    • Function: setOpenProvenanceId(activeSurface.provenanceId)
  • Release-checks list — read-only with stable data-release-check-count

Provenance drawer (when open)#

  • Drawer dialog (role="dialog", aria-labelledby="lilith-studio-provenance-title")
  • Close button (icon, X) — sets openProvenanceId(null)
  • Audit list — three checks (Source lane, Route contract, Release branch chain)

Provenance inspector (full)#

  • LilithProvenanceInspector — surface-level provenance browser (read its own walkthrough; here it lists all 8 V3 assets)

Data & contracts#

  • Reads: in-file constants LILITH_STUDIO_V1_CONTINUITY_LANES, LILITH_STUDIO_V3_AUTHORING_SURFACES, LILITH_STUDIO_SHELL_PROVENANCE_ASSETS (derived)
  • Writes: none — client state only (activeSurfaceId, openProvenanceId)
  • Realtime: none
  • Caching: client bundle
  • Auth/role check: signed-in is enforced upstream; the editorial-role gate lives in apps/oshun/web/src/app/lilith-studio/layout.tsx, which calls hasLilithStudioAccess() (src/lib/customer-role.ts) requiring an admin:* or studio:editorial scope. With access it renders the <ShellLayout active="studio"> + children; without it the layout renders <LilithStudioAccessDenied /> in place of the authoring shell. This layout gate covers /lilith-studio and every /lilith-studio/* sub-route, so the per-page data-v1-editorial-role flag is now a display detail, not the enforcement point.

Cross-references#

Open questions / known gaps#

  • Resolved: non-editorial roles are blocked by layout.tsx (hasLilithStudioAccess()admin:*/studio:editorial), which renders <LilithStudioAccessDenied /> instead of the shell for the whole /lilith-studio/* subtree
  • Resolved: the Release bridge surface (/lilith-studio/release) now has a route, release-state page, provenance inspector, and E2E coverage.
  • Document how role can be changed from the default v1_editorial_producer — the shell takes role as a prop but the page wraps it without passing one