# Generation Audience Tiers

Every AI generation in V1 — a curated devotional image, a narrated contemplative
arc, an instrumental ambient bed, a creator's raw ComfyUI graph, an operator's
RunPod dashboard — is gated by a single, deterministic **tier resolver** before
a pixel or sample is produced. This page documents the canonical tier taxonomy,
the 28 named generation surfaces and their per-tier allowlists, the enforcement
spine a request crosses (entitlements → Lilith → Isis → provider → provenance →
audit), and the real, provider-gated execution substrate behind it. It serves
product, platform, and operator readers who need to know exactly what a given
audience can do and where the fail-closed boundaries sit. It lives in the
generation-pipeline area alongside [Agentic AI Studio](./agentic-ai-studio.md)
and [Living Scenes](./living-scenes.md), and rests on the
[Isis — Generation Control Substrate](./substrate-isis.md).

> Product scope:
> [`V1/features.md` § Generation Audience Tiers and Surface Boundaries](../features.md#generation-audience-tiers-and-surface-boundaries).

## The canonical tier taxonomy

V1 has **four** generation audience tiers. The single source of truth is the
`GenerationTier` union in `libs/isis/entitlements/src/generation-tier.ts` (lines
23–28), frozen as the `GENERATION_TIERS` array:

```ts
type GenerationTier =
  | 'operator-admin'
  | 'aaa-creator'
  | 'curated-creator'
  | 'contemplative';
```

These four code-level identifiers are the canonical taxonomy. Earlier prose
(`V1/features.md–3230`) named the tiers `Customer`, `Curated-Creator`,
`AAA-Creator`, and `Operator` and claimed all four were "used verbatim" — but
two of those do **not** match the implementation. The mapping below reconciles
the product-facing labels with the enforced code identifiers:

| Product-facing label | Enforced `GenerationTier` | Who it is                                                                                      |
| -------------------- | ------------------------- | ---------------------------------------------------------------------------------------------- |
| Customer             | `contemplative`           | The default consumer of finished, curated products — no raw generation surfaces.               |
| Curated-Creator      | `curated-creator`         | A creator working only inside curated workflow classes — no raw model picker, no Civitai.      |
| AAA-Creator          | `aaa-creator`             | A power creator with the full graph editor, Civitai browser, LoRA training, model merging, 3D. |
| Operator             | `operator-admin`          | Platform staff: full surface set plus admin-only review queues, RunPod, audit, node registry.  |

Free-versus-paid is a subscription distinction **within** the `contemplative`
(Customer) tier, not a fifth tier. The resolver knows nothing about billing; it
reads entitlement tags only.

### How a tier is resolved

`resolveGenerationTier(entitlement)` (line 134) is the deterministic resolver
that BFF, Admin, and Studio middleware all consult before rendering any
generation surface. It takes a `GenerationEntitlement` —
`{ id, tenantId, userId, persona, tags }` — and returns a `ResolvedTier` of
`{ entitlement, tier, surfaceAllowlist }`. Resolution is a strict, ordered
precedence over the normalized tag set (`resolveTierFromTags`, line 143):

1. tag `operator-admin` present → `operator-admin`;
2. else tag `aaa-creator` → `aaa-creator`;
3. else tag `curated-creator` → `curated-creator`;
4. else → `contemplative` (the deny-by-default floor).

Tags are trimmed, empties dropped, and a non-array input degrades safely to an
empty set (`normalizeEntitlementTags`), so a malformed entitlement falls to
`contemplative` rather than silently escalating. This is the **why** behind the
ordering: the most privileged tier wins only on an explicit positive tag, and
the absence of any recognized tag always lands a user on the smallest surface
set.

## The 28 generation surfaces

The tier vocabulary is not abstract — it resolves to a frozen catalog of **28**
named `GenerationSurface` values (`GENERATION_SURFACE_VALUES`, lines 35–68,
exported frozen as `GENERATION_SURFACES`). Each surface is a concrete UI or
capability that the resolver either grants or denies. The canonical list,
grouped by the tier band that introduces it:

| Band                        | Surfaces                                                                                                                                                                                                                                                                                                             |
| --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Contemplative (curated)     | `curated-image`, `curated-living-scene`, `curated-voice-clip`                                                                                                                                                                                                                                                        |
| Curated-creator             | `curated-workflow-pick`, `curated-asset-search`                                                                                                                                                                                                                                                                      |
| AAA-creator                 | `graph-editor`, `civitai-search`, `civitai-lora-hash-picker`, `lora-trainer`, `model-merger`, `model-comparison`, `runpod-region-selector`, `gpu-worker`, `multi-gpu-orchestration`, `gaussian-splatting`, `auto-rigging`, `topaz`, `rife`, `animatediff`, `voice-cloning-tool`, `music-generation`, `3d-generation` |
| Operator-admin (admin-only) | `runpod-dashboard`, `intake-review-queue`, `lora-training-queue`, `output-gallery-admin`, `comfyui-node-registry`, `audit-trail`                                                                                                                                                                                     |

### Per-tier allowlists

`TIER_ALLOWLISTS` (lines 87–126) is a frozen
`Record<GenerationTier, GenerationSurface[]>` that binds each tier to exactly
the surfaces it may reach. The bands are cumulative: `aaa-creator` inherits the
contemplative and curated-creator surfaces and adds the heavy creative tooling;
`operator-admin` is the full `GENERATION_SURFACES` set (so it includes every
admin-only review and infrastructure surface). The exact grants:

| Tier              | Surface count | Surfaces granted                                                                         |
| ----------------- | ------------- | ---------------------------------------------------------------------------------------- |
| `contemplative`   | 3             | `curated-image`, `curated-living-scene`, `curated-voice-clip`                            |
| `curated-creator` | 5             | the 3 contemplative surfaces + `curated-workflow-pick`, `curated-asset-search`           |
| `aaa-creator`     | 22            | the 5 curated surfaces + all AAA-creator surfaces (graph editor through `3d-generation`) |
| `operator-admin`  | 28            | all of `GENERATION_SURFACES` (everything, including the 6 admin-only surfaces)           |

The `contemplative` floor is deliberately narrow: a Customer can only ever touch
finished, curated products — never a raw model picker, a graph editor, or
Civitai.

### Surface access is deny-by-default

`checkSurfaceAccess({ entitlement, surface })` (line 180) is the guard every
surface lookup calls. It resolves the tier, then returns a
`SurfaceAccessVerdict`:

- `{ verdict: 'allow', tier }` when the surface is on the resolved allowlist;
- `{ verdict: 'deny', tier, action: { kind: '404-hard-block' } }` otherwise.

The verdict type also allows a softer `{ kind: '404-with-aaa-cta' }` action, but
`checkSurfaceAccess` itself never issues it — CTA handling is reserved for
product-shell boundary guards that can prove the caller is _already_ entitled to
the surface but reached it from the wrong host app. Surface access in isolation
is strictly deny-by-default: an unknown or unentitled surface yields a plain
404, not an upsell.

## Where each tier actually lives

| Tier              | Product shell                                                                                                                       | Capability cap                                                           |
| ----------------- | ----------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------ |
| `contemplative`   | Living Offerings (Arete), Contemplative Arcs (Tara), Grounded Explainers (Veritas), Sky Briefings (Nyx), Lesson Visualizers (Metis) | Tone-gated; no raw graph editor; provenance always on.                   |
| `curated-creator` | `apps/oshun/web/src/app/studio/generation` + `studio/generation-gallery`                                                            | Curated workflow classes only; no raw model picker, no Civitai access.   |
| `aaa-creator`     | `apps/yemaya/studio-web` + `apps/yemaya/studio-desktop` (Yemaya Studio)                                                             | Full graph editor, Civitai browser, LoRA training, model merging, 3D.    |
| `operator-admin`  | `apps/oshun/admin/` with `@oshun/generation-control-isis`                                                                           | Workflow graph editor, intake review queues, RunPod power-user surfaces. |

### The contemplative ↔ Yemaya AAA Studio boundary

The legacy customer-facing tree under `apps/oshun/web/src/app/studio/isis/*` is
now **fail-closed**. `libs/isis/entitlements/src/studio-boundary.ts` exports
`STUDIO_ISIS_ALLOWED_ROUTE_SEGMENTS` as an **empty** frozen array — so
`isAaaOnlyRoute()` treats every non-empty legacy `isis` segment as AAA-only. The
approved customer-facing generation surfaces live under `/studio/generation/*`
and `/studio/generation-gallery`, not under the legacy provider-machinery tree.

This corrects a stale claim: earlier docs said AAA-tier `studio/isis/*` routes
return "disclosure + Yemaya signup gate." In reality, because the allowlist is
empty, those legacy segments **hard-block to 404** for a contemplative user.
`resolveStudioBoundary({ routeSegment, entitlement })` only emits the
`render-yemaya-cta` outcome (disclosure copy + `/aaa-upgrade` link) when the
caller is _already_ an `aaa-creator` or `operator-admin` who landed on the wrong
shell; everyone else gets `hard-block-404`. The `AAA_ONLY_STUDIO_ROUTES` catalog
(e.g. `3d-generation`, `lora-training`, `model-merging`, `music-generation`,
`multi-gpu-orchestration`, `comfyui-nodes`, `text-to-speech`) is retained for
documentation, tests, and operator diagnostics — not as a live allowlist.

A Yemaya output can flow _back_ into the contemplative product through the
editorial pipeline. `YemayaPromotionRequest` (`studio-boundary.ts:101`) posts to
`/api/isis/output-gallery/promote` with a `proposedCardKind` restricted to
`curated-image | curated-living-scene | curated-voice-clip | curated-workflow-pick`;
`validatePromotionRequest` rejects missing output ids, tenants, authors, notes,
or a non-curated card kind before forwarding to the §16 editorial lifecycle.

## Generation request flow

A generation request crosses the same enforcement spine regardless of tier:
entitlements gate the surface, Lilith gates the tone and crisis frame, Isis
dispatches against a versioned workflow template, the provider executes
sandboxed, and a `ProvenanceBundle` + watermark + audit record are produced
before the response returns. The provider node is intentionally drawn with the
**hosted** adapters that the live customer-facing executors actually call
(Stability, ElevenLabs, Suno, fal.ai), not the operator substrate
(RunPod/ComfyUI) — see
[Why the provider node is hosted, not ComfyUI](#why-the-provider-node-is-hosted-not-comfyui).

```mermaid
sequenceDiagram
    autonumber
    actor U as User / Creator
    participant BFF as BFF
    participant E as Entitlements
    participant L as Lilith<br/>(tone · crisis)
    participant I as Isis Control Plane
    participant P as Provider<br/>Stability · ElevenLabs · Suno · fal.ai (LTX)
    participant Pr as Provenance
    participant A as Audit

    U->>BFF: Generate request (prompt, surface, tier)
    BFF->>E: resolveGenerationTier + checkSurfaceAccess
    E-->>BFF: allow / deny (404-hard-block)
    BFF->>L: Tone band + crisis-frame check
    L-->>BFF: directive (allow / reduced / suppress)
    BFF->>I: Dispatch with WorkflowTemplate + ModelVersion
    I->>P: Execute (sandboxed, env-gated provider)
    P-->>I: Output (audio / image / video)
    I->>Pr: Build ProvenanceBundle<br/>consent · prompt · model · watermark · timestamp
    Pr-->>I: bundleRef
    I->>A: Audit generation (bundleId, actor)
    I-->>BFF: result + bundleRef + releaseMeasurement
    BFF-->>U: result (watermarked · C2PA manifest) or fail-closed block
```

### The BFF generation executors

The concrete request handlers live in `apps/oshun/bff/src/generation/`. Each is
a real executor paired with a `*-provider-env.ts` resolver and a test:

- **image** (`image-executor.ts`) — text-to-image;
- **narration** (`narration-executor.ts`) — TTS;
- **music** + **music-enqueue** (`music-executor.ts`,
  `music-enqueue-executor.ts`) — batch ambient/instrumental music;
- **video** (`video-executor.ts`) — text-to-video and image-to-video;
- **caption-dub** (`caption-dub-executor.ts`) — captioning + dubbing;
- **accessibility-pass** (`accessibility-pass-executor.ts`);
- **explainer** (`explainer-executor.ts`);
- **sky-briefing** + **sky-briefing-enqueue** (`sky-briefing-executor.ts`);
- **curated-generation** (`curated-generation-executor.ts`);
- **realtime-music** (`realtime-music-route.ts`) — the live streaming path.

Every executor routes its output through a **release measurement**
(`provider-measurement.ts` → `buildReleaseMeasurement`) that
`evaluateGenerationRelease` (`release-gate.ts:116`) grades into one of three
`GenerationReleaseStatus` values — `complete`, `needs_review`, or `blocked`. The
gate is fail-closed: a result with no measurement, a malformed measurement, or a
missing governance signal returns `blocked` with a specific reason (e.g.
`governance_measurement_absent`, `governance_measurement_invalid`). Two output
classifiers gate content before release: `image-safety-classifier.ts` scans
image URLs and `text-safety-classifier.ts` scans spoken/explainer text. When a
scanner is absent or its scan throws, the safety score is `null` and the gate
**blocks** — an unscanned output is never released ungoverned.

## The live providers (env-gated, fail-closed by design)

Every live provider call is environment-gated and fail-closed. With no
credential the resolver returns `null`, the executor never receives a `generate`
function, and the job fails closed with `provider_not_configured` — never a
fabricated result. Per their own source comments, the HTTP paths to each hosted
provider are "exercised at deploy time with a live key," not in default CI; the
env→provider wiring, request/result adaptation, and measurement emission _are_
unit-tested.

| Output kind    | Live provider                  | Adapter symbol & path                                                   | Required env                                                   |
| -------------- | ------------------------------ | ----------------------------------------------------------------------- | -------------------------------------------------------------- |
| Image          | Stability SD3.5 (hosted)       | `StabilityProvider` — `@isis/ai-providers/providers/image-generation`   | `OSHUN_STABILITY_API_KEY` (or `STABILITY_API_KEY`)             |
| Voice / TTS    | ElevenLabs                     | `createElevenLabsProvider` — `@psyche/voice-synthesis`                  | `OSHUN_ELEVENLABS_API_KEY` **and** `OSHUN_ELEVENLABS_VOICE_ID` |
| Batch music    | Suno                           | `SunoProvider` — `@isis/audio-generation/generation`                    | `OSHUN_SUNO_API_KEY`                                           |
| Realtime music | Google Magenta RealTime (MRT2) | `MagentaRtProvider` over `@euterpe/providers` / `@euterpe/realtime-gen` | `OSHUN_MRT2_ENABLED=true` + on-device runtime loads            |
| Video          | fal.ai-hosted LTX-Video        | `LTXProvider` — `@isis/ai-providers/providers/video-generation`         | fal.ai key                                                     |

### The real env-var contract

These are the deploy-time toggles that flip a surface from fail-closed to live:

- **Image** — `OSHUN_STABILITY_API_KEY` is required; `OSHUN_STABILITY_MODEL`
  overrides the default `sd3.5-large`. Accepted aspect ratios are `1:1`, `16:9`,
  `9:16`, `4:3`, `3:4`, `21:9`, `9:21`, `3:2`, `2:3`; anything else is coerced
  to `1:1` (`image-provider-env.ts`).
- **Voice** — _both_ `OSHUN_ELEVENLABS_API_KEY` and `OSHUN_ELEVENLABS_VOICE_ID`
  are required; either missing returns `null`. Narration uses a fixed,
  deploy-configured, platform-licensed voice — **not** a per-request clone — so
  the `cloned-voice-used` human-review trigger does not apply
  (`narration-provider-env.ts`).
- **Batch music** — `OSHUN_SUNO_API_KEY` is required; `OSHUN_SUNO_MODEL_VERSION`
  selects `v3 | v3.5 | v4 | v5` (default model from the provider);
  `OSHUN_SUNO_BASE_URL` is an optional override. Curated music is instrumental
  (no lyrics/vocals), and there is no in-repo audio-content scanner, so its
  release measurement carries `safetyScanScore: null` and **blocks** at the
  audio safety floor until a deploy-bound audio scanner, watermarker, and C2PA
  signer are wired (`music-provider-env.ts`).
- **Realtime music** — gated by `OSHUN_MRT2_ENABLED=true` _and_ a successful
  `runtime.load()`. The runtime is the official-engine Python sidecar when
  `OSHUN_MRT2_SIDECAR` is set (`OSHUN_MRT2_PYTHON`, `OSHUN_MRT2_TIER` of `230m`
  | `2.4b`), otherwise the native (Rust) on-device engine. If no inference
  backend or weights are present, `load()` reports `not_configured`, the
  resolver returns `null`, and the realtime route serves a `503` — never a fake
  stream (`realtime-music-provider-env.ts`).

### Realtime music is a distinct generation mode

The batch pipeline is admit → enqueue → worker → `{ id, url? }`. Realtime music
(MRT2) is fundamentally different: a long-lived, frame-level interactive session
where control flows in and audio frames flow out for the life of a socket
(`realtime-music-route.ts`). `buildSource` drives a `GenerationSession` one
block at a time — 48 kHz stereo PCM, an ~8-token-per-frame budget, a ~2.667 ms
frame budget — pushing each frame to an `audioSink` that the route forwards on
the WS `generation-audio` channel. Each tick layers the _current_ live
conditioning (text/MIDI/audio-ref updates from the control channel) over the
request's initial prompt. The loop ends the moment the client disconnects
(`isActive()` returns false) or the engine stops producing audio — terminating
the stream. This streaming mode is omitted from the prose music section in
`features.md`.

### Why the provider node is hosted, not ComfyUI

ComfyUI on RunPod is the **operator substrate** — the heavy GPU execution
environment AAA creators and operators drive through `graph-editor`,
`gpu-worker`, `multi-gpu-orchestration`, and `runpod-dashboard`. But the live,
customer-facing executors call **hosted HTTP providers** directly: Stability for
image, ElevenLabs for voice, Suno for batch music, fal.ai's LTX-Video for video.
A mermaid label of "ComfyUI · ElevenLabs · Suno" is therefore incomplete for the
customer path — image goes to `StabilityProvider`, video to `LTXProvider`, and
ComfyUI/RunPod sit behind the AAA-creator surfaces, not the default executor
flow.

## The provider adapter library

The full adapter catalog lives in `libs/isis/ai-providers/src/providers/`, one
subdirectory per capability: `animation`, `civitai`, `comfy`, `comfy-cloud`,
`controlnet`, `conversational-ai`, `florence`, `image-generation`, `instantid`,
`ip-adapter`, `live-preview-streaming`, `llm`, `model-registry`,
`multi-gpu-orchestration`, `music-generation`, `three-d`, `tts`, `usage`,
`video-generation`, `video-processing`, and `workflow-versioning`. The audio
provider set lives separately in `libs/isis/audio-generation/src/generation/`:
`suno-provider.ts`, `udio-provider.ts`, `self-hosted.ts`, `sfx-provider.ts`,
`music-generator.ts`, plus `audio-analysis.ts`.

Two accuracy notes on the music provider list. First, earlier docs described the
music abstraction as "MusicGen, Suno, Udio, Stable-Audio, custom-on-Comfy"; the
real files are `suno-provider.ts`, `udio-provider.ts`, `self-hosted.ts`,
`sfx-provider.ts`, and `music-generator.ts`. There is **no** provider file named
for MusicGen or Stable-Audio, and the realtime Magenta RT path is omitted from
that list. Second, although deps§9 lists both Suno _and_ Udio as V1-used, **only
Suno** is wired into the BFF batch music executor (`SunoProvider`,
`OSHUN_SUNO_API_KEY`, `OSHUN_SUNO_MODEL_VERSION`); `udio-provider.ts` exists as
an adapter but is not customer-path-wired. The docs imply a Suno/Udio parity
that the BFF wiring does not have.

The `@isis/music-generation` library ("provider abstraction, workflow classes,
watermark + provenance" — §24.8) enforces per-class MIME guardrails in
`guardrails.ts`: each workflow class declares an `allowedMimeTypes` list drawn
from `audio/wav`, `audio/mpeg`, `audio/ogg`, and `audio/flac`, and a request
whose `mimeType` is not in its class list is rejected before generation.

## The output gallery

`@isis/output-gallery` ("filters, lineage, branch/replay, compare grid, bulk
actions" — §24.10) is the unified review surface for generated outputs. Its real
typed contracts (`libs/isis/output-gallery/src/`) are richer than the prose
describes:

- **Compare grid** (`compare-grid.ts`) — `buildCompareGrid` produces a typed
  `CompareGridLayout` of `2-up | 4-up | n-up` (capped at 16 slots,
  `MAX_N_UP_SLOTS`). Each diff pair carries a `DiffMetric` typed _per asset
  class_: `pixel-delta` (mean absolute delta) for image, `frame-delta` for
  video, `audio-rms-delta` (RMS delta in dB) and `waveform-delta` (correlation
  coefficient) for audio, and `mesh-vertex-delta` (Hausdorff distance) for 3D.
  Mixing incompatible kinds throws `CompareGridError` with code `mixed-kinds`.
- **Branch / replay-with-tweak** (`branch-replay.ts`) — branching is **not**
  free-form. `validateBranchDelta` checks every override in a `BranchDelta`
  against the workflow class's `ParameterAllowedRange[]`: an unknown parameter
  throws `unknown-parameter`, a number outside `[min, max]` or an enum value not
  in `enumOptions` throws `out-of-range`, and a type mismatch throws
  `wrong-type`. `planBranch` then assembles a `BranchRunRequest` (parent output
  id, validated inputs, workflow class, estimated cost) — so a derived run can
  only ever stay inside the parent class's bounded parameter space.
- **Bulk actions** (`bulk-actions.ts`) — `BulkAction` / `BulkActionInvocation`
  drive multi-output operations.

## The AAA-tier execution scheduler: `@oshun/render-farm`

The AAA-creator tier's heavy GPU work is scheduled by `@oshun/render-farm`
(`libs/oshun/render-farm`), a real lib imported by `apps/yemaya/studio-web` (its
`vite.config.ts`, `vitest.config.ts`, and `tsconfig.json` all alias
`@oshun/render-farm` to the lib source, and `package.json` declares the
`workspace:*` dependency). It provides the render-farm scheduling primitives the
tier docs gesture at but never name: priority queues, worker-node capability and
GPU-requirement matching, dependency execution, preemption, checkpoint/resume,
cloud-burst, cost estimation, and dashboard snapshots. Its public surface (from
`src/index.ts`) includes `RenderJob`, `RenderJobSubmission`, `RenderAssignment`,
`RenderCheckpoint`, `RenderCloudBurstPlan`/`RenderCloudBurstDecision`/
`RenderCloudBurstProvider`, `RenderCostEstimate`, `RenderGpuCapability`/
`RenderGpuRequirement`, `PreemptionDecision`, `RenderQuotaBreach`/
`RenderQuotaEvaluation`, `RenderDashboardSnapshot`, and the
`RenderFarmScheduler` (via `createRenderFarmScheduler`).

## The autonomous creative orchestrator: `@oshun/creative-orchestrator`

The contemplative/curated "send-to-editorial" and autonomous generation
pipelines depend on `@oshun/creative-orchestrator`
(`libs/oshun/creative-orchestrator`), a real, BFF-wired lib (consumed by
`apps/oshun/bff/src/agentic/` and `libs/yemaya/orchestration` + agents). It
turns a brief into produced content through three real stages, all built on the
shared `@oshun/ai/agent-loop` primitives (`runStructuredOutput`, `runReflexion`)
and fail-loud throughout — never fabricating a plan or artifact when no provider
is configured:

1. **Plan** — `decomposeBrief` runs a real LLM planner that emits a
   schema-validated, acyclic `CreativePlan` DAG (validated against
   `CREATIVE_PLAN_SCHEMA`; cycle detection via `detectCycle` /
   `validateDagStructure`).
2. **Route + govern** — `routePlan` / `CreativeOrchestrator` dispatch plan nodes
   to a `GeneratorRegistry` of `DomainGenerator`s, gated by a `GovernanceGate`
   (`BudgetGovernanceGate`, with `ALLOW_ALL_GATE` for tests).
3. **Critique → revise** — `reviseArtifact` runs a bounded generate → critique →
   revise (Reflexion) loop around each artifact, scored by an `ArtifactCritic`
   (`createContentEvalCritic`, `createMetricCritic`, or `createLlmJudgeCritic`).

It also exposes `createYemayaAgentGenerator` (wiring Yemaya's specialized agents
in) and `createMetisNarrator`. This is the connective tissue behind the agentic
studio; see [Agentic AI Studio](./agentic-ai-studio.md) for the full picture.

## What is real vs. provider-gated vs. aspirational

To match the docs' candor:

- **Real, in-repo:** the deterministic tier resolver (`resolveGenerationTier`,
  `TIER_ALLOWLISTS`, `checkSurfaceAccess`) with 4 tiers and 28 surfaces; the
  studio boundary fail-closed allowlist; output-gallery lineage, branch-replay,
  compare-grid, and bulk-actions contracts; the music-generation guardrails; the
  BFF executors, release gate, and safety classifiers; the provider adapter
  library; `@oshun/render-farm`; `@oshun/creative-orchestrator`.
- **Provider-gated (real wiring, live call exercised only at deploy):** every
  hosted provider call — image (Stability), voice (ElevenLabs), batch music
  (Suno), video (fal.ai LTX), realtime music (MRT2). With no key the resolver
  returns `null` and the job fails closed (`provider_not_configured`).
- **Spec-only / unverified at runtime here:** LoRA training, model merging,
  gaussian-splatting, and 3D pipelines exist as data models and surfaces
  (`@isis/lora-training-surface` — "LoRA training queue + model merging + tuning
  rehearsal + quality scoring + lineage," §24.5; `@isis/runpod-surface` —
  "endpoint registry, dashboard, cost/quota, queue inspector," §24.4), but live
  training execution was not verified. The AAA Yemaya Studio graph editor exists
  as `apps/yemaya/studio-{web,desktop}` (studio-web importing
  `@oshun/render-farm`), but a rendered AAA graph editor was not confirmed here.
  Udio is library-present but not customer-path-wired.

## Related

- [Isis — Generation Control Substrate](./substrate-isis.md)
- [Agentic AI Studio](./agentic-ai-studio.md)
- [Living Scenes](./living-scenes.md)
- [Persona, Avatar, and Voice Packs](./persona-avatar-voice-packs.md)
- [Trust, Safety, and Privacy](./trust-safety-and-privacy.md)
- [Support, Entitlements, Billing, and the Aje Entitlement Bridge](./support-billing-and-crypto.md)
- [Generation Audience Tiers and Surface Boundaries](./agentic-ai-studio.md)
- Hub: [../ARCHITECTURE.md](../ARCHITECTURE.md)
