Context. surface customer · domain scene · route /scene/[id]/report · auth anon or signed-in · source apps/oshun/web/src/app/scene/[id]/report/page.tsx
Last walked. 2026-06-28 focused automated addendum — default form state, reason options, optional detail/maxLength, absence of contact/cancel fields, back-link href, submit-enabled in-flight behavior, recoverable 503 failure, browser-offline failure, anonymous success, signed-in receipts, and operator inbox/decision read-back covered in public-scene-abuse-report.spec.ts. 2026-06-26 signed-in reporter addendum — PublicSceneReportForm now includes the member access token when AuthProvider is authenticated; BFF stamps reporterUserId from the validated bearer and /profile/safety displays the receipt. Evidence: public-scene-abuse-report.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#
Anonymous-or-signed-in abuse / safety-report form for a public living offering.
Renders the PublicSceneReportForm client component and a "Back to offering"
link. Reports route to Lilith review with the share code, reason, page context,
and the validated reporter subject when the viewer is signed in.
/scene is in apps/oshun/web/src/proxy.ts PUBLIC_PATHS — anyone with the
share code can submit a report without signing in.
Entry points#
- "Report" action on the full scene viewer (
/scene/<id>accent-coloured<Link>) - Direct URL — anyone with the path can open the form
- Email / external link to "Report this scene"
- Direct URL / bookmark — yes (anon)
Layout regions#
page.tsx renders a single <main> with a centred 80svh content grid:
- Eyebrow:
Living Offering <params.id>(mono caps, teal) - Title:
Report this offering(5xl serif) - Body paragraph: "Reports route to Lilith review with the share code, reason, and page context."
<PublicSceneReportForm shortCode={params.id} />: the actual form composition (lives inapps/oshun/web/src/app/scene/[id]/report/PublicSceneReportForm.tsx)- "Back to offering" (Link) →
/scene/<id>
States#
- Default — form renders with the Reason select defaulting to
privacyand an empty Detail textarea - Submitting —
onSubmitis async with no in-flight disable/spinner; the button stays enabled whilesubmitPublicLivingSceneReportawaits - Submitted successfully — no redirect; the
aria-live="polite"role="status"line updates inline to "Report sent to review." - Submit failed (recoverable) — same inline status line shows "Report could not be sent."; the form stays on-page for retry
- Validation — none beyond
maxLength=2000on Detail; Reason always has a value (defaulted), Detail may be empty - Offline —
fetchrejects → caught → "Report could not be sent." status - Standalone PWA — verify form renders cleanly
Interactions#
Page-level: one navigation link.
- "Back to offering" (Link) →
/scene/<id>- Keyboard: Tab focusable; Enter activates
Form-level (inside PublicSceneReportForm):
- Reason — a
<select>(not radios/chips) with six options:privacy(default),self-harm,harassment,copyright,misinformation,other - Detail — a
<textarea maxLength={2000}>for additional context - "Send report" — primary submit; calls
submitPublicLivingSceneReport({ shortCode, reporterUserId: null, reason, detail, accessToken });accessTokenis present only when AuthProvider is authenticated - Inline status —
aria-live="polite"role="status"line below the button that surfaces the success / failure message - No reporter-contact (email) field and no cancel/clear button exist; the only way back is the page-level "Back to offering" link above the form
Data & contracts#
- Reads: none (page is static aside from the
params.idinterpolation) - Writes:
submitPublicLivingSceneReport()(@/lib/living-scenes-public~188) →POST /v1/living-scenes/public/<shortCode>/report(singularreport, ~196) with a JSON body{ reporterUserId, reason, detail }and an Authorization bearer when signed in. The BFF stampsreporterUserIdfrom the validated bearer when present and uses the nullable body field only for anonymous/back-compat submissions. - Realtime: none
- Caching: SSR static
- Auth/role check: anon allowed (
/sceneis insrc/proxy.tsPUBLIC_PATHS); signed-in sessions attach the member bearer for receipt tracking. - Metadata:
title: 'Report Living Offering'(bare; the| OSHUNsuffix comes from the root layout'stitle.template = '%s | OSHUN'),robots: { index: false, follow: false }
Automation Evidence#
apps/oshun/web/e2e/public-scene-abuse-report.spec.tsrenders the public form defaults, constraints, back link, in-flight state, and failure statusan anonymous visitor reports a shared offering and it routes to reviewa report with a reason but no detail is still accepteda self-harm report appears as an S1 (critical) auto INC with the scene deep link- operator resolve/dismiss API read-back and signed-in reporter receipt tests
Cross-references#
- Sibling scene routes:
- Lilith review (operator surface): out-of-scope here; reports route into the moderation queue
- Component sources:
apps/oshun/web/src/app/scene/[id]/report/page.tsxapps/oshun/web/src/app/scene/[id]/report/PublicSceneReportForm.tsxapps/oshun/web/src/lib/living-scenes-public.ts(submitPublicLivingSceneReport)
Open questions / known gaps#
- Resolved: fields enumerated — Reason
<select>(privacy/self-harm/ harassment/copyright/misinformation/other, defaultprivacy) + Detail<textarea maxLength=2000>; submits toPOST /v1/living-scenes/public/<shortCode>/report - Confirm where reports are stored and how Lilith review is notified (operator side)
- Resolved: anonymous reporters cannot include a contact email — the form
sends
reporterUserId: nulland exposes no contact field; signed-in identity is derived from the validated bearer rather than a visible field - Resolved: post-submit UX — no redirect/reset; an inline
aria-livestatus line shows "Report sent to review." or "Report could not be sent." - Confirm rate limiting and abuse protection on the report endpoint (anonymous submissions are abuse-prone)
- No CAPTCHA visible at the page level — verify whether one is added inside the form