V1 Web PWA · Surface walkthrough

Studio Aja · Content Watermarking

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

walked
8sections3 minread

On this page

Context. surface studio · domain aja · route /studio/aja/content-watermarking · auth signed-in + studio entitlement · source apps/oshun/web/src/app/studio/aja/content-watermarking/page.tsx

Last walked. 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; body re-derived 2026-06-03 from current source (lane-console architecture)

Purpose#

Admin lane console for the real @aja/content-watermarking MotionWatermarker payload codec. The operator fills a provenance / leak-tracing payload (watermark id, content id, owner id, ISO-8601 timestamp, optional custom JSON) and encodes it into watermark bytes plus an integrity checksum; a second action decodes those bytes back to the original payload to confirm round-trip detection.

Entry points#

  • Direct URL / bookmark/studio/aja/content-watermarking; metadata canonical to this path
  • Studio nav — Domain-bridge studios section of /studio
  • Breadcrumb parent/studio/aja/content-security (declared in the page.tsx breadcrumb <ol>)
  • Sibling quick-actions on this page: Content Security, Content Moderation, Privacy Protection, Data Retention, Back to Studio
  • Operator surfacing — see ../../studio-overview.md

Layout regions#

page.tsx renders inside <ShellLayout active="studio">:

  • Breadcrumb panel (data-aja-content-watermarking-breadcrumbs): <nav aria-label="Aja Content Watermarking breadcrumbs">Studio / Aja Content Security / Content Watermarking
  • Workspace (<StudioAjaContentWatermarkingWorkspace />, archetype: LEAF):
    • <h1> (WorkspaceHeading) "Aja Content Watermarking Workspace"
    • Summary <p data-aja-cw-summary> — encode a payload into watermark bytes (with checksum) and decode bytes back
    • The encode form lane + the encoded/decoded result blocks
  • Route Map panel (data-aja-content-watermarking-route-map): <h2>Route Map</h2> listing 6 entries from STUDIO_AJA_CONTENT_WATERMARKING_ROUTE_MAP (primary, rules, traces, packages, parity, governance)
  • Quick-action panel: five Link.quickAction anchors — Content Security, Content Moderation, Privacy Protection, Data Retention, Back to Studio

States#

  • Loading — GETs the codec catalog on mount; renders <p data-aja-cw-loading> "Loading watermark codec…"
  • Unauthorized — 401/403 renders data-aja-cw-unauthorized ("Access restricted." + admin-scope message, default "Aja workspace scope required to view content watermarking.")
  • Error — non-OK / malformed / unreachable renders data-aja-cw-error ("Could not load content watermarking." + reason)
  • Ready (form) — success renders the data-aja-cw-encode-form
  • Encoded — a successful encode renders data-aja-cw-encoded with data-aja-cw-checksum, data-aja-cw-bytelength, and a data-aja-cw-decode-submit button
  • Decoded — a successful decode renders data-aja-cw-decoded with data-aja-cw-detected and (if present) data-aja-cw-recovered (recovered owner / content)
  • Action error — invalid custom JSON, missing required fields, decode without an encode, or POST failure renders data-aja-cw-action-error
  • Empty / Standalone PWA / offline — N/A beyond the above; shell SSR, lane is a client fetch on mount

Interactions#

Encode lane (data-aja-cw-encode-form)#

  • Watermark id (data-aja-cw-field-id, input, label "Watermark id")
  • Content id (data-aja-cw-field-content, input, label "Content id")
  • Owner id (data-aja-cw-field-owner, input, label "Owner id")
  • Timestamp (data-aja-cw-field-timestamp, input, label "Timestamp (ISO-8601)")
  • Custom data (data-aja-cw-field-custom, input, label "Custom data (JSON, optional)")
  • "Encode watermark" (data-aja-cw-encode-submit, submit) — fires POST /v1/admin/aja/content-watermarking/encode with { id, contentId, ownerId, timestamp, customData? }
  • "Decode it back" (data-aja-cw-decode-submit, button) — fires POST /v1/admin/aja/content-watermarking/decode with the encoded { dataBase64 }

Route Map panel#

  • Route entries (6 × <article>) — non-interactive path+purpose

Quick-action panel#

  • "Open Aja Content Security workspace"/studio/aja/content-security
  • "Open Aja Content Moderation workspace"/studio/aja/content-moderation
  • "Open Aja Privacy Protection workspace"/studio/aja/privacy-protection
  • "Open Aja Data Retention workspace"/studio/aja/data-retention
  • "Back to Studio workspace index"/studio

Data & contracts#

  • Reads: GET /v1/admin/aja/content-watermarking on mount — catalog { payloadFields: string[], codec }
  • Writes:
    • POST /v1/admin/aja/content-watermarking/encode{ encoded } (dataBase64, byteLength, checksum)
    • POST /v1/admin/aja/content-watermarking/decode{ detected, payload }
  • Realtime: none
  • Caching: client fetch on mount with cache: 'no-store' and buildBffAuthHeaders(); SSR shell only
  • Auth/role check: BFF endpoints admin-scoped + fail-closed (401/403 → unauthorized render); route behind the signed-in + studio proxy gate

Cross-references#

Open questions / known gaps#

  • The decode action requires an in-session encode first (it reuses the encoded dataBase64); there is no standalone "paste bytes to decode" path
  • Route-map sub-routes are advertised but have no page.tsx in V1