Isis is the governed-generation control plane of V1: every image, video, audio, voice, 3D, and Living Scene render the product produces must pass through an Isis-registered workflow class, an Isis-registered model, and the Isis release-gate machinery before it can reach a customer. Raw provider machinery — ComfyUI on RunPod, Stability, ElevenLabs, Suno, fal.ai-hosted video, Civitai model intake — is never customer-facing; Isis is the only path. This page is the substrate companion to the audience-facing surfaces: it specifies the registries, the promotion lifecycle, the fail-closed dispatch seam, provenance bundles, release gates, failover policy, and the operator surface. For how those capabilities are exposed to different customers, see Generation Audience Tiers and Surface Boundaries, External Model Intelligence and Execution Providers, and Output Gallery, Lineage, Branch, and Replay.
Where Isis sits, and what is real versus gated#
The Isis control plane in V1 is a fully typed, unit-tested contract and policy layer, with the live provider execution deliberately held behind a deploy-time boundary. It is honest to call out exactly which pieces are enforced in-repo and which depend on credentials:
- Real, in-repo, unit-tested. The whole
@oshun/generation-control-isislibrary: the workflow-template / model / provider registry specs, the environment-promotion state machine, the release-gate model, theCanonicalProvenanceBundleschema, the per-family failover policy with circuit breaker, the Civitai intake spec and review pipeline, the ComfyUI governance module, and — most importantly — the fail-closedevaluateIsisDispatch/dispatchGuardedGenerationseam that makes "Isis is the only path" structurally true rather than merely aspirational. The Zod contractsWorkflowTemplate/ModelCard/ModelVersion/ProvenanceBundlealso exist inlibs/contracts/src/common/. Theapps/isis/*services exist (cli,generation-api,gpu-worker,output-registry,web,workflow-registry). - Boundary-gated / aspirational. The actual provider execution. The
generation route ships a fail-closed
notConfiguredProviderExecutorby default — the real ComfyUI/RunPod (and Stability/ElevenLabs/Suno/fal.ai) client is swapped in only at the app boundary, at deploy time, with live keys. So the gate is always exercised, but end-to-end live generation depends on deploy creds and is not run in the default e2e suite. The provenance/ledger assertions execute only behind theOSHUN_ISIS_PROVENANCE_LEDGER_FIXTURE=clean+OSHUN_ENABLE_TEST_HARNESSES=truetest-harness env gate. The operator release-gate dashboard is data-modeled (admin-view-models.ts); a rendered admin UI is planned but not verified here.
The library is published as the workspace package
@oshun/generation-control-isis
(libs/oshun/generation-control-isis/package.json). It has a single runtime
dependency, @oshun/types; main/types point at ./src/index.ts (source,
not a built dist), and it exposes two subpath exports, ./adapter and
./canonical-adapter. The barrel src/index.ts re-exports twenty modules:
types, control-model, adapter, canonical-adapter,
workflow-template-registry-spec, model-registry-spec,
provider-registry-spec, environment-promotion-model, release-gate-model,
provenance-bundle-schema, staging-recipe-schema, provider-failover-policy,
request-routing, promotion-routing, admin-view-models,
civitai-intake-spec, civitai-review-pipeline, comfyui-governance,
dispatch-guard, and generation-dispatcher.
The dispatch guard — the single enforcement seam#
The claim that "Isis is the only path; raw provider machinery is never customer-facing" is not a slogan in V1 — it is a single, concrete, fail-closed code seam. Two files carry it, and their own header comments record the audit finding that motivated them: the release gate was real and tested, but the library had no tsconfig alias and zero importers, so nothing actually consulted the gate before dispatching a generation. The seam closes that gap.
evaluateIsisDispatch (dispatch-guard.ts)#
evaluateIsisDispatch(request: IsisDispatchRequest): IsisDispatchDecision is
the fail-closed decision function. It takes a release-gate measurement plus an
optional list of pre-computed runtime admissions (each an
IsisRuntimeAdmission with a name, an admitted boolean, and an optional
reason) and returns:
interface IsisDispatchDecision {
permitted: boolean; // true ONLY when gate allows AND every admission admitted
mode: IsisReleaseGateMode; // 'allow' | 'review' | 'block' ('block' if the gate threw)
blockedReasons: readonly string[];
reviewReasons: readonly string[];
gateResult: CanonicalReleaseGateResult | null; // null if evaluation threw
}
The logic is fail-closed in every branch:
- If
evaluateReleaseGatethrows, the decision ispermitted: false,mode: 'block', with agate-error: …reason andgateResult: null. permittedistrueonly whengateResult.mode === 'allow'and there are zero denied admissions.- A
reviewverdict, ablockverdict, or any denied admission denies — a generation is never released on the strength of a missing or ambiguous check.
dispatchGuardedGeneration (generation-dispatcher.ts)#
dispatchGuardedGeneration<T>(request, runGeneration) is the runtime seam that
actually calls the provider. It evaluates the dispatch; if decision.permitted
is false, it returns { outcome: 'denied', decision } without ever invoking
runGeneration; only when permitted does it await runGeneration(decision)
and return { outcome: 'dispatched', decision, output }. The injected
runGeneration is the raw provider machinery — so the provider is physically
unreachable except through a permitting gate.
BFF route POST /v1/isis/generate#
apps/oshun/bff/src/isis/generation-route.ts registers
POST /v1/isis/generate, the HTTP face of the seam. Its IsisProviderExecutor
is injected, so the gate — not the route and not the provider — decides
whether generation runs. The response contract:
| Status | Condition | Body |
|---|---|---|
400 |
No measurement in the body |
{ error: 'invalid_request', message } |
403 |
dispatchGuardedGeneration returned outcome: 'denied' (provider never called) |
{ outcome: 'denied', mode, blockedReasons, reviewReasons } |
503 |
Executor threw isis_provider_not_configured |
{ error: 'isis_provider_not_configured', message } |
200 |
outcome: 'dispatched' |
{ outcome: 'dispatched', output } |
The default executor is notConfiguredProviderExecutor(), which always throws
isis_provider_not_configured. The deployable swaps in a real ComfyUI/RunPod
client executor at the app boundary. This is the honest shape of V1: the gate
and route ship and are enforced; the live provider is creds-gated.
Workflow, model, and provider registries#
Every generation pipeline, model, and provider endpoint is a versioned, state-machined artifact in one of three registries.
Workflow template registry#
Each generation pipeline is a versioned workflow class declaring its
parameter guardrails (locked ranges per parameter), disallowed graph patterns,
cost class, persona/tone-policy binding, and Sophia grounding requirement (see
Sophia Grounding). Templates are diffable per node and
per parameter, and a portability check verifies a class runs identically across
approved nodes. The ComfyUI specialization of this lives in
comfyui-governance.ts, which exposes CanonicalComfyTemplateClassSpec,
CanonicalParameterGuardrail, diffComfyTemplateGraphs (per-node /
per-parameter diff), checkComfyTemplatePortability,
checkComfyParameterGuardrails, and the runtime admission gate
admitComfyTemplateForRuntime — whose result is exactly the kind of
IsisRuntimeAdmission that the dispatch guard folds in.
The Zod contract WorkflowTemplate is a z.infer type at
libs/contracts/src/common/workflow-template.ts:956.
Staging recipe schema#
A staging recipe (staging-recipe-schema.ts) is a named, versioned,
environment-bound recipe that pins a workflow class to a model set and a
provider set for a given environment, so dev / staging / prod each resolve a
deterministic generation configuration. Civitai-imported models seed recipes
through buildCivitaiStagingRecipeSeed (see below).
Model registry#
Per-model lineage, license, version, deprecation flag, and eval scorecard;
deprecated models stay resolvable for kept artifacts but drop from
new-generation selection. The model lifecycle (model-registry-spec.ts) carries
the CanonicalModelState machine
(draft → scanning → verified → published → deprecated), license ids,
type→format maps, and size caps. The Zod contracts ModelCard and
ModelVersion live at libs/contracts/src/common/model-card.ts:728 and
model-version.ts:802.
Provider registry#
Per-provider endpoint registration, health checks, region-aware routing,
concurrency and cost controls, retry/backoff, dead-letter rules, secret
rotation, and per-provider failover chain. The endpoint lifecycle
(provider-registry-spec.ts) carries the CanonicalProviderEndpointState
machine (draft → validating → active → deprecated). Endpoints group into the
eleven IsisProviderFamily values: comfyui, sd, flux,
character-consistency, cinematic-video, three-d, texture, audio-sfx,
audio-voice, audio-music, and custom.
Note on the concrete V1 provider set. Earlier prose described the stack generically ("Civitai, ComfyUI on RunPod, voice/music/3D providers"). That phrasing is not wrong but is stale relative to what is now wired at the BFF boundary: the V1 providers are specific and env-gated — 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 falls back to the fail-closed
notConfiguredProviderExecutor. See External Model Intelligence and Execution Providers.
Generation types#
The IsisGenerationType union enumerates fifteen kinds: text-to-image,
image-to-image, text-to-video, image-to-video, text-to-3d,
image-to-3d, text-to-audio, voice-synthesis, music-generation,
upscaling, inpainting, blender-render, gaussian-splatting,
mesh-processing, and texture-upscale.
Environment promotion and release gates#
The environment-promotion state machine#
IsisControlPlaneEnvironment is a four-environment union — development,
staging, production, and test. (The older "dev → staging → prod"
shorthand omitted test.) The canonical rank order is
test (0) → development (1) → staging (2) → production (3)
(CANONICAL_ENVIRONMENT_ORDER / CANONICAL_ENVIRONMENT_RANK). Promotions move
up at most one rank at a time; skip-steps are forbidden. Limited downward moves
are allowed for incident response (production → staging, staging → development)
per CANONICAL_ENVIRONMENT_TRANSITIONS.
canPromoteEnvironment(request) (environment-promotion-model.ts:303) is the
decision function. It composes the transition rules, an admissibility
matrix, per-target gate evidence, and a minimum bake-off window:
- Admissibility (
CANONICAL_ARTEFACT_ENVIRONMENT_ADMISSIBILITY,isArtefactHostedAdmissibly): which lifecycle states may live in which environment, per artifact kind. For example, a workflow template may bedraftin test,draft/in-reviewin development,in-review/publishedin staging, andpublished/deprecatedin production; a model may bescanning/verifiedonly in development, never in production. - Minimum bake-off hours (
CANONICAL_ENVIRONMENT_MIN_BAKEOFF_HOURS): how long an artifact must remain in the lower environment before stepping up.
| Target environment | Min bake-off hours |
|---|---|
test |
0 |
development |
0 |
staging |
4 |
production |
24 |
- Per-environment gates (
CANONICAL_ENVIRONMENT_PROMOTION_GATES): test requiresunit-tests-passed; development addsartefact-shape-valid; staging addsintegration-tests-passedandmin-bakeoff-hours; higher environments add QA sign-off, shadow-traffic clearance, change-management approval, governance sign-off, and a rollback plan (carried onEnvironmentPromotionEvidence).
Every transition is recorded with actor, rationale, and the eval evidence that satisfied the gate.
Release gate model and concrete floors#
Promotion to a customer-facing environment requires the class's regression eval
suite to pass; any safety- or quality-eval drop strictly greater than the
declared MDE (minimum detectable effect) blocks promotion. The regression
metrics are safety-scan-score and quality-aggregate
(CANONICAL_RELEASE_REGRESSION_METRICS), each measured as a
baseline-versus-candidate mean with a per-metric minimumDetectableEffect.
Beyond MDE, the release-gate model exposes concrete, named floors that the prose summary never surfaced:
CANONICAL_SAFETY_SCORE_FLOOR = 0.9— the minimum safety-scan score (scored[0,1], higher is safer). Below it, release is blocked regardless of any other gate.CANONICAL_QUALITY_AGGREGATE_FLOOR— a per-output-kind quality floor. Falling below it does not block; it routes to review.CANONICAL_WATERMARK_COVERAGE_FLOOR— a per-output-kind watermark coverage floor (fraction of frames/turns). For example,imageandtexturerequire full coverage (1),video/audio/animationrequire0.99, and3d-model/point-cloud/document/datarequire0.
evaluateReleaseGate(measurement) runs the gates required for the output's kind
(adding human-review-ready whenever the release is customer-facing or any
trigger fired), each gate yielding a CanonicalReleaseGateStatus of
pass | review | block | not-applicable. The overall IsisReleaseGateMode
aggregates: block if any required gate blocks; otherwise review if
any gate reviews or a human-review trigger fired; otherwise allow.
A set of human-review triggers (CANONICAL_HUMAN_REVIEW_TRIGGERS) force a
review disposition even when every other gate passes — e.g.
minor-likeness-detected, real-person-likeness-detected, cloned-voice-used,
clinical-content-detected, legal-prescription-detected,
financial-forecast-detected, spiritual-prescription-detected,
political-campaign-detected, cross-domain-memory-write,
high-risk-policy-class. A triggered artifact without an assigned reviewer
blocks; with a reviewer assigned, it routes to review.
Staged rollout, rollback, failover, and fallback#
- Staged rollout. Promoted classes ramp by percentage with canary gating; canary anomalies halt the ramp and route to operator review.
- Rollback. Any production workflow class, model, or provider routing can be rolled back to a prior version with bound evaluation evidence; in-flight generations complete on the current version, new requests resolve to the rolled-back version.
- Failover is per-provider (an endpoint failure reroutes to the next provider in the chain); fallback is per-class degradation (e.g. a video class falls back to a still render) declared and tested per workflow class.
The per-family circuit breaker (provider-failover-policy.ts)#
Failover in V1 is a real circuit-breaker model, not just prose. The breaker has
three states — closed, open, half-open
(CANONICAL_CIRCUIT_BREAKER_STATES) — governed by per-family thresholds
(default error-rate 0.1, consecutive-failure threshold 5, p95 latency
5000ms, open-hold 60s, half-open recovery successes 3, flap-dampen
120s). assessProviderFailover(input) evaluates the live health signals and
returns a FailoverAssessment naming the primary endpoint and the fallback
chain; computeRetryBackoffMs(...) derives the exponential backoff (default
maxAttempts 3, initialBackoffMs 250, maxBackoffMs 4000, multiplier 2,
with jitter).
CANONICAL_FALLBACK_FAMILY_ORDER defines per-family fallback preference — e.g.
flux → sd → comfyui → custom, with custom always the last-chance fallback.
Critically, two families forbid cross-family fallback because the substitution
would itself be a trust failure: character-consistency (identity drift is a
trust signal) and audio-voice (cloned voices must never silently fall back to
a different family) both set crossFamilyFallbackForbidden: true and a
degradedMode: 'block'. When no partner is healthy, the breaker selects a
CanonicalDegradedMode from block, queue-and-wait, serve-cached, or
synthetic-refusal (CANONICAL_DEGRADED_MODES); the default is
queue-and-wait. All per-family policies are pinned in
CANONICAL_PER_FAMILY_FAILOVER_POLICIES.
Provenance bundles#
Every generation emits a provenance bundle that is persisted and travels with the artifact, an append-only generation-event ledger makes any output auditable and replayable, and provenance is surfaced wherever it adds trust value.
CanonicalProvenanceBundle — the real schema#
The earlier doc summarized the bundle as a flat list ("consent ID, prompt,
model, workflow class, watermark hash, timestamp, invoking user, tenant"). The
real CanonicalProvenanceBundle (provenance-bundle-schema.ts:271) is
materially richer and does not carry top-level prompt / consentId /
invokingUser / tenant fields by those names — those are modeled through
actors[] and claims[] rather than as flat fields. The full field set:
| Field | Meaning |
|---|---|
specVersion |
Bundle spec version |
bundleId |
prov_ + 26 Crockford base32 chars (CANONICAL_PROVENANCE_BUNDLE_ID_PATTERN); quotable verbatim in logs |
outputId |
The output this bundle attests |
outputKind |
An IsisOutputFileType (image, video, audio, 3d-model, point-cloud, animation, texture, material, document, data, other) |
outputHash |
{ algorithm, value } — algorithm ∈ sha256 / sha512 / blake3 |
sizeBytes |
Output size |
productionContext |
workflowTemplateId, workflowVersion, modelId, modelVersion, providerFamily, providerEndpointId, generationType, seed?, deterministicReplayable, modifierModelIds[] (LoRA/controlnet/adapter fingerprints) |
actors[] |
Typed participants (kind ∈ software/hardware/service/human-reviewer; role ∈ oshun-control-plane, isis-dispatcher, provider-endpoint, watermark-embedder, safety-scanner, quality-evaluator, human-reviewer, …) with optional version + public-key fingerprint |
claims[] |
Ordered created/generated/modified/reviewed/released/redacted/… claims, each with claimId, actor, monotonic atUnixSeconds, rationale, and output hash |
lineage[] |
Parent/derivation inputs |
watermark |
A CanonicalWatermarkAttestation or null |
releaseGateEvidence[] |
Stamped release-gate evidence |
humanReviewTriggers[] |
Triggers that fired |
retention |
A CanonicalRetentionStamp (totalRetentionDays, …) |
license |
A CanonicalLicenseStamp (licenseId, licenseDisplayName, commercialUseAdmissible, validUntilUnixSeconds | null) |
aggregateSignature |
Root signature over every claim + production context — { algorithm, value, publicKeyFingerprint, signedAtUnixSeconds }; algorithm ∈ ed25519 / ecdsa-p256 (both enforced as 64-byte / 128-hex) |
Hash and signature lengths are validated: sha256/blake3 = 64 hex chars,
sha512 = 128; ed25519 and ecdsa-p256 signatures = 128 hex (the canonical
64-byte raw (r||s) form for P-256).
The Zod contract
ProvenanceBundle(libs/contracts/src/common/provenance-bundle.ts:944) is a distinct, parallel contract from the adapter'sCanonical-prefixed variant. The two families coexist: the contracts layer holdsWorkflowTemplate/ModelCard/ModelVersion/ProvenanceBundleas Zod schemas; thegeneration-control-isisadapter does not re-export those names — it exportsCanonical-prefixed schemas (CanonicalProvenanceBundle, canonical workflow-template / model registry specs). Anything claiming the adapter exports the bare contract names is conflating the two layers.
Immutable ledger and surfaces#
Every generation appends to an append-only generation-event ledger so any output
is auditable and replayable from its inputs. Provenance is inspectable in Oshun
Admin for every output and surfaced to the customer wherever it adds trust value
(synthetic-content badges, citation trails, attestation pages). The web
provenance-ledger e2e is gated behind two env switches:
OSHUN_ENABLE_TEST_HARNESSES=true and
OSHUN_ISIS_PROVENANCE_LEDGER_FIXTURE=clean — the loader at
apps/oshun/web/src/lib/server/isis-provenance-loader.ts returns null (no
fixture) unless both are set.
Civitai intake and external-model review#
External models enter Isis through a typed intake-and-review pipeline, never directly into generation.
- Intake spec (
civitai-intake-spec.ts).CANONICAL_EXTERNAL_MODEL_SOURCESenumerates the allowed origins (civitai,huggingface,internal-transfer,partner-feed).CANONICAL_EXTERNAL_MODEL_INTAKE_POLICYpins the default mode (manual-review), per-source modes (Civitai and partner-feed → manual-review; HuggingFace and internal-transfer → auto-ingest-with-review), forbidden license ids (e.g.stability-ai-non-commercial), allowed model types (lora/controlnet/checkpoint/embedding),allowNsfwAutoIngest: false, and a minimum creator reputation (0.7) for auto-ingest.decideIntakeAdmission({ policy, record })returns either{ admissible: true, mode }or{ admissible: false, blockers }— and even when admissible, an NSFW record, a low-reputation creator, or an explicit / graphic-violence / hate-or-harassment content label forces the final mode back tomanual-review.normalizeIntakeToCanonicalModelmaps an admitted record onto a canonical model card. - Review pipeline (
civitai-review-pipeline.ts). The review queue is a state machine —intake-pending → rights-review → safety-review → preview-review → approved, withrejectedandtakedownas terminal states (CANONICAL_CIVITAI_REVIEW_STATES/CANONICAL_CIVITAI_REVIEW_TRANSITIONS).admitCivitaiImportedModelAtRuntime(...)produces the runtime admission folded into the dispatch guard;buildCivitaiStagingRecipeSeed(...)seeds a staging recipe from an approved import;CivitaiDenylistEntry/checkCivitaiDenylistenforce a denylist at intake.
Canonical adapter#
createCanonicalIsisGenerationControlAdapter({ apiAdapter })
(canonical-adapter.ts:35) wraps an injected IsisGenerationControlApiAdapter
and layers the canonical control-plane behavior on top. It exposes
listWorkflowCatalog / getWorkflowCatalogEntry, listModelCatalog /
getModelCatalogEntry, getProviderRoutingSummary, planGeneration,
dispatchGeneration (which refuses to run when the plan is not approved),
getGenerationExecution / getJob, and provenance / retention /
release-readiness inspectors (getProvenanceBundle, getReleaseReadiness).
This is the single typed surface the higher services compose against.
Operator surface#
Routing of approved media generation, model promotions, workflow promotions,
provenance inspection, release readiness, and rollback status flows through
Oshun Admin (see Admin Products — Web and Mobile and
Review, Compliance, and Trust & Safety). A
release-gate dashboard surfaces per-class eval scores, promotion state,
canary status, and the rollback control — its data is modeled in
admin-view-models.ts; the rendered admin UI is planned. The Isis test surface
covers validation, promotion, rollback, provenance, load, audit, and
release-gate regression, plus outage and performance tests on provider
endpoints.
Customer surface migration — legacy provider routes are hard-blocked#
The legacy provider-machinery route tree under
apps/oshun/web/src/app/studio/isis/* is now hard-blocked (404) for all
segments: STUDIO_ISIS_ALLOWED_ROUTE_SEGMENTS = Object.freeze([]) at
libs/isis/entitlements/src/studio-boundary.ts:60, and isAaaOnlyRoute returns
true for every non-empty segment. The real customer inspector home moved to
/studio/generation-gallery (with approved generation under
/studio/generation/*). This keeps raw machinery off the contemplative product
by construction: adding any legacy route back requires a deliberate edit to the
frozen allowlist.
A correction on the audience-tier names#
A note for cross-referencing readers: both this document and
V1/ARCHITECTURE.md historically declared the four "canonical" tier names as
Customer, Curated-Creator, AAA-Creator, Operator, "used verbatim." The
implementation GenerationTier union
(libs/isis/entitlements/src/generation-tier.ts:23) is in fact
'operator-admin' | 'aaa-creator' | 'curated-creator' | 'contemplative'. Two of
the four diverge: the customer tier is contemplative in code (not
Customer), and the operator tier is operator-admin (not Operator). The
"used verbatim" claim is false against the code; the authoritative names are the
union members above. See
Generation Audience Tiers and Surface Boundaries
for the full resolver and surface allowlists.
Related#
- Generation Audience Tiers and Surface Boundaries
- External Model Intelligence and Execution Providers
- Creator Surfaces, Voice, Music, and 3D Generation
- Output Gallery, Lineage, Branch, and Replay
- Sophia Grounding
- Review, Compliance, and Trust & Safety
- Admin Products — Web and Mobile
- Subsystem Glossary
- Architecture, Platform Foundations, and Security
- Hub: ../features.md