# Journey: Lilith Studio · author a Tara venue scene and record a durable release receipt

An editorial producer enters Lilith Studio, composes a fixture-backed Tara venue
in `TaraSceneEditor`, clears its readiness gates, and records a release-edition
receipt through the scene-publish BFF. The authoring interaction is deep and
real in the browser; the exact manifest and owner-scoped receipt commit to the
durable snapshot authority before the editor paints success and recover after a
BFF restart. This receipt is **not** the admin editorial approval stream, emits
no audit event, and is not consumed by `getTara()` or `/lilith`. The former
title's promise—“publish to `/tara`”—is the remaining cross-surface product leg,
not a current post-condition.

## Personas

- **Editorial producer** — has `studio:editorial` or `admin:*`, passes the
  Lilith Studio layout gate, and operates the scene editor.
- **Viewer-role customer** — lacks those scopes and receives the explicit
  access-denied surface.
- **Operator reviewer** — future consumer of an editorial candidate; the scene
  route does not currently create an admin review item.
- **Tara customer** — future consumer of an approved venue; the Tara room does
  not currently read this publish store.

## Pre-conditions

- The producer has a signed-in session whose scopes derive an editorial role
  through `deriveCustomerRoleFromScopes` / `hasLilithStudioAccess`.
- `/lilith-studio/scenes` can mount `TaraSceneEditor`.
- The editor's fixture catalog is loaded in source: four assets, four zones,
  three selectable lighting presets, three rights-cleared audio beds, three
  triggers/actions, four capacity tiers, three sharding profiles, and two
  profiles for each accessibility dimension.
- The scene-publish BFF route is reachable with `studio:editorial`,
  `admin:studio`, or `admin:*`.
- Production has hydrated `StudioScenePublishStore` from the required durable
  snapshot sink before traffic. “Persisted” means a `201` followed an awaited
  snapshot commit and the same owner can recover the receipt after restart.

## Steps

### 1. Enter Lilith Studio

- [x] Navigate to `/lilith-studio`.
- [x] The layout reads customer-session scopes and either mounts
      `ShellLayout active="studio"` or `LilithStudioAccessDenied`.
- [x] The shell identifies the seeded tenant/program/workspace and exposes eight
      authoring tabs: Scene, Avatar/costume, Asana, Persona dossiers, Music,
      Concert, Provenance, and Release bridge.
- [x] “Open Scene authoring” links to `/lilith-studio/scenes`; “Open V1 Studio”
      links to `/studio`.

### 2. Orient in the scene editor

- [x] The route mounts `TaraSceneEditor` with breadcrumb, “Tara venue authoring”
      title, shell link, and V1 workflow link.
- [x] Asset tray, Stage/Scene graph, control lane, release readiness, manifest,
      and provenance inspector render as one responsive workspace.
- [x] The initial state is `draft`, with no publish ID or release stream.

### 3. Place and inspect assets

- [x] Select any of `threshold`, `mandala`, `north-grove`, or `sound-corner`.
- [x] Drag an asset or use its keyboard-accessible “Place in selected zone”
      button.
- [x] Placement updates the zone list, graph node/edge counts, and focal-asset
      readiness.
- [x] Selecting a graph node exposes its scope and incoming/outgoing edges.

### 4. Choose lighting and audio

- [x] Choose `dawn-soft`, `twilight-amber`, or `moonlit-blue`; kelvin and
      intensity update with the selected preset.
- [x] Choose `forest-drone`, `singing-bowl`, or `rain-texture`; rights and
      loudness metadata remain visible.
- [x] The internal `none` audio value is filtered out of the picker. Readiness
      requires `rights === 'cleared'`.

These controls choose authored fixture metadata; they do not fetch or preview
the underlying scene media.

### 5. Bind an interaction

- [x] Choose one of three triggers and one of three actions.
- [x] “Add binding” appends a row and clears the interaction readiness gate.
- [x] Any later authored change calls `revertToDraft`, clearing the prior
      publish ID, release stream, and error.

### 6. Configure capacity and run the modelled simulation

- [x] Select `stadium` and `interest-management`.
- [x] Run the 4,096-attendee simulation.
- [x] The pure client calculation reports accepted attendees, shard count, and
      interest cells; the covered configuration yields 4,096 accepted and 16
      shards.
- [x] `single-room` or `regional-fanout` leaves stadium interest-management
      readiness false.

This is a deterministic capacity model in the editor, not a load test against
4,096 real clients.

### 7. Clear accessibility readiness

- [x] Select `wcag-aa-cedar`, `comfort-reduced`, and `full-spatial-captions`.
- [x] Color, motion, and caption checks expose pass/fail text and remediation;
      color is not the only status channel.
- [x] A failing profile keeps the publish button disabled. Once all six
      readiness rows pass, `canPublish` becomes true.

The checker evaluates the scene's declared profile metadata. Downstream viewer
behavior still needs consumer-surface verification.

### 8. Inspect the manifest and provenance declarations

- [x] The read-only manifest summarizes placements, lighting, audio, bindings,
      capacity/sharding, simulation, accessibility, graph, branding, and the
      current local release branch.
- [x] `LilithProvenanceInspector` lists the fixture assets and their declared
      provenance chains.
- [ ] Resolve each provenance declaration to a signed, immutable asset record.
      The inspector is currently authored data, not a ledger readback.

### 9. Record the durable release receipt

- [x] Choose “Publish Tara venue” after readiness passes.
- [x] The editor POSTs `sceneId`, `title`, `capacityTier`, `shardCount`, and
      `manifestJson` to `/v1/admin/studio/scenes/publish`.
- [x] The BFF derives the owner from validated auth, bounds and validates the
      summary and JSON-object manifest, hashes the exact manifest bytes, and
      awaits a complete durable candidate save.
- [x] Only after a 201 response does the editor paint `published` and expose the
      stable returned `publishId` and `release-edition:<sceneId>:<digest>`
      string. An exact retry returns that same identity.
- [x] A BFF error keeps the editor in draft and renders the real failure.
- [x] The record is readable only by the exact owner, recovers after restart,
      and lists its manifest digest without exposing raw editorial JSON.

The exact editor manifest crosses the receipt boundary, including its authored
placements, readiness result, declared provenance, and scene graph. The store
does not resolve those declarations to immutable asset records or attach a
review approval, tenant/surface placement, or audit event. The route does not
call `admin-editorial-release-streams.ts`.

### 10. Re-edit after recording

- [x] Change any placement, preset, binding, capacity/sharding, or accessibility
      profile.
- [x] The browser returns to `draft` and clears the surfaced receipt.
- [ ] Withdraw or supersede the previously recorded BFF row. It remains in the
      durable owner list until retention or signed account erasure because there
      is no update/delete endpoint for an individual receipt.

### 11. Editorial approval — target handoff

- [ ] Create a review candidate from the full manifest and immutable asset
      references.
- [ ] Route it into the real editorial queue with author and source lineage.
- [ ] Run Sophia, Lilith, rights, accessibility, and provenance gates.
- [ ] Record human approve/request-changes/reject decisions against the same
      artifact identity.
- [ ] Promote only an approved edition to customer availability.

The current V1 workflow header link proves navigation to
`/studio/review-approval-workflows`; it does not link this scene record into
that evaluator or `/operator/studio`.

### 12. Consumer and audit readback — target handoff

- [ ] `/tara` reads the approved scene edition through a published-scene
      registry and exposes it as a venue without a fixture edit.
- [ ] `/lilith` includes the edition only when intentionally bound to its
      showcase.
- [ ] A customer reload/cold PWA launch sees the same edition under its
      entitlement and tenant policy.
- [ ] The audit explorer reconstructs author → readiness → review → release →
      customer publication with a verifiable provenance bundle.

## Post-conditions

- The editor has exercised every local readiness dimension and received a real
  durable BFF publish ID/release-edition string for the exact manifest.
- The BFF can recover and list that receipt for the exact owner after restart.
- Any subsequent edit returns the browser to draft without mutating the stored
  receipt.
- No claim is made that the receipt is audited, approved, supersedable, or
  visible on `/tara` or `/lilith`.

## Failure modes

- [x] **Viewer role** — the layout denies access before the editor mounts.
- [x] **Single-room stadium configuration** — simulation readiness remains false
      and publish stays disabled.
- [x] **Accessibility remediation outstanding** — failed rows explain the
      requirement and block publish.
- [x] **No rights-cleared audio** — readiness is false; the `none` value is not
      selectable through the UI.
- [x] **Keyboard cannot drag** — every asset has an equivalent placement button.
- [x] **Missing auth / wrong scope / malformed payload** — the BFF returns
      401/403/400 and the editor stays draft.
- [x] **Publish service failure** — the error is visible; no local success is
      fabricated.
- [x] **BFF restart** — real-PostgreSQL integration and exact-bundle process
      restart proofs recover the same receipt and manifest digest.
- [x] **Adjacent owner read** — exact-owner list scoping returns no receipt or
      raw manifest to another authenticated editorial principal.
- [x] **Erasure and stale completion** — signed generated-artifact erasure
      removes the exact owner and the recovered one-way fence rejects a retry.
- [ ] **Post-publish re-edit** — the old row is not withdrawn or superseded.
- [ ] **Crisis frame / tenant policy** — the scene-publish route does not
      consult either gate today.
- [x] **Oversized/malformed manifest** — non-object JSON, invalid JSON, and
      manifests over 256 KiB fail before acknowledgement.
- [ ] **Semantically unsafe manifest** — exact bytes are integrity-checked, but
      no complete immutable publication schema or asset resolver is applied.

## E2E coverage

- [`apps/oshun/web/e2e/lilith-scene-editor-smoke.spec.ts`](../../apps/oshun/web/e2e/lilith-scene-editor-smoke.spec.ts)
  drives the shell entry, authoring happy path, simulated capacity, blocked
  accessibility state, access denial, and publish-ready transition.
- [`apps/oshun/web/e2e/lilith-scene-editor-deep.spec.ts`](../../apps/oshun/web/e2e/lilith-scene-editor-deep.spec.ts)
  covers every editor control, drag and keyboard placement, graph inspection,
  manifest/provenance presentation, real-BFF publish, re-edit-to-draft, exact
  route offline replay, and mobile standalone overflow.
- [`apps/oshun/web/e2e/lilith-scene-publish.spec.ts`](../../apps/oshun/web/e2e/lilith-scene-publish.spec.ts)
  covers exact-manifest digest acknowledgement, stable replay, exact-owner list
  scoping, raw-manifest minimization, adjacent-owner isolation, 401/403/400
  gates, and the browser success receipt. Store and real-PostgreSQL suites cover
  commit ordering, restart, DSAR, retention, erasure, and its persistent fence.
- [`apps/oshun/web/e2e/studio-review-approval-workflows.spec.ts`](../../apps/oshun/web/e2e/studio-review-approval-workflows.spec.ts)
  covers the linked workflow evaluator as a separate surface; it does not
  approve this scene.
- **Coverage depth:** deep for local authoring and the durable owner receipt;
  absent for editorial linkage, audit/immutable-provenance records, supersede,
  and consumer publication.

## Per-view files touched by this journey

- [`customer/10-lilith/lilith-studio.md`](../customer/10-lilith/lilith-studio.md)
  — authoring shell.
- [`customer/10-lilith/lilith-studio-scenes.md`](../customer/10-lilith/lilith-studio-scenes.md)
  — scene editor.
- [`customer/03-tara/tara.md`](../customer/03-tara/tara.md) — future consumer
  readback.
- [`customer/10-lilith/lilith.md`](../customer/10-lilith/lilith.md) — optional
  future showcase binding.
- [`operator/operator-studio.md`](../operator/operator-studio.md) — future
  linked reviewer queue.
- [`shell/04-auth-session.md`](../shell/04-auth-session.md) — authoring gate.

## Cross-references

- [Living Scenes](../../V1/features.md#living-scenes) and
  [Review, Audit, Compliance, Rights, and Provenance](../../V1/features.md#review-audit-compliance-rights-and-provenance).
- [`editorial-review-approval.md`](./editorial-review-approval.md) — current
  operator release-stream seam and missing full lifecycle.
- [`scene-keep-and-share.md`](./scene-keep-and-share.md) — customer instances
  after a real publication path exists.
- Editor: `apps/oshun/web/src/app/lilith-studio/scenes/TaraSceneEditor.tsx`.
- Publish route/store: `apps/oshun/bff/src/routes/admin-studio-scene-publish.ts`
  and `apps/oshun/bff/src/studio/studio-scene-publish-store.ts`.
- Access gate: `apps/oshun/web/src/app/lilith-studio/layout.tsx` and
  `apps/oshun/web/src/lib/customer-role.ts`.

## Open questions / known gaps

- [x] Bind the owner receipt and exact manifest to durable persistence with
      restart, privacy, erasure, and retention proof.
- [ ] Validate immutable asset references, policy versions, and target
      tenant/surface against a complete publication schema.
- [ ] Link one scene identity through submission, automated checks, human
      review, audit events, provenance, and publication.
- [ ] Define supersede/withdraw behavior when an author edits after recording.
- [ ] Make `/tara` consume only approved scene editions and add browser
      readback.
- [ ] Add crisis-frame and tenant-policy checks to the publish boundary.
- [ ] Decide whether “Publish” should become “Record release receipt” until the
      durable receipt is linked to reviewed customer publication.
