V1 Web PWA · Surface walkthrough

Studio · Generation · Music

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

walked
8sections4 minread

On this page

Context. surface studio · domain generation · route /studio/generation/music · auth signed-in + creator (proxy-gated; not anonymous, not search-indexed) · source apps/oshun/web/src/app/studio/generation/music/page.tsx

Last walked. 2026-06-03 automated runtime probe (Playwright headless) — prod build + mock BFF; render, HTTP 200, server-rendered <h1>, 0 page errors verified. Evidence: WALKTHROUGH/results/walkthrough-runtime-probe-2026-06-03.md

Purpose#

The approved music generation surface (§24.6 ambient-audio / §24.8). Renders the rich MusicCard bound to the server's approved music workflow classes (GET /v1/isis/music/workflow-classes) and submits through POST /v1/isis/music/generate. The backend runs the workflow-class envelope guard + ambient-audio entitlement, then enqueues — fail-closed 503 until a music provider is configured. The client mirrors the same envelope guard (evaluateMusicRequestEnvelope) so out-of-envelope requests are surfaced before submit; every outcome is reported honestly.

Entry points#

  • Direct URL / bookmark/studio/generation/music (proxy-gated to authed creators; robots: noindex/nofollow/noarchive/nosnippet)
  • Studio shell navactive="studio" (shortcut 6), generation sub-area
  • Sibling generation surfaces — cross-linked from curated-cards / nyx-3d / living-scene

Layout regions#

  • Header: shell header (ShellLayout active="studio")
  • Main: <section data-music-studio>
    • <h1>Music Generation</h1> — page heading, rendered in all three states (error → inside data-music-studio-error; loading → inside data-music-studio-loading; populated → top of the studio section), plus a lede <p> "Generate ambient and contemplative music bound to the approved workflow classes. Inputs are envelope-guarded; outputs are provenance-tracked."
    • Consent panel (.panel, data-music-consent) — single rights/terms confirmation checkbox; gates the consentId passed to the card
    • MusicCard (via CardShell) — workflow-class picker + music inputs + live envelope verdict + preflight meta + Generate
    • Status line (.panel, data-music-status) after a submit attempt

States#

  • Loadingdata-music-studio-loading panel "Loading approved music workflow classes…" while the GET is in flight, or when the response lacks a card / provenance
  • Empty — N/A: the approved workflow-class set is server-authoritative
  • Populated — consent panel + MusicCard with the approved workflow classes filtered against MUSIC_WORKFLOW_CLASSES
  • Envelope deny (client) — when the current inputs violate WORKFLOW_CLASS_ENVELOPES[workflowClass], a data-card-issues list shows the violations and Generate is disabled (inputsValid === false)
  • Entitlement-denied / feature-unavailable — handled by CardShell (data-card-status), as on curated-cards
  • Submit accepted — "Accepted — queued for music generation."
  • Submit rejected (503) — "Music generation provider is not configured for this deployment yet."
  • Submit rejected (403) — "Not available: "
  • Submit rejected (422) — "The request is outside the approved envelope for this workflow class."
  • Error (load failed)data-music-studio-error "Music generation is unavailable right now: "
  • Offline — load GET fails → error panel; submit POST → "Submission failed."
  • Gated — proxy (creator) + ambient-audio entitlement (server)
  • Standalone PWA — renders within shell

Interactions#

  • Rights/terms consent (checkbox, data-music-consent-checkbox)
    • Function: toggles consentAccepted; sets consentId to consent-music-<userId> when accepted (empty otherwise), and builds the ConsentConfirmation for preflight
    • Keyboard: Space toggles; first in tab order
    • Screen reader: announces "I confirm I have rights to any reference inputs and accept the curated-generation terms."

MusicCard inputs (all re-evaluate the envelope verdict live):

  • Workflow class (approved) (select, data-field="workflowClass") — options filtered to the intersection of the server's approved classes and MUSIC_WORKFLOW_CLASSES; selecting one resets tempo/duration defaults to the class envelope mid-points
  • Mood (select, data-field="mood") — calm / reflective / invitational / cinematic / devotional
  • Tempo (BPM) (number, data-field="tempoBpm") — min/max bound to [envelope.minTempoBpm, envelope.maxTempoBpm]; label shows the envelope
  • Duration (s) (number, data-field="durationSeconds") — bound to [envelope.minDurationSeconds, envelope.maxDurationSeconds]
  • Loopable (checkbox, data-field="loopable") — disabled unless envelope.loopable === 'optional'; label shows the envelope rule
  • Key signature (select, data-field="keySignature") — C-major / A-minor / D-major / G-major / E-minor / F-major / D-minor
  • Direction (textarea) — regenerate steer
  • Generate (button, data-card-action="generate")
    • Function: submit(request)POST /v1/isis/music/generate with the full MusicGenerationRequest (workflowClass, mood, tempoBpm, durationSeconds, loopable, keySignature, tenantId, userId, consentId)
    • Disabled when: envelope deny / preflight blocked / no consent / busy
  • Regenerate with direction, Variant compare, Send to editorial, Takedown — shared CardShell controls (the last two are () => undefined here)

Data & contracts#

  • Reads: GET /v1/isis/music/workflow-classes{ workflowClasses: MusicWorkflowClass[], creatorTier, card: CardSpec | null, provenance: ProvenancePreview | null }
  • Writes: POST /v1/isis/music/generateMusicGenerationRequest; fail-closed 503 until a provider is configured (Suno is the registered provider when OSHUN_SUNO_API_KEY is set)
  • Realtime: None.
  • Caching: client fetch on mount
  • Auth/role check: proxy (creator) + ambient-audio entitlement (server) + workflow-class envelope guard (evaluateMusicRequestEnvelope) client + server
  • Contracts: @oshun-web/isis-music-generation (MUSIC_WORKFLOW_CLASSES, WORKFLOW_CLASS_ENVELOPES, evaluateMusicRequestEnvelope, MusicGenerationRequest, MusicWorkflowClass), @oshun-web/isis-curated-cards (CardSpec, ConsentConfirmation, ProvenancePreview, PENDING_COST_COEFFICIENTS)

Cross-references#

Open questions / known gaps#

  • tenantId is '' and userId defaults to 'me' in MusicStudio — confirm both are meant to resolve from the session/proxy.
  • onSendToEditorial / onTakedown are () => undefined; editorial routing from this surface is not wired.