# Isis — Generation Control Substrate

Isis is the V1 **governed-generation control plane** — the single, fail-closed
seam every generated artifact (image, video, audio, 3D mesh, texture, document)
must pass through before it can reach a customer-facing surface or land in the
data lake. It is a _substrate_, not a consumer tab: it has no shell of its own.
Instead, it binds workflow templates, model and provider registries, environment
promotion, provenance bundles, release gates, failover, and rollback into one
typed adapter that the BFF, the assistant, Living Scenes, Tara, Veritas, and the
operator admin surfaces all dispatch through. This page sits among the
platform-substrate deep-dives hubbed at
[../ARCHITECTURE.md](../ARCHITECTURE.md), alongside
[Sophia](./substrate-sophia.md), [Iris](./substrate-iris.md),
[Psyche](./substrate-psyche.md), [Lilith](./substrate-lilith.md), and
[Aje](./substrate-aje.md).

> **Read this page for what is _shipping_ vs. _spec / provider-gated_.** The
> entire control/spec layer in `libs/oshun/generation-control-isis` is **real,
> typed, and unit-tested**: workflow-template and model/provider registries with
> state machines, the environment-promotion model, the release-gate evaluator,
> the canonical provenance bundle, per-family failover with circuit breakers,
> the Civitai intake and review pipeline, ComfyUI governance, and the
> fail-closed dispatch guard. What is **provider-gated** is the actual
> generation: the BFF route ships a fail-closed `notConfiguredProviderExecutor`
> by default, and a live ComfyUI/RunPod/Stability/ElevenLabs/Suno/fal client is
> swapped in only at deploy time with real credentials. "Every render passes
> through Isis release-gate machinery" is structurally enforced in-repo;
> end-to-end _live_ generation depends on those deploy creds and is not
> exercised in the default e2e suite.

This `Isis` is the V1 governed-generation control plane — distinct from the
original Isis generative _factory_ elsewhere in the monorepo. The factory runs
the raw machinery (queues, GPU workers, output storage); this control plane
wraps it so the factory is never customer-facing except through the gate.

---

> **Canonical home (§13).** `Isis` is a cross-product substrate, so its
> canonical reference home is the domain space
> [`docs/domains/isis`](../../docs/domains/isis/deep-dive/architecture.md) and
> its code-linked entity catalog at
> [`systems/isis`](../../docs-center/systems/lib-isis.html). This page is V1's
> view — how the V1 platform composes `Isis`; the substrate itself is documented
> in full at its canonical home, which this page references rather than
> duplicates.

## Where Isis sits

```mermaid
flowchart LR
    consumer["Assistant · Tara · Living Scenes ·\nVeritas · Studio · Admin"]
    bff["BFF\nPOST /v1/isis/generate"]
    guard["dispatchGuardedGeneration\n→ evaluateIsisDispatch"]
    gate["evaluateReleaseGate\n(safety/provenance/watermark/\nquality/policy/rights/shape/review)"]
    exec["injected IsisProviderExecutor\n(notConfigured by default)"]
    factory["Raw Isis factory\napps/isis/* · ComfyUI/RunPod"]

    consumer --> bff --> guard --> gate
    gate -->|allow + all admissions| exec --> factory
    gate -->|block / review / denied| deny["403 denied —\nprovider never called"]
```

The arrow that matters: the **provider executor is invoked only when the gate
permits**. A `block` verdict, a `review` verdict, a gate evaluation error, and
any denied runtime admission all short-circuit to a denial, and the raw factory
is never reached. That is the literal mechanism behind the "Isis is the only
path; raw provider machinery is never customer-facing" guarantee.

---

## The library: `@oshun/generation-control-isis`

The control plane is a single source-only package,
`libs/oshun/generation-control-isis` (package name
`@oshun/generation-control-isis`). Its `package.json` declares exactly one
runtime dependency, `@oshun/types`, and points `main`/`types` at
`./src/index.ts` (source, not a built `dist`), with subpath exports `./adapter`
and `./canonical-adapter`. The barrel `src/index.ts` re-exports **20 modules**:

| Module                                        | Responsibility                                                                                                                                                                          |
| --------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `types.ts`                                    | Raw Isis API envelopes, enums (`IsisGenerationType`, `IsisProviderFamily`, `IsisControlPlaneEnvironment`, `IsisReleaseGateMode`, …) and the `IsisGenerationControlApiAdapter` interface |
| `control-model.ts`                            | `build*` view-model functions (catalog entries, routing summaries, plan, execution summary, provenance bundle)                                                                          |
| `adapter.ts`                                  | Contract descriptor, metadata, availability, the composed `IsisGenerationControlAdapter`                                                                                                |
| `canonical-adapter.ts`                        | `createCanonicalIsisGenerationControlAdapter` — wraps an injected `apiAdapter` with the canonical methods                                                                               |
| `workflow-template-registry-spec.ts`          | V1-ISIS-001 — template id/version patterns + `draft→…` state machine                                                                                                                    |
| `model-registry-spec.ts`                      | V1-ISIS-002 — license ids, type→format maps, size caps, model state machine                                                                                                             |
| `provider-registry-spec.ts`                   | V1-ISIS-003 — provider-endpoint spec + state machine                                                                                                                                    |
| `environment-promotion-model.ts`              | V1-ISIS-004 — `canPromoteEnvironment`, gates, bake-off hours, admissibility matrix                                                                                                      |
| `release-gate-model.ts`                       | V1-ISIS-005 — `evaluateReleaseGate`, regression gate, floors                                                                                                                            |
| `provenance-bundle-schema.ts`                 | V1-ISIS-006 — `CanonicalProvenanceBundle`                                                                                                                                               |
| `staging-recipe-schema.ts`                    | Staging-recipe schema for imported models                                                                                                                                               |
| `provider-failover-policy.ts`                 | V1-ISIS-008 — circuit breaker, retry/backoff, fallback ordering                                                                                                                         |
| `request-routing.ts` / `promotion-routing.ts` | Request and promotion routing helpers                                                                                                                                                   |
| `admin-view-models.ts`                        | Data models for the operator release-gate dashboard surface                                                                                                                             |
| `civitai-intake-spec.ts`                      | External-model intake sources, modes, `decideIntakeAdmission`                                                                                                                           |
| `civitai-review-pipeline.ts`                  | Civitai review state machine + `admitCivitaiImportedModelAtRuntime`                                                                                                                     |
| `comfyui-governance.ts`                       | ComfyUI template classes, disallowed nodes, `admitComfyTemplateForRuntime`                                                                                                              |
| `dispatch-guard.ts`                           | `evaluateIsisDispatch` — the fail-closed enforcement seam                                                                                                                               |
| `generation-dispatcher.ts`                    | `dispatchGuardedGeneration` — runs the provider IFF permitted                                                                                                                           |

Everything in the library is **pure data + pure functions** (no IO, no clock):
each spec module carries a JSDoc banner stating "Pure data + pure functions. No
IO, no clock", which is what makes the gates deterministically unit-testable.

---

## The enforcement seam (fail-closed dispatch)

The audit that produced this substrate found that `evaluateReleaseGate` was real
and tested but had **zero importers** — nothing actually consulted the gate
before dispatching a generation, so the "Isis is the only path" guarantee could
not hold. Two small modules close that gap, and they are the single in-repo
mechanism that makes the guarantee literally true.

### `evaluateIsisDispatch` (`dispatch-guard.ts:57`)

Takes a `CanonicalReleaseGateMeasurement` plus an optional list of
`IsisRuntimeAdmission` (each a `{ name, admitted, reason? }`). Each admission is
typically the result of `admitComfyTemplateForRuntime` or
`admitCivitaiImportedModelAtRuntime`, normalized by the caller. It returns an
`IsisDispatchDecision`:

- It calls `evaluateReleaseGate(measurement)` inside a `try`; **if evaluation
  throws, it denies with `mode: 'block'`** and a `gate-error:` reason — a
  missing or ambiguous check never permits a release.
- It permits **only** when `gateResult.mode === 'allow'` **and** every
  admission's `admitted` flag is true. A `review` or `block` mode denies; any
  denied admission denies.

This is fail-closed throughout: `block`, `review`, a gate error, and a denied
admission all deny dispatch.

### `dispatchGuardedGeneration` (`generation-dispatcher.ts:38`)

```ts
async function dispatchGuardedGeneration<T>(
  request: IsisDispatchRequest,
  runGeneration: (decision: IsisDispatchDecision) => Promise<T>
): Promise<GuardedGenerationResult<T>>;
```

It evaluates the dispatch decision and invokes the injected `runGeneration` (the
raw provider machinery) **only when `decision.permitted` is true**, returning
`{ outcome: 'dispatched', decision, output }`. When not permitted, it returns
`{ outcome: 'denied', decision }` and the provider is never called. Because
`runGeneration` is injected — not hardcoded — the **gate, not the route or the
provider, decides whether generation runs**.

### The concrete entry point: `POST /v1/isis/generate`

The dispatcher is wired at the BFF in
`apps/oshun/bff/src/isis/generation-route.ts:27`. The route registration takes
an `IsisProviderExecutor` and maps outcomes to HTTP status:

| Condition                                                 | Status | Body                                                         |
| --------------------------------------------------------- | ------ | ------------------------------------------------------------ |
| No `measurement` in the request body                      | `400`  | `{ error: 'invalid_request', … }`                            |
| Gate denies (`outcome: 'denied'`) — provider never called | `403`  | `{ outcome: 'denied', mode, blockedReasons, reviewReasons }` |
| Executor throws `isis_provider_not_configured`            | `503`  | `{ error: 'isis_provider_not_configured', … }`               |
| Permitted and provider runs (`outcome: 'dispatched'`)     | `200`  | `{ outcome: 'dispatched', output }`                          |

The default executor is `notConfiguredProviderExecutor` — an async function that
throws `isis_provider_not_configured`. In `apps/oshun/bff/src/server.ts:614` the
route is registered with exactly that default
(`registerIsisGenerationRoute({ app, runGeneration: notConfiguredProviderExecutor() })`),
so a stock build **fails closed at 503** rather than silently calling an
unconfigured provider. The deployable swaps in a real ComfyUI/RunPod client at
the app boundary; tests inject a spy executor. Neither the dispatch guard nor
this route was named anywhere in the prose docs before — the architecture
mermaid showed the _flow_ but not the actual enforcement entry point.

---

## The release gate (V1-ISIS-005)

`evaluateReleaseGate` (`release-gate-model.ts`) is the heart of the substrate.
It governs _produced artifacts_ (the registries below govern the _producers_).
Eight canonical gate kinds exist:

`safety-scan`, `provenance-c2pa`, `watermark-coverage`, `quality-aggregate`,
`policy-compliance`, `rights-and-license`, `output-shape-valid`,
`human-review-ready`.

Each output kind requires a different subset
(`CANONICAL_OUTPUT_GATE_REQUIREMENTS`): images, video, audio, and animation
require `watermark-coverage`; `document`/`data` do not. The evaluator composes
per-gate verdicts into an overall `IsisReleaseGateMode`:

- **`block`** if any required gate returned `block`;
- **`review`** if no blocks but at least one gate returned `review` _or_ a
  human-review trigger fired;
- **`allow`** otherwise.

Customer-facing release (`measurement.customerFacing === true`) **always** adds
the `human-review-ready` gate to the requirement set, even when no trigger
fired.

### Concrete floors (named constants, not prose)

These are real exported constants — the docs previously said only
"safety/quality drop > MDE blocks" without surfacing them:

| Constant                             | Value                                                                                  | Effect                                              |
| ------------------------------------ | -------------------------------------------------------------------------------------- | --------------------------------------------------- |
| `CANONICAL_SAFETY_SCORE_FLOOR`       | `0.9`                                                                                  | safety score below 0.9 (or outside [0,1]) → `block` |
| `CANONICAL_QUALITY_AGGREGATE_FLOOR`  | per-kind: image `0.75`, video `0.7`, 3d-model `0.65`, point-cloud `0.6`, data `0.5`, … | below floor → `review` (not block)                  |
| `CANONICAL_WATERMARK_COVERAGE_FLOOR` | image/texture/material `1.0`, video/audio/animation `0.99`, 3d/doc/data `0`            | below floor → `block`; floor `0` → `not-applicable` |

Per-gate verdicts use a four-value `CanonicalReleaseGateStatus`: `pass`,
`review`, `block`, `not-applicable`. The last is what lets watermarking be
skipped for 3D meshes and documents without faking a pass.

### Human-review triggers

`CANONICAL_HUMAN_REVIEW_TRIGGERS` is a closed catalog —
`regulated-topic-detected`, `clinical-content-detected`,
`legal-prescription-detected`, `financial-forecast-detected`,
`minor-likeness-detected`, `real-person-likeness-detected`, `cloned-voice-used`,
`spiritual-prescription-detected`, `political-campaign-detected`,
`cross-domain-memory-write`, `high-risk-policy-class`. A non-canonical trigger
**blocks** outright; a canonical trigger with no reviewer assigned **blocks**; a
canonical trigger with a reviewer assigned routes to **`review`**.

### Regression gate (promotion candidates)

`evaluateReleaseRegressionGate` compares a baseline run against a candidate run
on `CANONICAL_RELEASE_REGRESSION_METRICS` (`safety-scan-score`,
`quality-aggregate`). A drop strictly greater than the per-metric
`minimumDetectableEffect` (MDE) **blocks** promotion; a drop within MDE routes
to **review**; no drop **passes**. This is the formal version of "any safety or
quality drop greater than the configured MDE blocks promotion."

---

## Canonical provenance bundle (V1-ISIS-006)

Every artifact that leaves Isis carries a `CanonicalProvenanceBundle`
(`provenance-bundle-schema.ts:271`) — the shape the admin inspector, the release
gate, the watermark verifier, and downstream C2PA manifest builders all consume.
The earlier docs described this as a flat record carrying "consent ID, prompt,
model, watermark hash, timestamp, invoking user, tenant." **That was an
oversimplification.** The real bundle is materially richer and has no top-level
`prompt` / `consentId` / `invokingUser` / `tenant` fields by those names —
consent, prompt, user, and tenant are modeled through `actors[]` and `claims[]`,
not flat fields. The actual top-level fields are:

| Field                                 | Shape / notes                                                                                                                                                                                               |
| ------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `specVersion`                         | `CANONICAL_PROVENANCE_BUNDLE_SPEC_VERSION = 1`                                                                                                                                                              |
| `bundleId`                            | `prov_` + 26 Crockford-base32 chars (ULID-shaped)                                                                                                                                                           |
| `outputId`, `outputKind`, `sizeBytes` | the artifact identity                                                                                                                                                                                       |
| `outputHash`                          | `{ algorithm, value }` — algorithm ∈ `sha256` / `sha512` / `blake3`                                                                                                                                         |
| `productionContext`                   | `workflowTemplateId, workflowVersion, modelId, modelVersion, providerFamily, providerEndpointId, generationType, seed?, deterministicReplayable, modifierModelIds[]`                                        |
| `actors[]`                            | software / hardware / service / human-reviewer actors with role + public-key fingerprint                                                                                                                    |
| `claims[]`                            | C2PA-aligned claims (`created`, `generated`, `modified`, `reviewed`, `released`, `redacted`, `thumbnail-extracted`, `derivative-produced`) each with output-hash + optional signature, monotonic timestamps |
| `lineage[]`                           | input refs + relation (`derived_from`, `composed_of`, `refined_from`, `upscaled_from`, `converted_from`, `transcribed_from`, `stylised_from`)                                                               |
| `watermark`                           | `CanonicalWatermarkAttestation` or `null` (algorithm, coverage, `publiclyVerifiable`, optional `c2paManifestRef`)                                                                                           |
| `releaseGateEvidence[]`               | per-gate evidence stamps joining back to V1-ISIS-005 gate kinds                                                                                                                                             |
| `humanReviewTriggers[]`               | the triggers that fired                                                                                                                                                                                     |
| `retention`                           | retention-policy stamp (hot/warm/cold/total days)                                                                                                                                                           |
| `license`                             | license stamp (`licenseId`, `commercialUseAdmissible`, `validUntilUnixSeconds`)                                                                                                                             |
| `aggregateSignature`                  | root signature over every claim + production context                                                                                                                                                        |

Hash algorithms are `['sha256','sha512','blake3']`; signature algorithms are
`['ed25519','ecdsa-p256']` (both enforced as 128-hex-char raw signatures). The
aggregate signature is the verifiable root: a downstream consumer can confirm
none of the actors, claims, lineage, or production context were tampered with.

### Two contract families — don't conflate them

There are **two distinct contract families**, and the architecture hub's Isis
entry previously listed one family's names under the other's bullet:

1. **Zod contracts** `WorkflowTemplate`, `ModelCard`, `ModelVersion`,
   `ProvenanceBundle` live in `libs/contracts/src/common/` as `z.infer` types
   (`workflow-template.ts:956`, `model-card.ts:728`, `model-version.ts:802`,
   `provenance-bundle.ts:944`). These are the wire/validation contracts.
2. The **`generation-control-isis` adapter library does NOT export those bare
   names** — it exports `Canonical`-prefixed variants:
   `CanonicalProvenanceBundle`, the canonical workflow-template / model registry
   specs, etc. The adapter consumes the canonical-prefixed shapes; the Zod
   contracts are the validated envelopes the surfaces exchange.

---

## Producer registries and lifecycle state machines

The release gate governs outputs; the registries govern the producers, each with
its own canonical state machine.

### Workflow templates (V1-ISIS-001)

`workflow-template-registry-spec.ts` pins the id pattern
(`CANONICAL_WORKFLOW_TEMPLATE_ID_PATTERN`, lowercase-kebab, no double-hyphen), a
strict semver version pattern, and the state set
`draft → in-review → published → deprecated → archived`
(`CANONICAL_WORKFLOW_TEMPLATE_STATES`, with `archived` terminal). Engines span
`comfyui | blender | unreal | godot | custom`.

### Models (V1-ISIS-002)

`model-registry-spec.ts` pins:

- a **closed license enum** `CANONICAL_MODEL_LICENSE_IDS` — `apache-2.0`, `mit`,
  `bsd-3-clause`, the Creative Commons family (`cc-by-4.0` … `cc0-1.0`), the
  OpenRAIL family (`openrail`, `openrail-m`, `creativeml-openrail-m`), Stability
  (`stability-ai-community`, `stability-ai-non-commercial`), `llama3-community`,
  `oshun-internal`, `vendor-proprietary`, `other`; with
  `CANONICAL_COMMERCIAL_USE_LICENSES` as the no-extra-review allowlist;
- type→format maps (`CANONICAL_MODEL_TYPE_FORMATS`), size caps
  (`CANONICAL_MODEL_MIN_SIZE_BYTES = 1 KiB` reject-empties …
  `CANONICAL_MODEL_MAX_SIZE_BYTES = 128 GiB` hard cap), and tag/trigger-word
  limits;
- the state machine
  `draft → scanning → verified → published → deprecated → archived`
  (`CANONICAL_MODEL_TRANSITIONS`, `archived` terminal) with
  `canPromoteCanonicalModel` enforcing transitions.

### Providers (V1-ISIS-003)

`provider-registry-spec.ts` pins the provider-endpoint spec and state machine
and requires every active production endpoint to declare ≥ 1 failover partner
(the hook V1-ISIS-008 below consumes). Provider families (`IsisProviderFamily`)
are: `comfyui`, `sd`, `flux`, `character-consistency`, `cinematic-video`,
`three-d`, `texture`, `audio-sfx`, `audio-voice`, `audio-music`, `custom`. The
generation-type vocabulary `IsisGenerationType` has 15 values, including
`text-to-image`, `image-to-video`, `text-to-3d`, `voice-synthesis`,
`music-generation`, `gaussian-splatting`, `mesh-processing`, and
`texture-upscale`.

---

## Environment promotion (V1-ISIS-004)

`IsisControlPlaneEnvironment` has **four** environments — `development`,
`staging`, `production`, **and `test`** (the prose docs' "dev → staging → prod"
omits `test`). Promotion is encoded in `environment-promotion-model.ts`:

- **`CANONICAL_ENVIRONMENT_ORDER`** =
  `test → development → staging → production` (rank 0–3). Promotions move up one
  rank at a time; skip-steps are forbidden. Rollback is limited to
  `production → staging` and `staging → development`
  (`CANONICAL_ENVIRONMENT_TRANSITIONS`).
- **`canPromoteEnvironment` (`environment-promotion-model.ts:303`)** composes
  transition rules, the admissibility matrix, per-target gate evidence, and
  bake-off hours into a `{ allowed }` / `{ allowed: false, blockers[] }`
  decision.
- **`CANONICAL_ENVIRONMENT_MIN_BAKEOFF_HOURS`** =
  `{ test: 0, development: 0, staging: 4, production: 24 }`.
- **`CANONICAL_ARTEFACT_ENVIRONMENT_ADMISSIBILITY`** is a per-(kind ×
  environment) matrix of hostable lifecycle states — e.g. a workflow template in
  `draft` is admissible in `test`/`development` but a `published`/`active` state
  is required for production; `isArtefactHostedAdmissibly` checks a hosted
  artifact against it.

Production promotion additionally requires integration tests, shadow-traffic
parity, change-management approval (release captain + ops lead), governance
sign-off, and a documented rollback plan.

---

## Provider failover (V1-ISIS-008)

`provider-failover-policy.ts` is a real **circuit-breaker model**, not just
prose about "fallback". The prose docs describe failover but never name this
machinery:

- **Circuit-breaker states** `['closed','open','half-open']`
  (`CANONICAL_CIRCUIT_BREAKER_STATES`), with a per-family
  `CanonicalCircuitBreakerPolicy` (error-rate threshold, consecutive-failure
  threshold, p95-latency threshold, open-hold seconds, half-open recovery
  successes, flap-dampen window).
- **`CANONICAL_PER_FAMILY_FAILOVER_POLICIES`** — one policy record per provider
  family.
- **`CANONICAL_FALLBACK_FAMILY_ORDER`** — per-family fallback preference, e.g.
  `flux → sd → comfyui → custom`, `sd → flux → comfyui → custom`,
  `character-consistency → flux → sd → comfyui → custom`; `custom` is always the
  last-chance fallback.
- **`CANONICAL_DEGRADED_MODES`**
  `['block','queue-and-wait','serve-cached', 'synthetic-refusal']` — what the
  runtime does when _no_ endpoint is admissible.
- **`assessProviderFailover` (`provider-failover-policy.ts:351`)** takes
  candidate endpoints + live health signals and returns the admissible primary,
  the ordered fallback chain, the unhealthy endpoints with reasons, and the
  degraded mode to apply if nothing is admissible. An endpoint trips out of the
  chain on a missing health snapshot, an open breaker still within hold, an
  error rate over threshold, too many consecutive failures, or p95 latency over
  threshold.
- **`computeRetryBackoffMs` (`provider-failover-policy.ts:452`)** — exponential
  backoff clamped to `maxBackoffMs`, with optional ±25% jitter (deterministic
  when `jitterSeed` is omitted, for tests).

---

## External-model intake: Civitai

Isis treats Civitai (and other external sources) as **operator-only intake**,
never a direct generation surface. Two modules govern it:

### Intake (`civitai-intake-spec.ts`)

`CANONICAL_EXTERNAL_MODEL_SOURCES` = `civitai`, `huggingface`,
`internal-transfer`, `partner-feed`; `CANONICAL_EXTERNAL_MODEL_INTAKE_MODES` =
`manual-review`, `auto-ingest-with-review`, `denied`. `decideIntakeAdmission`
(`civitai-intake-spec.ts:409`) applies `CANONICAL_EXTERNAL_MODEL_INTAKE_POLICY`
to an intake request; `normalizeIntakeToCanonicalModel` maps an admitted import
onto the V1-ISIS-002 canonical model shape.

### Review pipeline (`civitai-review-pipeline.ts`)

`CANONICAL_CIVITAI_REVIEW_STATES` =
`intake-pending → rights-review → safety-review → preview-review → approved`,
with terminal `rejected` and `takedown` (`CANONICAL_CIVITAI_TERMINAL_STATES`).
Each stage carries a typed decision (`RightsReviewDecision`,
`SafetyReviewDecision`, `PreviewReviewDecision`).
`buildCivitaiStagingRecipeSeed` produces a staging recipe for an admitted model;
`admitCivitaiImportedModelAtRuntime` (`civitai-review-pipeline.ts:275`) is the
runtime gate. Its result feeds the dispatch guard as an `IsisRuntimeAdmission`,
so an imported model that isn't in the `approved` state (or is on the
`CivitaiDenylistEntry` denylist / under takedown) denies dispatch.

---

## ComfyUI governance

`comfyui-governance.ts` pins canonical template classes, per-class parameter
guardrails (`CANONICAL_COMFY_PARAMETER_GUARDRAILS`), and a list of disallowed
nodes (`CANONICAL_COMFY_DISALLOWED_NODES`). `admitComfyTemplateForRuntime`
(`comfyui-governance.ts:319`) and `checkComfyTemplatePortability` decide whether
a ComfyUI graph is admissible; like the Civitai runtime admission, the result
feeds the dispatch guard. `diffComfyTemplateGraphs` supports change review
between template versions.

---

## The canonical adapter

`createCanonicalIsisGenerationControlAdapter` (`canonical-adapter.ts:35`) wraps
an injected `apiAdapter` (`IsisGenerationControlApiAdapter`) and layers the
canonical view-model methods on top of the raw API:

- `listWorkflowCatalog` / `getWorkflowCatalogEntry`
- `listModelCatalog` / `getModelCatalogEntry`
- `getProviderRoutingSummary`
- `planGeneration` (builds an `IsisGenerationControlPlan` with
  release-readiness, provenance/watermark/quality requirements, blocked reasons)
- `dispatchGeneration` (refuses to run when `plan.approved` is false)
- `getGenerationExecution` / `getProvenanceBundle` / `getReleaseReadiness`

The plan/readiness types (`IsisGenerationControlPlan`, `IsisReleaseReadiness`)
encode `approved`, `humanReviewRequired`, `provenanceRequired`,
`watermarkRequired`, `blockedReasons`, and `warnings`, so a caller can inspect
_why_ a generation is or isn't admissible before dispatch.

---

## Service backing and surfaces

The raw factory lives at `apps/isis/*` — the service directories that exist are
`cli`, `generation-api`, `gpu-worker`, `output-registry`, `web`, and
`workflow-registry`. Supporting libraries include
`libs/isis/{client, database, workflows, comfyui-nodes, ai-providers/*, 3d-generation, ai-video, audio-generation, outputs, gaussian-splatting}`.
The control plane wraps all of this so the factory is reachable only through the
gate.

### Provider stack (concrete, env-gated)

The V1 providers wired behind the BFF are specific and credential-gated, not the
generic list the older docs imply: **Stability SD3.5** (image), **ElevenLabs**
(voice/TTS), **Suno** (music), and **fal.ai-hosted LTX-Video** (video).
**RunPod/ComfyUI** are the operator _execution substrate_, but no live
ComfyUI/RunPod client is wired by default — the route fails closed with
`notConfiguredProviderExecutor` until a real client is injected at deploy time.
The full provider topology and audience rules are in
[Generation Audience Tiers](./generation-audience-tiers.md) and
[V1/DEPENDENCIES.md § Generation Providers](../DEPENDENCIES.md#9-generation-providers-isis).

### Generation tiers — the real names

Two companion docs declare the four "canonical" tier names — `Customer`,
`Curated-Creator`, `AAA-Creator`, `Operator` — as "used verbatim." **That is
false against the implementation.** The real `GenerationTier` union in
`libs/isis/entitlements/src/generation-tier.ts` is:

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

Two of the four diverge: `Customer` is **`contemplative`** in code (a consumer
of contemplative products, no raw generation surfaces), and `Operator` is
**`operator-admin`**. The tier resolver is the single source of truth — the BFF,
Admin, and Studio middleware all consult it before rendering any generation
surface. See [Generation Audience Tiers](./generation-audience-tiers.md).

### Studio boundary — legacy routes hard-blocked

The legacy provider-machinery route tree under
`apps/oshun/web/src/app/studio/isis/*` is now **hard-blocked (404) for every
segment**. In `libs/isis/entitlements/src/studio-boundary.ts:60`,
`STUDIO_ISIS_ALLOWED_ROUTE_SEGMENTS = Object.freeze([])`, and `isAaaOnlyRoute`
returns `true` for every non-empty segment. The real customer inspector home
moved to `/studio/generation-gallery` (with approved surfaces under
`/studio/generation/*`). Docs that still reference the old `/studio/isis/*`
surface boundaries are stale.

### Operator dashboard and the provenance ledger

The operator release-gate dashboard surface is **data-modeled** in
`admin-view-models.ts`, but a rendered admin UI was not verified here — treat
the dashboard as data-modeled, not confirmed-shipping. The provenance-ledger e2e
is **gated**: the loader at
`apps/oshun/web/src/lib/server/isis-provenance-loader.ts` returns `null` unless
**both** `OSHUN_ENABLE_TEST_HARNESSES === 'true'` **and**
`OSHUN_ISIS_PROVENANCE_LEDGER_FIXTURE === 'clean'`, so provenance/ledger
assertions run only behind those harness env vars, not in the default suite.

---

## What is real vs. spec-only — honest summary

- **Real and unit-tested:** the entire `generation-control-isis` spec/control
  layer — registries with state machines and id/version/license/size
  constraints, environment promotion (`canPromoteEnvironment`, bake-off hours,
  admissibility matrix), the release-gate evaluator with its named floors and
  regression gate, the `CanonicalProvenanceBundle` with aggregate
  ed25519/ecdsa-p256 signatures, per-family failover with circuit breaker and
  retry/backoff, Civitai intake/review, ComfyUI governance, and the fail-closed
  `evaluateIsisDispatch` / `dispatchGuardedGeneration` seam with its
  `POST /v1/isis/generate` route. The Zod contracts `WorkflowTemplate` /
  `ModelCard` / `ModelVersion` / `ProvenanceBundle` exist in
  `libs/contracts/src/common/`.
- **Spec-only / provider-gated:** the actual provider execution. The route ships
  fail-closed; a real ComfyUI/RunPod (and Stability/ElevenLabs/Suno/fal) client
  is swapped in only at the app boundary with live keys. "Every render passes
  through Isis release-gate machinery" is structurally enforced in-repo; the
  end-to-end _live_ generation depends on deploy creds and is not exercised in
  default e2e.

The substrate adapter and gate work is tracked under the Isis V1-ISIS-00x items
in [../TODOS.md](../TODOS.md); provider topology and credentials are in
[../DEPENDENCIES.md](../DEPENDENCIES.md).

## Related

- [High-Level Architecture](./high-level-architecture.md)
- [Generation Audience Tiers](./generation-audience-tiers.md)
- [Agentic AI Studio](./agentic-ai-studio.md)
- [Trust, Safety, and Privacy](./trust-safety-and-privacy.md)
- [Lilith — Contemplative Policy Substrate](./substrate-lilith.md)
- [Sophia — Grounding Substrate](./substrate-sophia.md)
- [Subsystem Glossary](./glossary.md)
- [`V1/features.md` § Generation, Providers, and Provenance](../features.md)
- [Hub: V1 Architecture](../ARCHITECTURE.md)
