# Generation Audience Tiers and Surface Boundaries

The same provider stack — Civitai intake, ComfyUI on RunPod, hosted
image/voice/music/video providers, and the 3D pipeline — serves **four canonical
generation audience tiers** with non-overlapping exposure profiles. This page
specifies the tier taxonomy as it actually exists in code, the canonical
vocabulary of 28 named surfaces, the deterministic resolver that maps an
entitlement bundle to a tier and a surface allowlist, and the deny-by-default
boundary enforcement that keeps raw generation machinery off the contemplative
product. It serves product, platform, and trust-and-safety readers who need to
know _who can see what_ and _why the wrong customer cannot reach a surface even
by typing its URL_. It sits on top of the
[Isis Generation Control](./isis-generation-control.md) substrate and is the
front door for the
[External Model Intelligence and Execution Providers](./external-models-and-execution.md)
page.

## Where this sits, and what is real

The tier system is **real, in-repo, and unit-tested today**. The resolver, the
frozen tier list, the 28-surface vocabulary, the per-tier allowlists, and the
deny-by-default surface guard all live in
`libs/isis/entitlements/src/generation-tier.ts` (module
`@isis/entitlements/generation-tier`). The product-shell boundary that turns a
denied surface into either a 404 or a Yemaya upgrade CTA is wired into the
Oshun-web proxy at `apps/oshun/web/src/proxy.ts`. What is _gated_ is everything
downstream of the resolver: a tier may grant access to a surface, but the live
generation that surface invokes still fails closed unless deploy-time provider
credentials are present (see
[External Model Intelligence and Execution Providers](./external-models-and-execution.md)).
The resolver itself never touches a provider; it is pure policy.

## The canonical tier taxonomy

The implemented tier union is the single source of truth. In code
(`generation-tier.ts:23-28`) it is:

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

These four values are frozen into the exported `GENERATION_TIERS` array. The
prose names used across the rest of the V1 docs map onto the code identifiers as
follows — and the mapping matters, because two of the "verbatim" doc names do
_not_ match the code:

| Doc / product name               | Code identifier (`GenerationTier`) | Product shell                                              |
| -------------------------------- | ---------------------------------- | ---------------------------------------------------------- |
| Customer (contemplative product) | `contemplative`                    | Oshun contemplative apps                                   |
| Curated-Creator                  | `curated-creator`                  | Oshun Studio, `apps/oshun/web/src/app/studio/generation`   |
| AAA-Creator                      | `aaa-creator`                      | Yemaya Studio, `apps/yemaya/studio-web` + `studio-desktop` |
| Operator                         | `operator-admin`                   | Oshun Admin, `apps/oshun/admin/`                           |

> Naming note (accuracy correction): earlier doc text claimed the four tier
> names `Customer`, `Curated-Creator`, `AAA-Creator`, and `Operator` were "used
> verbatim" as the code taxonomy. In the implementation, the _Customer_ tier is
> `contemplative` and the _Operator_ tier is `operator-admin`. The remaining two
> (`curated-creator`, `aaa-creator`) line up. Treat the code identifiers above
> as authoritative for anything that touches the resolver, allowlists, or
> boundary guards.

Free-versus-paid is a subscription distinction _within_ the `contemplative`
(Customer) tier, not a separate tier. `platform-emitted` generation —
operational notifications and system artifacts — is a non-user generation source
governed by the `operator-admin` tier.

### What each tier exposes

- **`contemplative` (Customer / contemplative product).** Curated,
  entitlement-gated, customer-facing generation only: Living Offerings (Arete),
  Contemplative Arcs (Tara), Grounded Explainers (Veritas), Lesson Visualizers
  (Metis), Sky Briefings (Nyx). Tone-gated by Lilith, provenance always on. No
  raw graph editor and no model picker. In allowlist terms, this tier sees
  exactly three surfaces: `curated-image`, `curated-living-scene`,
  `curated-voice-clip`.
- **`curated-creator` (Oshun Studio).** A small set of curated cards —
  illustration, narration, ambient audio, explainer, caption/dub,
  accessibility-pass — bound to approved workflow classes, approved voice
  profiles, and approved persona/policy bindings. It adds two surfaces on top of
  the contemplative set: `curated-workflow-pick` and `curated-asset-search`. No
  raw model picker, no LoRA hash selector, no scheduler choice, no graph editor.
- **`aaa-creator` (Yemaya Studio).** Power-user surfaces: full graph editor,
  full Civitai browser, LoRA training, model merging, music generation, voice
  cloning, the full 3D pipeline, plus GPU/region orchestration. It inherits
  every curated surface and adds the entire creative power-user block (see the
  allowlist table below). It does _not_ receive the operator-only admin
  surfaces.
- **`operator-admin` (Oshun Admin).** Everything `aaa-creator` has _plus_ the
  admin-only surfaces: the RunPod endpoint dashboard, intake review queues, the
  LoRA training queue, the output-gallery operator view, the ComfyUI node
  registry, and the audit trail. In code, `operator-admin`'s allowlist is simply
  the frozen `GENERATION_SURFACES` array — all 28 surfaces.

## The 28-surface vocabulary

The tier system does not describe surfaces in prose only; it pins a canonical,
frozen enum of 28 `GenerationSurface` values (`GENERATION_SURFACES`,
`generation-tier.ts:87-126`). This vocabulary is the high-value contract every
boundary guard, route, and component checks against. The surfaces, grouped by
the tier band that first introduces them:

| Band                                      | `GenerationSurface` values                                                                                                                                                                                                                                                                                           |
| ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Contemplative (curated finished products) | `curated-image`, `curated-living-scene`, `curated-voice-clip`                                                                                                                                                                                                                                                        |
| Curated-creator                           | `curated-workflow-pick`, `curated-asset-search`                                                                                                                                                                                                                                                                      |
| AAA-creator (creative power-user)         | `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`                                                                                                                                                                                     |

Each surface name is meaningful and stable: `topaz` and `rife` are the upscaling
and frame-interpolation surfaces, `animatediff` is the motion surface,
`gaussian-splatting` and `auto-rigging` are 3D-pipeline surfaces, and
`civitai-lora-hash-picker` is the operator/AAA hash-precise model selector. The
curated tier deliberately exposes none of these directly; it only offers
`curated-workflow-pick` (choose an approved workflow class) and
`curated-asset-search` (search post-intake approved assets).

### Per-tier allowlists

`TIER_ALLOWLISTS` (`generation-tier.ts`) is a frozen
`Record<GenerationTier, readonly GenerationSurface[]>`. The allowlists are
strictly nested — each higher tier is a superset of the one below — which is
what makes "the same stack, different exposure" structurally true:

| Surface                                               | `contemplative` | `curated-creator` | `aaa-creator` | `operator-admin` |
| ----------------------------------------------------- | :-------------: | :---------------: | :-----------: | :--------------: |
| `curated-image`                                       |       ✅        |        ✅         |      ✅       |        ✅        |
| `curated-living-scene`                                |       ✅        |        ✅         |      ✅       |        ✅        |
| `curated-voice-clip`                                  |       ✅        |        ✅         |      ✅       |        ✅        |
| `curated-workflow-pick`                               |        —        |        ✅         |      ✅       |        ✅        |
| `curated-asset-search`                                |        —        |        ✅         |      ✅       |        ✅        |
| `graph-editor` … `3d-generation` (17 AAA surfaces)    |        —        |         —         |      ✅       |        ✅        |
| `runpod-dashboard` … `audit-trail` (6 admin surfaces) |        —        |         —         |       —       |        ✅        |

The contemplative tier therefore resolves to exactly three surfaces — finished,
curated products and nothing else. There is no path from a contemplative
entitlement to the graph editor, a model picker, a LoRA hash selector, or the
RunPod dashboard, because none of those surfaces are on its allowlist.

## The deterministic resolver

`resolveGenerationTier(entitlement)` is the single source of truth that BFF,
Admin, and Studio middleware all consult before rendering any generation surface
(`generation-tier.ts:128-184`). Its inputs and outputs:

```ts
interface GenerationEntitlement {
  readonly id: string;
  readonly tenantId: string;
  readonly userId: string;
  readonly persona: string;
  readonly tags: readonly string[];
}

interface ResolvedTier {
  readonly entitlement: GenerationEntitlement;
  readonly tier: GenerationTier;
  readonly surfaceAllowlist: readonly GenerationSurface[];
}
```

The resolution rule is a deterministic, ordered tag check
(`resolveTierFromTags`): if the bundle's tags include `operator-admin`, the tier
is `operator-admin`; else if they include `aaa-creator`, that; else if
`curated-creator`, that; otherwise the tier defaults to `contemplative`. Tags
are normalized first (`normalizeEntitlementTags`): non-string entries are
dropped, each tag is trimmed, and empty strings are discarded, so a malformed or
empty tag list resolves cleanly to the most restrictive tier (`contemplative`)
rather than throwing. The resolver returns a frozen `surfaceAllowlist` copied
from `TIER_ALLOWLISTS[tier]`, so callers cannot mutate the canonical lists.

This design is **deny-by-default with the safe default being the _most_
restrictive tier**: the absence of an entitlement tag, a corrupt tag array, or
an unexpected tag value all collapse to `contemplative` (curated products only).
Privilege is only ever granted by an explicit, recognized tag.

### Surface access check

`checkSurfaceAccess({ entitlement, surface })` returns a typed
`SurfaceAccessVerdict` (`generation-tier.ts`):

```ts
type SurfaceAccessVerdict =
  | { readonly verdict: 'allow'; readonly tier: GenerationTier }
  | {
      readonly verdict: 'deny';
      readonly tier: GenerationTier;
      readonly action:
        | { readonly kind: '404-with-aaa-cta' }
        | { readonly kind: '404-hard-block' };
    };
```

The function resolves the tier, and if the requested surface is on that tier's
allowlist it returns `allow`; otherwise it returns `deny` with a
`404-hard-block` action. Importantly, **the surface check itself is
deny-by-default and never emits a CTA** — its deny outcome is always
`404-hard-block`. The CTA branch (`404-with-aaa-cta`) is reserved for the
product-shell boundary guard, which is the only layer that can prove the caller
is _already entitled_ to a surface but reached it from the wrong host app. The
type carries both action shapes so the boundary guard and the raw surface check
share one verdict vocabulary.

## Boundary enforcement: component, route, and proxy

Deny-by-default is enforced at three layers, and the proxy layer is where the
two distinct deny _behaviors_ are decided.

1. **Component layer.** Studio components consult the resolved allowlist before
   rendering a surface; a surface not on the allowlist is never mounted.
2. **Route layer (BFF).** Generation routes re-check the verdict server-side, so
   a forged client cannot reach an executor for a surface it lacks.
3. **Product-shell proxy.** `apps/oshun/web/src/proxy.ts` applies the §24.11
   Studio boundary for the legacy contemplative `studio/isis/*` tree.
   `applyStudioBoundary(pathname, entitlement)` checks for the
   `STUDIO_ISIS_PREFIX` (`/studio/isis/`), resolves the route segment, and
   routes AAA-only segments through `resolveStudioBoundary`. The outcome is one
   of:
   - `render-as-is` — the caller is entitled and in the right shell;
   - `render-yemaya-cta` — the caller _is_ AAA-entitled but reached the surface
     from the contemplative shell, so the proxy issues a 307 redirect to the
     Yemaya upgrade URL with `X-Studio-Boundary: aaa-cta`;
   - `hard-block-404` — the caller has no upgrade path (e.g., a contemplative
     customer), so the proxy rewrites to Next's internal `/_not-found` route
     returning a real **404** with `X-Studio-Boundary: hard-block`.

   The 404 is rendered through the root document shell deliberately, so it ships
   with `<html lang="en">` and a `<title>` — a WCAG document-title /
   html-has-lang fix, since a bare `Not Found` body failed axe on every AAA-only
   route.

> Staleness note: earlier text said "AAA-tier routes return disclosure + Yemaya
> signup gate for entitled users, hard-block for the rest." That is _partly_
> accurate. The proxy preserves both behaviors — `render-yemaya-cta` (a redirect
> to upgrade) for AAA-entitled callers in the contemplative shell, and a real
> hard 404 for everyone else. The legacy `studio/isis/*` segments are
> 404-hard-blocked when the caller is not entitled, not merely shown a CTA. The
> live contemplative-Studio generation surfaces today are `studio/generation`
> and `studio/generation-gallery`; the older `studio/isis` tree is gated by this
> boundary.

### Why it works this way

The "raw machinery never appears on the contemplative product" guarantee is not
a UI convention — it is a _structural_ property of the resolver plus the nesting
of allowlists. Because each tier's allowlist is a frozen superset of the tier
below, and because the resolver's default is the most restrictive tier, there is
no combination of inputs that grants a contemplative customer a power-user
surface. A direct URL to `graph-editor`, an attempt to import an AAA component,
or a forged BFF request all hit the same `checkSurfaceAccess` deny path, and the
proxy decides whether the right answer is "upgrade here" (proven-entitled, wrong
shell) or "this does not exist for you" (a hard 404). The surface enforcement
tests assert exactly this: a contemplative entitlement cannot resolve to an AAA
route or component even via direct URL or import.

## Cross-tier execution: where the surfaces lead

A surface being _visible_ is necessary but not sufficient for generation to run.
The AAA execution surfaces (`gpu-worker`, `multi-gpu-orchestration`,
`runpod-region-selector`) are fronted by the render-farm scheduler in
`@oshun/render-farm` (`libs/oshun/render-farm`, imported by
`apps/yemaya/studio-web`), which provides the priority queues, worker-node
capability matching, GPU-requirement matching, preemption, checkpoint/resume,
cloud-burst, and cost estimation that the AAA tier's scheduling surfaces expose.
The curated and contemplative surfaces, by contrast, route through the BFF
generation executors and the autonomous `@oshun/creative-orchestrator`. Both are
detailed on the
[External Model Intelligence and Execution Providers](./external-models-and-execution.md)
and
[Creator Surfaces, Voice, Music, and 3D Generation](./creator-voice-music-3d.md)
pages.

Backlog references: the resolver and surfaces are §24.1; the RunPod operator
surface §24.4; LoRA training §24.5; music generation §24.8; the unified output
gallery §24.10; the Studio boundary §24.11. External-provider intake and
adapters are tracked in deps§9.

## Related

- [Isis Generation Control](./isis-generation-control.md)
- [External Model Intelligence and Execution Providers](./external-models-and-execution.md)
- [Creator Surfaces, Voice, Music, and 3D Generation](./creator-voice-music-3d.md)
- [Output Gallery, Lineage, Branch, and Replay](./output-gallery-lineage.md)
- [Support, Entitlements, Billing, and Customer Operations](./support-billing.md)
- [Admin Products — Web and Mobile](./admin-products.md)
- [Review, Compliance, and Trust & Safety](./review-trust-safety.md)
- [Subsystem Glossary](./glossary.md)
- [Architecture, Platform Foundations, and Security](./platform-foundations-and-security.md)
- Hub: [../features.md](../features.md)
