scene-id-report.mdscene-id.md03-pwa-behavior.md04-auth-session.mdJourney flow#
Generated from the authored steps below — click a node to jump to that section.
The public Living Offering viewer is a real branch-driven server surface, not a single happy-path player. It distinguishes password, tenant, retired, transient outage, and playable outcomes; the playable branch serves attested APNG bytes, accessibility artifacts, embeds, reports, and short-lived downloads. Durable share metadata does not make every runtime artifact durable: materialized media bytes and download grants remain process-local.
Personas#
- Anonymous recipient — follows a public or private-link URL without an Oshun session.
- Password recipient — exchanges a shared password once, then revalidates through a short-lived HttpOnly unlock cookie.
- Tenant recipient — reaches a tenant-internal link and must enter through a tenant-aware surface rather than the anonymous viewer.
- Crawler or embed host — consumes robots/Open Graph/Twitter or embed/oEmbed metadata without receiving privileged content.
- Accessible-media user — relies on reduced motion, high contrast, transcript, caption, or audio-description metadata.
Pre-conditions#
/scene/<shortCode>is a public middleware path. The page server-fetchesGET /v1/living-scenes/public/:shortCodewithcache: 'no-store'.- A playable share requires a retained artifact, active share state, and the correct password/tenant conditions.
- When Postgres is configured, artifact/share/index/audit/takedown state is
wired through
wireDurableLivingSceneShares. Without that wiring, the same stores are process-local. - The share's robots policy determines whether the playable page is indexable; protected and non-playable branches are always noindex.
Steps#
1. Resolve the public branch#
The server resolves exactly one of the following outcomes:
| Branch | Viewer and recovery contract |
|---|---|
| Playable | Attested media, transcript, report, download, and copy actions render. |
| Password | A successful exchange sets a short-code-scoped unlock cookie. |
| Tenant auth | Tenant-access message; no anonymous media or download surface. |
| Tombstone | Retired offering after a definitive 4xx, missing, revoked, or deleted result. |
| Unavailable | Temporary 5xx/network outage with a real retry, never a false retirement. |
These rows map directly to the BFF resolution kinds playable,
password-required, tenant-auth-required, tombstone, and unavailable.
generateMetadata uses the share's Open Graph/Twitter/robots values only for a
playable branch. All non-playable branches currently share the generic title
“Living Offering Retired,” including password, tenant, and transient-unavailable
states; that metadata mismatch is a known gap.
2. Unlock a password-protected offering#
The raw password is posted to the unlock-token endpoint. A valid exchange mints an HMAC-signed, short-code-scoped token with a four-hour lifetime; the server action stores it in an HttpOnly path-scoped cookie. Wrong, missing, expired, or cross-scene tokens return to the password gate without leaking the media.
3. Render the playable offering#
The page displays tenant/default branding, public mark, privacy/rendition, C2PA
manifest and media-hash summary, and the exact materialized APNG from /media.
Reduced-motion CSS swaps the motion layer for the reduced artifact;
high-contrast CSS adds a stronger viewer outline. Captions, audio-description
metadata, and transcript download are exposed from the share resolution.
The keyboard-cue labels are rendered as buttons, but those buttons have no handlers. They are descriptive chrome today, not working playback shortcuts.
4. Copy, embed, download, or report#
ShareSettingsPanel copies the scene URL, iframe, and oEmbed snippets and
surfaces an explicit clipboard-denied state. Download creates a 15-minute grant
and redeems the same APNG bytes whose hash is carried by the C2PA manifest. The
report link opens the public abuse form; it does not require the viewer to be
signed in.
5. Revisit after lifecycle changes#
Revocation, originating-user deletion, or operator takedown turns the viewer into a tombstone and invalidates existing grants. A transient BFF failure stays an unavailable/retry state. The service worker treats API reads as network-only by default, so a first online visit does not establish a supported offline viewer guarantee.
Post-conditions#
- A playable viewer sees only the public artifact, branding, attestation, and accessibility artifacts authorized by that share.
- Password material is replaced by a scoped unlock token; the raw password is not stored in the cookie.
- A valid download grant redeems attested media while the share is active and the grant is unexpired.
- The viewer never claims an outage is a retirement, but its head metadata does not yet express every non-playable branch accurately.
Failure modes#
- Restart after durable share hydration — share/artifact metadata can
survive, but
shareMediaByIdanddownloadGrantsByIdare process-local maps and are cleared on hydration. The viewer can resolve as playable while/mediareturnsmedia_not_materialized; old grants never survive restart. - Invalid/expired/cross-scene unlock — returns to the password gate.
- Tenant-internal link without tenant context — renders “Tenant access required,” never public media.
- Clipboard denied — copy controls report an explicit unavailable status.
- Offline revisit — no supported cached media/API contract; the request may fail even after an earlier visit.
- Accessibility cue activation — the visible cue buttons currently do nothing.
- View analytics — there is no per-IP or per-share public view counter in this path; do not infer audience telemetry from page rendering.
E2E coverage#
apps/oshun/web/e2e/living-scene-card.spec.tscovers public attestation/noindex/tombstone, reduced motion, embed/copy, tenant gating, and delete cascade.apps/oshun/web/e2e/scene-password-and-grants.spec.tscovers password gates, scoped/expired tokens, embed protection, APNG grant redemption with matching media hash, report access, and deletion invalidation.apps/oshun/web/e2e/scene-viewer-deepening.spec.tscovers indexable metadata, high contrast, playable viewer actions, clipboard denial, and idempotent re-share behavior.- Coverage depth: deep for the online browser/API branches. Restart media recovery, offline replay, and functional cue shortcuts remain uncovered.
Per-view files touched#
customer/12-scene/scene-id.md— all viewer branches and playable chrome.customer/12-scene/scene-id-report.md— report continuation.shell/03-pwa-behavior.md— network/cache boundary.shell/04-auth-session.md— anonymous, password-token, and tenant-access distinctions.
Cross-references#
scene-keep-and-share.md— creation and revocation before/after this viewer.public-scene-abuse-report.md— public report continuation.offline-first-time-use.md— why API network-only policy matters.- Sources:
apps/oshun/web/src/app/scene/[id]/page.tsx,apps/oshun/web/src/lib/living-scenes-public.ts, andapps/oshun/bff/src/routes/living-scenes.ts.
Open questions#
- Should materialized media be snapshot/object-store durable, or rebuilt and re-hashed deterministically when a durable share hydrates?
- Should non-playable metadata distinguish password, tenant, retired, and transient-unavailable states?
- Should keyboard-cue buttons control playback, or render as non-interactive key labels until a controller exists?
- Is an explicit offline public-viewer product contract wanted, including revocation freshness and sensitive-cache policy?