# Isis — Technical Specifications

> Technical reference for the Isis generative-AI factory domain: data models,
> database schema, enumerations, the job-envelope contract, API surface, event
> contracts, the library inventory, configuration, and operational contracts.
>
> Every statement below is traceable to source in `libs/isis/*` or
> `apps/isis/*`. The canonical Prisma schema is
> `libs/isis/database/prisma/schema.prisma`.

---

This document is the engineering reference for the Isis domain. Where the
architecture and features documents explain _what_ Isis does and _why_, this
document records the precise contracts that all services in the domain must
agree on: the exact shape of every database table, every enumeration value,
every API endpoint, every event payload schema, and every configuration
variable. When you are building a new Isis service, adding an endpoint, or
integrating with Isis from another domain, start here.

---

## Domain Layout

Isis is split across two top-level trees in the monorepo. There is no
`services/isis/` tree — all services live under `apps/`.

| Tree         | Count | Contents                                                  |
| ------------ | ----- | --------------------------------------------------------- |
| `apps/isis/` | 6     | Deployable services and front-ends                        |
| `libs/isis/` | 55    | Library directories (54 `@isis/*` TS packages + 1 Python) |

### Applications (`apps/isis/`)

Each REST service reads its listen port from `process.env.PORT`, defaulting to
`3000` / `3001` / `3002` respectively (`apps/isis/*/src/index.ts`).

| Application         | Type          | Default port | Framework             |
| ------------------- | ------------- | ------------ | --------------------- |
| `generation-api`    | REST API      | `3000`       | Hono                  |
| `workflow-registry` | REST API      | `3001`       | Hono                  |
| `output-registry`   | REST API      | `3002`       | Hono                  |
| `gpu-worker`        | Queue worker  | —            | Node.js               |
| `cli`               | CLI tool      | —            | Commander.js          |
| `web`               | Web front-end | —            | Next.js (`@isis/web`) |

---

## Database Configuration

All Isis services share a single PostgreSQL database. The Prisma schema is the
canonical source of truth for the data model; every table, column, and index
described in this document is defined there.

| Property                 | Value                                     |
| ------------------------ | ----------------------------------------- |
| **Engine**               | PostgreSQL                                |
| **ORM**                  | Prisma (`prisma-client-js`)               |
| **Schema location**      | `libs/isis/database/prisma/schema.prisma` |
| **Schema size**          | 1141 lines                                |
| **Model count**          | 24                                        |
| **Enum count**           | 14                                        |
| **Environment variable** | `ISIS_DATABASE_URL`                       |
| **Generated client**     | `libs/isis/database/src/generated/client` |
| **Preview features**     | `fullTextSearch`, `fullTextIndex`         |
| **Package**              | `@isis/database`                          |

The generator and datasource blocks declare `provider = "postgresql"` with the
URL sourced from `env("ISIS_DATABASE_URL")`.

---

## Data Models

The schema defines 24 models. They group into five clusters: the core generation
pipeline (jobs, workflows, outputs, provenance, models), the canonical
model-and-governance contracts, retention/worker/audit infrastructure, the
canonical platform audit event, and the pipeline-state persistence layer. Each
cluster is described below.

### Core Pipeline Models

These models form the heart of the domain — they track every job, workflow,
output, and model that flows through Isis.

#### GenerationJob (`generation_jobs`)

The core work unit. Each record represents one AI generation request with full
lifecycle tracking. `id` is a `cuid()` stored as `VarChar(25)`.

| Field                   | Type             | Default      | Description                                     |
| ----------------------- | ---------------- | ------------ | ----------------------------------------------- |
| `id`                    | `String` (cuid)  | auto         | Primary key                                     |
| `type`                  | `GenerationType` | —            | Generation type (15 enum values)                |
| `status`                | `JobStatus`      | `PENDING`    | Lifecycle status                                |
| `priority`              | `JobPriority`    | `NORMAL`     | Queue priority                                  |
| `progress`              | `Int`            | `0`          | Progress percentage (0–100)                     |
| `prompt`                | `String?` (Text) | —            | Text prompt                                     |
| `negativePrompt`        | `String?` (Text) | —            | Negative prompt                                 |
| `inputUrl`              | `String?`        | —            | Input file URL for image/video jobs             |
| `modelId`               | `String?`        | —            | FK to `ModelRegistry` (optional)                |
| `workflowId`            | `String?`        | —            | FK to `Workflow` (optional)                     |
| `parameters`            | `Json`           | `{}`         | Model-specific generation parameters            |
| `outputData`            | `Json?`          | —            | Output metadata from a completed job            |
| `previewUrl`            | `String?`        | —            | Preview image URL                               |
| `errorMessage`          | `String?` (Text) | —            | Error description on failure                    |
| `errorCode`             | `String?`        | —            | Error code for programmatic handling            |
| `retryCount`            | `Int`            | `0`          | Number of retries attempted                     |
| `maxRetries`            | `Int`            | `3`          | Maximum retries before terminal `FAILED`        |
| `workerId`              | `String?`        | —            | Assigned GPU worker ID                          |
| `queueName`             | `String?`        | —            | Redis queue name used                           |
| `queuePosition`         | `Int?`           | —            | Current queue position                          |
| `callbackUrl`           | `String?`        | —            | Webhook callback URL on completion              |
| `metadata`              | `Json`           | `{}`         | Arbitrary client metadata                       |
| `gpuType`               | `String?`        | —            | GPU type used for processing                    |
| `gpuTimeSeconds`        | `Int?`           | —            | GPU time consumed (seconds)                     |
| `tokensUsed`            | `Int?`           | —            | LLM tokens consumed (text jobs)                 |
| `costEstimate`          | `Float?`         | —            | Estimated cost in USD                           |
| `userId`                | `String`         | —            | Owner user ID                                   |
| `organizationId`        | `String?`        | —            | Owner organization ID                           |
| `projectId`             | `String?`        | —            | Originating project ID (cross-domain reference) |
| `createdAt`             | `DateTime`       | `now()`      | Creation timestamp                              |
| `updatedAt`             | `DateTime`       | `@updatedAt` | Last-update timestamp                           |
| `startedAt`             | `DateTime?`      | —            | Processing start timestamp                      |
| `completedAt`           | `DateTime?`      | —            | Processing end timestamp                        |
| `estimatedCompletionAt` | `DateTime?`      | —            | ETA for completion                              |
| `deletedAt`             | `DateTime?`      | —            | Soft-delete timestamp                           |

**Relations:** `model` (ModelRegistry?), `workflow` (Workflow?), `outputs`
(GeneratedOutput[]), `provenance` (Provenance?). **Indexes:** `status`, `type`,
`priority`, `userId`, `organizationId`, `projectId`, `workerId`, `createdAt`,
`deletedAt`, plus composites `[status, type]` and `[userId, status]`.

#### Workflow (`workflows`)

Reusable workflow definitions for ComfyUI, Blender, Unreal, Godot, or custom
pipelines. Supports semver versioning, community statistics, and visibility
controls.

| Field              | Type                       | Default      | Description                        |
| ------------------ | -------------------------- | ------------ | ---------------------------------- |
| `id`               | `String` (cuid)            | auto         | Primary key                        |
| `name`             | `String`                   | —            | Workflow name                      |
| `description`      | `String?` (Text)           | —            | Description                        |
| `engine`           | `WorkflowEngine`           | —            | Execution engine                   |
| `category`         | `WorkflowCategory`         | —            | Content category                   |
| `status`           | `WorkflowStatus`           | `DRAFT`      | Lifecycle status                   |
| `visibility`       | `WorkflowVisibility`       | `PRIVATE`    | Access level                       |
| `currentVersion`   | `String`                   | `"1.0.0"`    | Active semver version              |
| `totalVersions`    | `Int`                      | `1`          | Total version count                |
| `parameters`       | `Json`                     | `[]`         | Parameter schema                   |
| `outputs`          | `Json`                     | `[]`         | Expected-outputs schema            |
| `requirements`     | `Json`                     | `{}`         | Hardware/software requirements     |
| `definition`       | `Json`                     | `{}`         | Workflow node/edge definition      |
| `previewImage`     | `String?`                  | —            | Preview thumbnail URL              |
| `tags`             | `String[]`                 | `[]`         | Searchable tags                    |
| `runCount`         | `Int`                      | `0`          | Total execution count              |
| `successfulRuns`   | `Int`                      | `0`          | Successful execution count         |
| `avgExecutionTime` | `Float?`                   | —            | Average execution time (seconds)   |
| `starCount`        | `Int`                      | `0`          | Community stars/favorites          |
| `downloadCount`    | `Int`                      | `0`          | Download count                     |
| `author`           | `String`                   | —            | Author display name                |
| `ownerId`          | `String`                   | —            | Owner user ID                      |
| `organizationId`   | `String?`                  | —            | Organization scope                 |
| `createdAt`        | `DateTime`                 | `now()`      | Creation timestamp                 |
| `updatedAt`        | `DateTime`                 | `@updatedAt` | Last-update timestamp              |
| `publishedAt`      | `DateTime?`                | —            | Publish timestamp                  |
| `deletedAt`        | `DateTime?`                | —            | Soft-delete timestamp              |
| `searchVector`     | `Unsupported("tsvector")?` | —            | PostgreSQL full-text search vector |

**Unique:** `[ownerId, name]`. **Relations:** `versions`, `jobs`,
`generatedOutputs`, `stars`.

#### WorkflowVersion (`workflow_versions`)

Immutable snapshot of a workflow definition at a specific version point. Each
version locks the complete `definition`, `parameters`, and `requirements` so
prior workflow versions are always exactly reproducible.

| Field          | Type             | Default | Description                           |
| -------------- | ---------------- | ------- | ------------------------------------- |
| `id`           | `String`         | auto    | Primary key                           |
| `workflowId`   | `String`         | —       | FK to `Workflow` (cascade delete)     |
| `version`      | `String`         | —       | Semver string                         |
| `changelog`    | `String?` (Text) | —       | Human-readable changelog              |
| `definition`   | `Json`           | —       | Complete workflow-definition snapshot |
| `parameters`   | `Json`           | `[]`    | Parameters snapshot                   |
| `requirements` | `Json`           | `{}`    | Requirements snapshot                 |
| `deprecated`   | `Boolean`        | `false` | Whether this version is deprecated    |
| `author`       | `String`         | —       | Version author                        |
| `metadata`     | `Json`           | `{}`    | Metadata                              |
| `createdAt`    | `DateTime`       | `now()` | Creation timestamp                    |

**Unique:** `[workflowId, version]`.

#### WorkflowStar (`workflow_stars`)

User star/favorite on a workflow. Fields: `id`, `workflowId`, `userId`,
`createdAt`. **Unique:** `[workflowId, userId]`.

#### WorkflowTemplate (`workflow_templates`)

Curated starter templates for quick-start workflow creation. Fields: `id`,
`name`, `description`, `engine` (`WorkflowEngine`), `category`
(`WorkflowCategory`), `definition` (`Json`), `parameters` (`Json` default `[]`),
`previewImage`, `tags` (`String[]`), `featured` (`Boolean` default `false`),
`usageCount` (`Int` default `0`), `createdAt`, `updatedAt`.

#### GeneratedOutput (`generated_outputs`)

Every file produced by a generation job; the node type of the lineage graph. The
`storageBucket` + `storageKey` pair is unique (enforced by the
`@@unique([storageBucket, storageKey])` constraint) to prevent duplicate storage
entries for the same physical file.

| Field            | Type             | Default      | Description                       |
| ---------------- | ---------------- | ------------ | --------------------------------- |
| `id`             | `String`         | auto         | Primary key                       |
| `name`           | `String`         | —            | Output filename                   |
| `description`    | `String?` (Text) | —            | Description                       |
| `type`           | `OutputFileType` | —            | File category                     |
| `mimeType`       | `String`         | —            | MIME type                         |
| `size`           | `BigInt`         | —            | File size in bytes                |
| `hashAlgorithm`  | `HashAlgorithm`  | `SHA256`     | Hash algorithm                    |
| `hashValue`      | `String`         | —            | File hash for deduplication       |
| `storageBucket`  | `String`         | —            | Object-storage bucket             |
| `storageKey`     | `String`         | —            | Object-storage key                |
| `storageTier`    | `StorageTier`    | `HOT`        | Storage lifecycle tier            |
| `storageRegion`  | `String?`        | —            | Storage region                    |
| `status`         | `OutputStatus`   | `PENDING`    | Availability status               |
| `width`          | `Int?`           | —            | Width in pixels (image/video)     |
| `height`         | `Int?`           | —            | Height in pixels (image/video)    |
| `depth`          | `Int?`           | —            | Depth dimension (3D)              |
| `duration`       | `Float?`         | —            | Duration in seconds (audio/video) |
| `frameCount`     | `Int?`           | —            | Frame count (video)               |
| `jobId`          | `String?`        | —            | FK to `GenerationJob`             |
| `workflowId`     | `String?`        | —            | FK to `Workflow`                  |
| `ownerId`        | `String`         | —            | Owner user ID                     |
| `organizationId` | `String?`        | —            | Organization scope                |
| `projectId`      | `String?`        | —            | Project reference                 |
| `tags`           | `String[]`       | `[]`         | Tags                              |
| `metadata`       | `Json`           | `{}`         | Arbitrary metadata                |
| `createdAt`      | `DateTime`       | `now()`      | Creation timestamp                |
| `updatedAt`      | `DateTime`       | `@updatedAt` | Last-update timestamp             |
| `expiresAt`      | `DateTime?`      | —            | Retention expiry timestamp        |
| `deletedAt`      | `DateTime?`      | —            | Soft-delete timestamp             |
| `accessCount`    | `Int`            | `0`          | Total access counter              |
| `lastAccessedAt` | `DateTime?`      | —            | Most recent access timestamp      |

**Relations:** `job`, `workflow`, `provenance`, `parentEdges` (LineageEdge[] via
`LineageTarget`), `childEdges` (LineageEdge[] via `LineageSource`).

#### LineageEdge (`lineage_edges`)

Directed edge in the output lineage graph. An edge connects a source output (the
origin) to a target output (the derivative). Both endpoint relations cascade-
delete so edges are removed automatically when either output is deleted.

| Field            | Type              | Default | Description                           |
| ---------------- | ----------------- | ------- | ------------------------------------- |
| `id`             | `String`          | auto    | Primary key                           |
| `sourceId`       | `String`          | —       | FK to source `GeneratedOutput`        |
| `targetId`       | `String`          | —       | FK to target `GeneratedOutput`        |
| `type`           | `LineageEdgeType` | —       | Derivation-relationship type          |
| `transformation` | `String?`         | —       | Description of transformation applied |
| `weight`         | `Float?`          | `1.0`   | Influence weight (composed outputs)   |
| `createdAt`      | `DateTime`        | `now()` | Creation timestamp                    |

**Unique:** `[sourceId, targetId]`.

#### Provenance (`provenance`)

Full generation metadata for an output, enabling reproducibility. The `outputId`
relation is 1:1 with `GeneratedOutput`, and `jobId` is unique (one provenance
record per job execution).

| Field                | Type       | Default      | Description                              |
| -------------------- | ---------- | ------------ | ---------------------------------------- |
| `id`                 | `String`   | auto         | Primary key                              |
| `outputId`           | `String`   | —            | FK to `GeneratedOutput` (unique, 1:1)    |
| `jobId`              | `String?`  | —            | FK to `GenerationJob` (unique)           |
| `workflowInfo`       | `Json?`    | —            | `{ id, name, version }` snapshot         |
| `modelInfo`          | `Json?`    | —            | `{ name, version, hash }`                |
| `lorasUsed`          | `Json`     | `[]`         | `[{ name, version, weight }]`            |
| `parameters`         | `Json`     | `{}`         | Complete generation parameters           |
| `inputs`             | `Json`     | `[]`         | `[{ outputId, url, type, description }]` |
| `seed`               | `Int?`     | —            | Random seed for reproducibility          |
| `generatedAt`        | `DateTime` | `now()`      | Generation timestamp                     |
| `generationDuration` | `Int?`     | —            | Generation duration in milliseconds      |
| `gpu`                | `String?`  | —            | GPU type used                            |
| `provider`           | `String?`  | —            | AI provider used                         |
| `cost`               | `Float?`   | —            | Actual cost in USD                       |
| `createdAt`          | `DateTime` | `now()`      | Creation timestamp                       |
| `updatedAt`          | `DateTime` | `@updatedAt` | Last-update timestamp                    |

#### ModelRegistry (`model_registry`)

Registry of available AI model checkpoints, LoRAs, and other artifacts. The
`[name, version]` pair is unique, ensuring no two registry entries refer to the
same model version.

| Field               | Type               | Default      | Description                      |
| ------------------- | ------------------ | ------------ | -------------------------------- |
| `id`                | `String`           | auto         | Primary key                      |
| `name`              | `String`           | —            | Model name                       |
| `description`       | `String?` (Text)   | —            | Description                      |
| `type`              | `ModelType`        | —            | Model type                       |
| `format`            | `ModelFormat`      | —            | File format                      |
| `version`           | `String`           | —            | Version string                   |
| `storagePath`       | `String`           | —            | Storage path                     |
| `sizeBytes`         | `BigInt`           | —            | File size in bytes               |
| `hashAlgorithm`     | `HashAlgorithm`    | `SHA256`     | Hash algorithm                   |
| `hashValue`         | `String`           | —            | File hash for integrity          |
| `baseModel`         | `String?`          | —            | Base model identifier            |
| `trainedOn`         | `String?` (Text)   | —            | Training-data description        |
| `triggerWords`      | `String[]`         | `[]`         | Trigger words (LoRAs/embeddings) |
| `tags`              | `String[]`         | `[]`         | Searchable tags                  |
| `metadata`          | `Json`             | `{}`         | Metadata                         |
| `compatibleEngines` | `WorkflowEngine[]` | `[]`         | Compatible workflow engines      |
| `usageCount`        | `Int`              | `0`          | Cumulative usage count           |
| `downloadCount`     | `Int`              | `0`          | Download count                   |
| `starCount`         | `Int`              | `0`          | Community stars                  |
| `uploaderId`        | `String`           | —            | Uploader user ID                 |
| `organizationId`    | `String?`          | —            | Organization scope               |
| `isPublic`          | `Boolean`          | `false`      | Global vs organization-scoped    |
| `isActive`          | `Boolean`          | `true`       | Whether the model is active      |
| `isVerified`        | `Boolean`          | `false`      | Whether the model is verified    |
| `createdAt`         | `DateTime`         | `now()`      | Creation timestamp               |
| `updatedAt`         | `DateTime`         | `@updatedAt` | Last-update timestamp            |
| `deletedAt`         | `DateTime?`        | —            | Soft-delete timestamp            |

**Unique:** `[name, version]`. **Relations:** `jobs`.

### Canonical Model and Governance Models

A second model-management cluster carries richer, governance-grade contracts for
model cards, version lineage, provenance bundles, and review packages. All five
use `uuid()` primary keys and a unique `slug` / `graphId`. These models are
separate from `ModelRegistry` because they capture compliance and review
metadata that goes beyond simple operational tracking.

| Model              | Table                 | Purpose                                                                                                                                                         |
| ------------------ | --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ModelCard`        | `model_cards`         | Canonical model card: source, creator, licenses, hashes, overview, usage, training, evaluation, limitations, ethics, safety, governance, citations, changelog.  |
| `ModelVersion`     | `model_versions`      | Per-version record: lineage, files, runtime, telemetry, safety, governance, deployments, release notes.                                                         |
| `ProvenanceBundle` | `provenance_bundles`  | Provenance bundle: artifacts, workflow, models, lineage nodes/edges, watermark signals, disclosure, rights, review, integrity.                                  |
| `ReviewPackage`    | `review_packages`     | Governance review package: stages, decisions, delegations, attestations, exceptions, SLA clocks, governance export, release check.                              |
| `ReviewStageGraph` | `review_stage_graphs` | Versioned stage-graph template (`@@unique([graphId, version])`) referenced by `ReviewPackage.stageGraphId` at submission to stamp the package's `stages` array. |

### Retention, Worker, and Audit Models

#### RetentionPolicy (`retention_policies`)

Storage-lifecycle configuration controlling how outputs transition between
tiers. A policy with `organizationId = null` is the global default; org-scoped
policies override it for that organization's outputs.

| Field                        | Type               | Default | Description                         |
| ---------------------------- | ------------------ | ------- | ----------------------------------- |
| `id`                         | `String`           | auto    | Primary key                         |
| `name`                       | `String`           | —       | Policy name (unique)                |
| `description`                | `String?` (Text)   | —       | Description                         |
| `hotRetentionDays`           | `Int`              | `30`    | Days to keep in HOT tier            |
| `warmRetentionDays`          | `Int`              | `90`    | Days to keep in WARM tier           |
| `coldRetentionDays`          | `Int`              | `365`   | Days to keep in COLD tier           |
| `totalRetentionDays`         | `Int`              | `730`   | Total retention before deletion     |
| `archiveAfterInactivityDays` | `Int?`             | —       | Archive after N days inactive       |
| `outputTypes`                | `OutputFileType[]` | `[]`    | Output types this policy applies to |
| `tags`                       | `String[]`         | `[]`    | Tag scope                           |
| `isActive`                   | `Boolean`          | `true`  | Whether the policy is enforced      |
| `organizationId`             | `String?`          | —       | Org scope (null = global default)   |
| `createdAt`/`updatedAt`      | `DateTime`         | —       | Timestamps                          |

#### GpuWorker (`gpu_workers`)

Registration record for each GPU worker instance. Workers self-register at
startup and update `lastHeartbeat` periodically; the generation API uses
`supportedTypes` and `supportedEngines` to route jobs to capable workers.

| Field                   | Type               | Default     | Description                       |
| ----------------------- | ------------------ | ----------- | --------------------------------- |
| `id`                    | `String`           | auto        | Primary key                       |
| `name`                  | `String`           | —           | Worker display name               |
| `hostname`              | `String`           | —           | Hostname (unique)                 |
| `gpuType`               | `String`           | —           | GPU model                         |
| `gpuMemoryMb`           | `Int`              | —           | GPU VRAM in MB                    |
| `gpuCount`              | `Int`              | `1`         | Number of GPUs                    |
| `supportedTypes`        | `GenerationType[]` | `[]`        | Supported `GenerationType` values |
| `supportedEngines`      | `WorkflowEngine[]` | `[]`        | Supported workflow engines        |
| `maxConcurrentJobs`     | `Int`              | `1`         | Concurrency cap                   |
| `status`                | `String`           | `"offline"` | Worker status                     |
| `lastHeartbeat`         | `DateTime?`        | —           | Last heartbeat timestamp          |
| `currentJobId`          | `String?`          | —           | Currently-assigned job ID         |
| `totalJobsProcessed`    | `Int`              | `0`         | Cumulative job count              |
| `totalGpuTimeSeconds`   | `BigInt`           | `0`         | Cumulative GPU time               |
| `averageJobDuration`    | `Float?`           | —           | Average job duration              |
| `metadata`              | `Json`             | `{}`        | Metadata                          |
| `createdAt`/`updatedAt` | `DateTime`         | —           | Timestamps                        |

#### AuditLog (`audit_log`)

Per-entity change tracking for operational audit purposes. Fields: `id`,
`action`, `entityType`, `entityId`, `previousState` (`Json?`), `newState`
(`Json?`), `changes` (`Json?`), `userId`, `ipAddress`, `userAgent`, `requestId`,
`metadata`, `createdAt`.

#### CanonicalAuditEvent (`canonical_audit_events`)

The canonical platform audit event (per ADR-0023). This model is append-only —
no update or delete. `eventId` is the UUID primary key. It carries the full
canonical envelope defined in `@oshun/contracts`
(`CanonicalPlatformAuditEventSchema`):

- **Actor fields:** `actorType`, `actorId`, `actorRole`, `actorLabel`,
  `actorSystem`
- **Target fields:** `resourceType`, `resourceId`, `resourceName`, `domain`,
  parent resource, `tenantId`
- **Required canonical fields:** `reason`, `traceId`, `spanId`, `requestId`,
  `sessionId`
- **Evidence fields:** `ipAddress`, `userAgent`, `geo`
- **Payload fields:** `previousState`, `newState`, `metadata`
- **Compliance fields:** `policyId`, `retentionTag`, `schemaVersion`

### Pipeline-State Persistence Models

Six models persist `PipelineOrchestrator` runs so they survive BFF restarts.
They back the `PostgresPipelineRepository` in
`libs/isis/operation-orchestrator/src/persistence`.

IDs are `uuid`-typed so the orchestrator's branded `PipelineId` / `ChainId`
round-trip without conversion. Status fields are stored as `String` (not Prisma
enums) because the orchestrator's `ChainStatus` and `CheckpointDecisionStatus`
are TypeScript const-objects that may gain values in patch releases without
requiring a database migration.

Cascade deletes mirror runtime semantics: deleting a pipeline drops its chains;
deleting a chain drops its phases; deleting a phase drops its artifacts and
checkpoints.

| Model                | Table                                 | Role                                                                                               |
| -------------------- | ------------------------------------- | -------------------------------------------------------------------------------------------------- |
| `Pipeline`           | `pipeline_state_pipelines`            | Top-level run: name, status, started/completed, metadata, tenant/user.                             |
| `Chain`              | `pipeline_state_chains`               | Chain within a pipeline (cascade from pipeline).                                                   |
| `Phase`              | `pipeline_state_phases`               | Phase within a chain: `phaseType`, status, `durationMs`, `ordinal`.                                |
| `PhaseArtifact`      | `pipeline_state_phase_artifacts`      | Artifact of a phase: `key`, `mimeType`, `inlineData` or `artifactUri`. `@@unique([phaseId, key])`. |
| `Checkpoint`         | `pipeline_state_checkpoints`          | Human-review checkpoint: status, `awaitedAt`, `deadlineAt`.                                        |
| `CheckpointDecision` | `pipeline_state_checkpoint_decisions` | Decision on a checkpoint: status, reviewer, `reviewedAt`, `notes`, `modifications`.                |

---

## Enumerations

The schema defines 14 enums. All enum values listed here are exact — they must
match in code, API payloads, and any external integrations.

### JobStatus

The six states a `GenerationJob` passes through:

`PENDING`, `QUEUED`, `RUNNING`, `COMPLETED`, `FAILED`, `CANCELLED`

(The generation-api request/response layer in `job.schema.ts` uses the same six
values in lowercase: `pending`, `queued`, `running`, `completed`, `failed`,
`cancelled`.)

### JobPriority

`LOW`, `NORMAL`, `HIGH`, `URGENT`

### GenerationType (15 values)

The complete set of generation modes supported by the domain:

`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`, `TEXTURE_UPSCALE`

### WorkflowEngine

`COMFYUI`, `BLENDER`, `UNREAL`, `GODOT`, `CUSTOM`

### WorkflowStatus

`DRAFT`, `PUBLISHED`, `DEPRECATED`, `ARCHIVED`

### WorkflowVisibility

`PRIVATE`, `TEAM`, `ORGANIZATION`, `PUBLIC`

### WorkflowCategory (12 values)

`IMAGE_GENERATION`, `VIDEO_GENERATION`, `AUDIO_GENERATION`, `GENERATION_3D`,
`UPSCALING`, `STYLE_TRANSFER`, `INPAINTING`, `COMPOSITING`, `RENDERING`,
`SIMULATION`, `UTILITY`, `OTHER`

### OutputFileType (11 values)

`IMAGE`, `VIDEO`, `AUDIO`, `MODEL_3D`, `POINT_CLOUD`, `ANIMATION`, `TEXTURE`,
`MATERIAL`, `DOCUMENT`, `DATA`, `OTHER`

### OutputStatus

`PENDING`, `AVAILABLE`, `ARCHIVED`, `EXPIRED`, `DELETED`

### StorageTier

The four storage tiers from hottest (most accessible, most expensive) to coldest
(least accessible, cheapest):

`HOT`, `WARM`, `COLD`, `GLACIER`

### HashAlgorithm

`SHA256`, `SHA512`, `MD5`, `BLAKE3`

### LineageEdgeType

`DERIVED_FROM`, `COMPOSED_OF`, `REFINED_FROM`, `UPSCALED_FROM`, `CONVERTED_FROM`

### ModelType

`CHECKPOINT`, `LORA`, `CONTROLNET`, `VAE`, `EMBEDDING`, `UPSCALER`, `CUSTOM`

### ModelFormat

`SAFETENSORS`, `PYTORCH`, `ONNX`, `GGUF`, `BLEND`, `GLTF`, `FBX`, `OTHER`

---

## Job Envelope Contract

The job envelope is the canonical queue message defined by `@isis/job-envelope`
(`libs/isis/job-envelope/src/job-envelope.ts`). It is **not** a flat copy of the
`GenerationJob` row — it is a compact, strict Zod-validated message designed for
reliable serialization over a Redis queue. Every producer (API, SDK, CLI) and
every consumer (GPU workers, executors) uses this exact shape.

```typescript
export const ISIS_JOB_ENVELOPE_VERSION = '1.0.0';

interface IsisJobEnvelope {
  jobId: string; // UUID
  type: IsisGenerationType;
  input: Record<string, unknown>;
  priority: IsisJobPriority; // 'low' | 'normal' | 'high' | 'urgent'
  metadata: IsisJobEnvelopeMetadata; // { userId?, projectId?, correlationId?, ...catchall }
  idempotencyKey: string; // non-empty, max 128 chars
}
```

`IsisJobEnvelopeSchema` is `.strict()` — unknown top-level keys are rejected.
`IsisJobEnvelopeMetadataSchema` is a `.catchall(z.unknown())` object: `userId`,
`projectId`, and `correlationId` are typed optionals; any other key is allowed.

Helper functions exported alongside the schema: `createIsisJobEnvelope()`,
`parseIsisJobEnvelope()`, `safeParseIsisJobEnvelope()`, `isIsisJobEnvelope()`.
`createIsisJobEnvelope()` defaults `priority` to `'normal'`, `metadata` to `{}`,
and `idempotencyKey` to the `jobId` when not supplied.

### Generation-type identifiers (`ISIS_GENERATION_TYPES`)

The envelope's `type` field uses kebab-case identifiers, which differ from the
database `GenerationType` enum's `SCREAMING_SNAKE_CASE`. There are 18 total: the
15 standard modes plus three scene-from-image composer dispatch types.

`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`, `texture-upscale`,
`scene-from-image-environment`, `scene-from-image-mesh`,
`scene-from-image-bake`.

`ISIS_GENERATION_TYPE_ALIASES` maps legacy `SCREAMING_SNAKE`/`snake_case`
spellings (e.g. `BLENDER_RENDER`, `blender_render`) onto the kebab-case
canonical values; `normalizeIsisGenerationType()` resolves any input form. This
means callers do not need to know which spelling the system expects — they can
submit in any historically-used form and it will be normalized.

### Composer dispatch payloads (`@isis/job-envelope/payloads`)

`payloads.ts` defines typed input/output payloads for the three scene-from-image
dispatch types. These are the shapes that the `@isis/scene-from-image-composer`
uses when dispatching work to the GPU worker pool:

- `EnvironmentDispatchInput` / `EnvironmentDispatchOutput`
- `MeshDispatchInput` / `MeshDispatchOutput`
- `BakeDispatchInput` / `BakeDispatchOutput`
- `ScenecomposerDispatchPayload` (union of the three above)
- `SCENECOMPOSER_DISPATCH_TYPES` constant

Binary buffers are wrapped via `encodeDispatchBuffer()` /
`decodeDispatchBuffer()` (`DispatchBuffer`).

---

## Generation-Type Manifest

`ISIS_GENERATION_TYPE_MANIFEST` in `job-envelope.ts` is the single source of
truth for what each generation type requires and produces. It is a
`Record<IsisGenerationType, IsisGenerationTypeManifestEntry>` covering all 18
generation types. Every entry declares:

| Field                       | Meaning                                                              |
| --------------------------- | -------------------------------------------------------------------- |
| `generationType`            | The kebab-case type identifier                                       |
| `label`                     | Human-readable label                                                 |
| `description`               | Short description                                                    |
| `ui.requiresPrompt`         | Whether a text prompt is required                                    |
| `ui.requiresInputUrl`       | Whether an input file URL is required                                |
| `ui.supportsNegativePrompt` | Whether a negative prompt is accepted                                |
| `ui.supportsImageControls`  | Whether ControlNet/IP-Adapter/InstantID controls apply               |
| `outputPackageDescription`  | Human-readable output-package description                            |
| `outputPackageRules`        | `{ type: IsisOutputPackageType; multiple? }[]` — valid output shapes |

`IsisOutputPackageType` is `image | video | audio | 3d | text`. The helper
`isIsisOutputPackageCompatibleWithGenerationType()` validates a produced package
against a type's rules. For example, `text-to-3d` and `image-to-3d` accept
either a `3d` package or a multi-image reconstruction package — the manifest
entry encodes both valid shapes.

---

## Control-Input Vocabulary

`@isis/job-envelope` defines the canonical vocabulary for image-conditioning
controls (ControlNet, IP-Adapter, InstantID). This vocabulary is shared by all
producers and consumers so that parameter names never drift between the API, the
GPU worker, and ComfyUI workflow nodes.

| Vocabulary                        | Values                                                                                               |
| --------------------------------- | ---------------------------------------------------------------------------------------------------- |
| `ISIS_CONTROLNET_MAJOR_MODES`     | `pose`, `depth`, `canny`, `lineart`, `seg`, `normal`                                                 |
| `ISIS_IPADAPTER_MAJOR_MODES`      | `style`, `face`, `composition`                                                                       |
| `ISIS_INSTANTID_MAJOR_MODES`      | `instantid`, `faceid`                                                                                |
| `ISIS_CONTROL_INPUT_SOURCE_KINDS` | `image`, `sequence`, `cached-feature-map`                                                            |
| `ISIS_CONTROL_BLEND_DOMAINS`      | `controlnet`, `ipadapter`, `instantid`                                                               |
| `ISIS_CONTROL_PRESET_IDS`         | `cinematic-asset-control`, `stylized-asset-control`, `concept-art-control`, `gameplay-asset-control` |
| `ISIS_CONTROL_BLEND_CURVES`       | `linear`, `ease-in`, `ease-out`, `ease-in-out`, `hold`                                               |

`ISIS_DEFAULT_CONTROL_BLEND_PRECEDENCE` is `instantid` → `ipadapter` →
`controlnet`. When multiple control domains are active simultaneously, this
precedence order determines which one wins at each pixel.

Each vocabulary has an alias map and a `normalize*` function, plus legacy-
workflow-mode maps (`ISIS_CONTROLNET_LEGACY_WORKFLOW_MODE_MAP`, etc.) that
translate major modes into the string identifiers older ComfyUI workflows
expect.

---

## API Surface

All three REST services are Hono apps. `/api/*` routes are rate-limited
(generation-api: 100 requests per 60 seconds), require authentication, and pass
through a structured security-log middleware. `/health` and `/ready` bypass
authentication.

### Generation API (`apps/isis/generation-api`, port 3000)

Mounts: `/api/v1/jobs`, `/api/v1/queue/stats`, `/api/v1/models`,
`/api/v1/workflows`, `/api/v1/webhook-subscriptions`, and `/webhooks` (provider
callbacks). Route modules are `jobs.ts`, `models.ts`, `workflows.ts`,
`webhook-subscriptions.ts`, and `provider-callbacks.ts`.

#### Jobs (`/api/v1/jobs`)

The jobs endpoints cover the full lifecycle from submission through output
retrieval. Admin endpoints (prefixed `/admin/`) provide operational tools for
backfilling missing data and managing the queue.

| Method   | Path                                  | Description                            |
| -------- | ------------------------------------- | -------------------------------------- |
| `POST`   | `/`                                   | Submit a generation job                |
| `POST`   | `/batch`                              | Submit a batch of jobs (max 100)       |
| `GET`    | `/`                                   | List jobs with filters and pagination  |
| `GET`    | `/stats`                              | Queue-statistics snapshot              |
| `GET`    | `/providers/operations`               | Provider operations snapshot           |
| `GET`    | `/runpod/operations`                  | RunPod operations snapshot             |
| `GET`    | `/providers/compatibility`            | Provider/generation-type compatibility |
| `GET`    | `/feature-flags`                      | Provider-routing diagnostics           |
| `PATCH`  | `/feature-flags/:key`                 | Update a provider-routing feature flag |
| `GET`    | `/dead-letter`                        | List dead-letter queue entries         |
| `POST`   | `/dead-letter/:outboxId/replay`       | Replay a dead-letter entry             |
| `GET`    | `/admin/queue/health`                 | Admin queue-health snapshot            |
| `POST`   | `/admin/queue/drain`                  | Drain waiting/delayed queue jobs       |
| `POST`   | `/admin/legacy-pending/recover`       | Recover legacy pending jobs            |
| `POST`   | `/admin/workflow-ids/backfill`        | Backfill missing workflow IDs          |
| `POST`   | `/admin/generation-types/backfill`    | Backfill missing generation types      |
| `POST`   | `/admin/historical-taxonomy/backfill` | Backfill historical job taxonomy       |
| `POST`   | `/admin/costs/backfill`               | Backfill missing historical costs      |
| `GET`    | `/:id`                                | Get a job's details                    |
| `GET`    | `/:id/status`                         | Get a job's status snapshot            |
| `GET`    | `/:id/queue-position`                 | Get a job's current queue position     |
| `POST`   | `/:id/retry`                          | Retry a job                            |
| `POST`   | `/:id/cancel`                         | Cancel a pending/queued/running job    |
| `DELETE` | `/:id`                                | Soft-delete a job                      |
| `GET`    | `/:id/output`                         | Get a job's output and artifacts       |
| `GET`    | `/:id/audio`                          | Get the job audio-contract snapshot    |

#### Models (`/api/v1/models`)

The models endpoints manage the model registry, including pre-signed upload URLs
for large model files that bypass the API server.

| Method   | Path                      | Description                         |
| -------- | ------------------------- | ----------------------------------- |
| `POST`   | `/`                       | Register a new model                |
| `GET`    | `/`                       | List models with filters            |
| `GET`    | `/audit-logs`             | List model audit-log entries        |
| `GET`    | `/:id`                    | Get model details                   |
| `PUT`    | `/:id`                    | Update model metadata               |
| `DELETE` | `/:id`                    | Delete a model                      |
| `GET`    | `/:id/versions`           | List a model's versions             |
| `POST`   | `/:id/upload-url`         | Get a pre-signed upload URL         |
| `POST`   | `/:id/upload-complete`    | Mark an upload complete             |
| `GET`    | `/:id/download-url`       | Get a pre-signed download URL       |
| `GET`    | `/by-name/:name/:version` | Look up a model by name and version |

#### Workflow execution (`/api/v1/workflows`)

| Method | Path                                   | Description               |
| ------ | -------------------------------------- | ------------------------- |
| `POST` | `/:workflowId/run`                     | Run a workflow            |
| `POST` | `/triggers/batch`                      | Batch-trigger workflows   |
| `POST` | `/triggers/chained`                    | Chained-trigger workflows |
| `GET`  | `/:workflowId/executions`              | List workflow executions  |
| `GET`  | `/:workflowId/executions/:executionId` | Get a single execution    |

The workflow-run path validates a typed contract per workflow recipe (see
[Asset-Pack Workflow Recipes](#asset-pack-workflow-recipes)).

#### Webhook subscriptions (`/api/v1/webhook-subscriptions`)

Manages callback subscriptions for job lifecycle events. Provides full CRUD plus
lifecycle operations:

`GET /event-types`, `GET /event-schemas`, `GET /event-schemas/:eventType`,
`POST /callback-security/sign`, `POST /callback-security/verify`, `POST /`,
`GET /`, `GET /:subscriptionId`, `PATCH /:subscriptionId`,
`DELETE /:subscriptionId`, `POST /:subscriptionId/activate`,
`POST /:subscriptionId/pause`, `POST /:subscriptionId/rotate-secret`.

#### Provider callbacks (`/webhooks`)

`POST /webhooks/runpod` — signature-validated callback endpoint for RunPod
provider results. Runs outside the authenticated `/api/*` namespace so RunPod
can call it directly.

#### Health endpoints

`GET /health` — liveness probe; always returns 200 if the process is running.
`GET /ready` — readiness probe; runs job-service, model-service, and
ComfyUI-service health checks in parallel and returns `200`/`503` with a
per-dependency breakdown (jobs DB, models DB, queue, storage, provider).

### Workflow Registry (`apps/isis/workflow-registry`, port 3001)

Mounts `/api/v1/workflows`, `/api/v1/templates`, `/api/v1/staging-recipes`, plus
`/health` and `/ready`. The workflow service supports two storage backends —
`postgres` (production) and `in-memory` (explicit test/dev override).

| Method   | Path (under `/api/v1`)                       | Description                        |
| -------- | -------------------------------------------- | ---------------------------------- |
| `GET`    | `/workflows`                                 | List workflows with filters        |
| `GET`    | `/workflows/audit-logs`                      | Workflow audit-log entries         |
| `GET`    | `/workflows/:id`                             | Get workflow details               |
| `GET`    | `/workflows/:id/metadata`                    | Get workflow metadata              |
| `GET`    | `/workflows/:id/export`                      | Export a workflow                  |
| `GET`    | `/workflows/:id/stats`                       | Get workflow run statistics        |
| `POST`   | `/workflows/:id/star`                        | Star a workflow                    |
| `DELETE` | `/workflows/:id/star`                        | Un-star a workflow                 |
| `DELETE` | `/workflows/:id`                             | Delete a workflow                  |
| `POST`   | `/workflows/:id/restore`                     | Restore a deleted workflow         |
| `POST`   | `/workflows/:id/validate`                    | Validate a workflow definition     |
| `GET`    | `/workflows/:id/versions`                    | List versions                      |
| `GET`    | `/workflows/:id/versions/tag/:versionTag`    | Get a version by tag               |
| `GET`    | `/workflows/:id/versions/:version`           | Get a specific version             |
| `POST`   | `/workflows/:id/versions/:version/activate`  | Activate a version                 |
| `DELETE` | `/workflows/:id/versions/:version`           | Delete a version                   |
| `POST`   | `/workflows/:id/versions/:version/deprecate` | Deprecate a version                |
| `POST`   | `/workflows/:id/versions/:version/restore`   | Restore a version                  |
| `GET`    | `/templates`                                 | List templates                     |
| `GET`    | `/templates/featured`                        | List featured templates            |
| `GET`    | `/templates/:id`                             | Get a template                     |
| `POST`   | `/templates/:id/create`                      | Create a workflow from a template  |
| `GET`    | `/staging-recipes`                           | List staging recipes               |
| `GET`    | `/staging-recipes/:id`                       | Get a staging recipe               |
| `DELETE` | `/staging-recipes/:id`                       | Delete a staging recipe            |
| `GET`    | `/staging-recipes/:id/promotion`             | Get staging-recipe promotion state |

### Output Registry (`apps/isis/output-registry`, port 3002)

Mounts `/api/v1/outputs`, `/api/v1/policies`, `/api/v1/provenance`, plus
`/health` and `/ready`.

| Method   | Path (under `/api/v1`)                 | Description                          |
| -------- | -------------------------------------- | ------------------------------------ |
| `POST`   | `/outputs`                             | Register a generated output          |
| `GET`    | `/outputs`                             | List outputs with filters            |
| `GET`    | `/outputs/stats`                       | Output statistics                    |
| `POST`   | `/outputs/batch-delete`                | Batch-delete outputs                 |
| `POST`   | `/outputs/upload-url`                  | Get a pre-signed output upload URL   |
| `GET`    | `/outputs/:id`                         | Get output metadata                  |
| `GET`    | `/outputs/:id/download`                | Get a pre-signed download URL        |
| `PATCH`  | `/outputs/:id`                         | Update output metadata               |
| `DELETE` | `/outputs/:id`                         | Soft-delete an output                |
| `POST`   | `/outputs/:id/move-tier`               | Move an output between storage tiers |
| `POST`   | `/outputs/:id/restore`                 | Restore a deleted output             |
| `POST`   | `/outputs/:id/verify`                  | Verify output integrity              |
| `GET`    | `/outputs/:id/provenance`              | Get an output's provenance           |
| `POST`   | `/outputs/:id/provenance`              | Register provenance for an output    |
| `GET`    | `/outputs/:id/lineage`                 | Get the lineage graph for an output  |
| `GET`    | `/outputs/:id/ancestors`               | Get an output's ancestors            |
| `GET`    | `/outputs/:id/descendants`             | Get an output's descendants          |
| `POST`   | `/outputs/lineage`                     | Add a lineage edge                   |
| `DELETE` | `/outputs/lineage/:sourceId/:targetId` | Delete a lineage edge                |
| `GET`    | `/policies`                            | List retention policies              |
| `GET`    | `/policies/:name`                      | Get a retention policy               |
| `POST`   | `/policies`                            | Create a retention policy            |
| `PATCH`  | `/policies/:name`                      | Update a retention policy            |
| `DELETE` | `/policies/:name`                      | Delete a retention policy            |
| `POST`   | `/policies/apply`                      | Apply retention policies             |
| `PATCH`  | `/provenance/:id`                      | Update a provenance record           |

### Asset-Pack Workflow Recipes

`apps/isis/generation-api/src/schemas/` defines 32 typed asset-pack workflow
recipes. Each recipe has its own request schema and a
`validate<Recipe>WorkflowRunContract` function consumed by the
`/api/v1/workflows/:workflowId/run` route. Each recipe additionally carries a
budget-utility module, a quality-gate-utility module, and a regression
golden-dataset module under `generation-api/src/routes/`.

The 32 recipes are:

`animatic-shot-set`, `architecture-kitbash-pack`, `audio-sfx-pack`,
`character-concept-art`, `character-costume-variant-pack`,
`character-expression-sheet`, `character-prop-interaction-sheet`,
`character-turnaround-sheet`, `cinematic-shot-sequence`, `creature-concept-art`,
`decal-pack`, `environment-concept-art`, `environment-matte-painting`,
`environment-tileset-pack`, `foliage-pack`, `hud-element-pack`,
`interior-scene-pack`, `marketing-key-art-pack`, `material-pbr-pack`,
`music-cue-pack`, `npc-crowd-variation-pack`, `prop-pack-general`,
`sky-atmosphere-pack`, `social-cutdown-pack`, `storyboard-frame-set`,
`terrain-heightmap-pack`, `ui-icon-pack`, `vehicle-exterior-pack`,
`vehicle-interior-pack`, `vfx-element-pack`, `voice-line-pack`, `weapon-pack`.

---

## Job Lifecycle

### Database Job Status (`JobStatus`)

The following state machine governs `GenerationJob.status`. A job begins at
`PENDING`, advances through `QUEUED` and `RUNNING`, and ends at one of three
terminal states. `FAILED` jobs may be retried while `retryCount < maxRetries`;
cancellation is possible from any non-terminal state.

```
PENDING ──► QUEUED ──► RUNNING ──► COMPLETED
   │           │          │
   │           │          └──────► FAILED ──► (retry → QUEUED while retryCount < maxRetries)
   │           │
   └───────────┴─────────────────► CANCELLED
```

The `progress` field advances from 0 to 100 during the `RUNNING` phase. Long-
running jobs (3D generation, Blender renders) use this to display meaningful
progress indicators in the UI and CLI.

### GPU-Worker Internal Job Status

The `gpu-worker` app tracks a finer-grained per-job status that is not stored in
the database — it is internal to the worker process (`gpu-worker/src/types.ts`):
`pending`, `downloading`, `processing`, `uploading`, `completed`, `cancelled`,
`failed`. The worker process itself has a separate `WorkerStatus`: `idle`,
`initializing`, `processing`, `shutting-down`, `error`. Worker job priority adds
a `background` tier beyond the database `JobPriority` enum.

### GPU-Worker Executors

`apps/isis/gpu-worker/src/executors/` registers four concrete executors over a
`BaseExecutor` / `registerExecutor` / `createExecutor` registry. All other
generation types route through the generic executor that calls external provider
APIs.

| Executor                    | Worker type                                        |
| --------------------------- | -------------------------------------------------- |
| `TextureUpscaleExecutor`    | `texture-upscale`                                  |
| `BlenderRenderExecutor`     | `blender-render`                                   |
| `MeshProcessingExecutor`    | `gaussian-splatting` companion / `mesh-processing` |
| `GaussianSplattingExecutor` | `gaussian-splatting`                               |

The `WorkerTypeSchema` enum recognises seven worker types: `texture-upscale`,
`mesh-processing`, `blender-render`, `gaussian-splatting`, `video-generation`,
`neural-bake`, `general`.

---

## Event Contracts

Isis publishes events through `@isis/event-publisher`
(`libs/isis/event-publisher`), which wraps `@oshun/event-bus` (Redis Streams).
Event types and payload schemas are defined canonically in `@oshun/contracts`
(`libs/contracts/src/events/isis.ts`) as `IsisEventTypes`. This separation means
that changes to the Isis internal implementation never affect the event contract
that other domains depend on — only changes to `@oshun/contracts` do.

### Events Published

The following table lists every event type, the `@isis/event-publisher` method
that emits it, and the payload schema in `@oshun/contracts`:

| Event type                 | Publisher method            | Payload schema                        |
| -------------------------- | --------------------------- | ------------------------------------- |
| `isis.job.queued`          | `publishJobQueued`          | `IsisJobQueuedPayloadSchema`          |
| `isis.job.started`         | `publishJobStarted`         | `IsisJobStartedPayloadSchema`         |
| `isis.job.progress`        | `publishJobProgress`        | `IsisJobProgressPayloadSchema`        |
| `isis.job.completed`       | `publishJobCompleted`       | `IsisJobCompletedPayloadSchema`       |
| `isis.job.failed`          | `publishJobFailed`          | `IsisJobFailedPayloadSchema`          |
| `isis.job.cancelled`       | `publishJobCancelled`       | `IsisJobCancelledPayloadSchema`       |
| `isis.asset.generated`     | `publishAssetGenerated`     | `IsisAssetGeneratedPayloadSchema`     |
| `isis.workflow.registered` | `publishWorkflowRegistered` | `IsisWorkflowRegisteredPayloadSchema` |
| `isis.workflow.updated`    | `publishWorkflowUpdated`    | `IsisWorkflowUpdatedPayloadSchema`    |
| `isis.model.loaded`        | `publishModelLoaded`        | `IsisModelLoadedPayloadSchema`        |

The `@oshun/contracts` event layer uses its own coarse `GenerationTypeSchema`
(`image`, `video`, `audio`, `model_3d`, `texture`, `animation`, `avatar`,
`world`) and `GenerationStatusSchema` (`queued`, `processing`, `completed`,
`failed`, `cancelled`) for cross-domain payloads — these are distinct from the
Isis database `GenerationType` enum and are intentionally simpler.

### Representative Payload Shapes

The following examples show the most commonly consumed event payloads. Full
schemas are in `@oshun/contracts`.

- **`isis.job.queued`** — `jobId`, `projectId`, `userId`, `type`, `workflow`,
  `priority` (0–10 int), `estimatedDurationMs?`, `queuePosition?`, `parameters`.
- **`isis.job.completed`** — `jobId`, `projectId`, `userId`, `type`, `workflow`,
  `durationMs`, `outputs[]` (`assetId`, `type`, `url`, `filename`, `sizeBytes`,
  `metadata?`), optional `metrics` (`gpuTimeMs`, `memoryPeakMb`,
  `modelLoadTimeMs`).
- **`isis.job.failed`** — `jobId`, `projectId`, `userId`, `type`, `workflow`,
  `error` (`code`, `message`, `details?`, `retryable`), `attemptCount`,
  `totalDurationMs`.
- **`isis.asset.generated`** — `assetId`, `projectId`, `userId`, `jobId`,
  `type`, `name`, `filename`, `url`, `sizeBytes`, `mimeType`, `provenance`
  (`model`, `modelVersion?`, `workflow`, `prompt?`, `seed?`, `parameters?`),
  optional `thumbnails`.

### Event Publisher Configuration

Event publishing is non-fatal: a publish failure is logged and swallowed so it
never breaks the main generation flow. The publisher is configurable via
`IsisEventPublisherConfig` (`redisUrl`, `enabled`, `keyPrefix`) and can be
disabled entirely with `ISIS_EVENTS_ENABLED=false`. The default `keyPrefix` is
`oshun:events`.

The `gpu-worker` additionally emits _internal_ (in-process, non-bus) lifecycle
events on its own event emitter: `worker:started`, `worker:stopped`,
`worker:health`, `job:started`, `job:progress`, `job:completed`, `job:failed`.
These are not published to Redis Streams and are not visible outside the worker
process.

---

## Library Inventory

`libs/isis/` contains **55 library directories**: 54 `@isis/*` TypeScript
packages plus one Python package (`comfyui-nodes`, packaged with
`pyproject.toml`, no `package.json`). Every directory has real `src/` source.

### Core platform

| Package                 | Role                                                                                              |
| ----------------------- | ------------------------------------------------------------------------------------------------- |
| `@isis/client`          | TypeScript SDK (`IsisClient`, `HttpTransport`, `RequestBuilder`)                                  |
| `@isis/database`        | Prisma schema (1141 lines, 24 models) and generated client                                        |
| `@isis/job-envelope`    | Job-envelope Zod schema, generation-type manifest, control vocabulary, composer dispatch payloads |
| `@isis/event-publisher` | Typed lifecycle-event publishing onto `@oshun/event-bus`                                          |
| `@isis/workflows`       | Workflow-registry domain library: definition storage, versioning, templates                       |
| `@isis/outputs`         | Output-manifest management: file tracking, storage tiering, retention                             |

### AI providers and LLM

| Package                        | Role                                                                                                       |
| ------------------------------ | ---------------------------------------------------------------------------------------------------------- |
| `@isis/ai-providers`           | Unified provider adapters (LLM, image, video, video-processing, TTS, 3D, ComfyUI, Civitai, model-registry) |
| `@isis/llm-providers`          | Additional LLM provider adapters                                                                           |
| `@isis/llm-orchestrator`       | LLM orchestration for multi-step workflows                                                                 |
| `@isis/batch-llm-processing`   | Batch LLM inference for high-volume text tasks                                                             |
| `@isis/token-budget`           | LLM token-budget allocation, prediction, enforcement                                                       |
| `@isis/agent-consensus`        | Multi-agent debate, reasoning, and consensus                                                               |
| `@isis/react-framework`        | ReAct-pattern tool-using agent execution framework                                                         |
| `@isis/prompt-engineering`     | Prompt templates, builder, analyzer, optimizer                                                             |
| `@isis/operation-orchestrator` | Multi-step operation orchestration, retry, dead-letter, pipeline/chain/phase model                         |
| `@isis/managed-models`         | Managed-model browser surface                                                                              |

### ComfyUI

| Package                  | Role                                                                                                              |
| ------------------------ | ----------------------------------------------------------------------------------------------------------------- |
| `@isis/comfyui-sdk`      | WebSocket ComfyUI SDK                                                                                             |
| `@isis/comfyui-factory`  | Workflow-class authoring, template diff, portability check, rehearsal harness                                     |
| `comfyui-nodes`          | Python ComfyUI custom-node package (sacred-geometry, spiritual-styles, vfx-post, consciousness, lilith node sets) |
| `@isis/3d-comfyui-nodes` | 3D-specific ComfyUI node definitions                                                                              |
| `@isis/workflow-classes` | Living-scene workflow-class catalogs (tara, nyx, veritas, …)                                                      |

### Image, video, and audio

| Package                    | Role                                                               |
| -------------------------- | ------------------------------------------------------------------ |
| `@isis/ai-video`           | Video generation (providers, advanced, self-hosted)                |
| `@isis/video-enhancement`  | AI video enhancement/restoration (super-resolution, interpolation) |
| `@isis/video-to-mesh`      | 3D-geometry extraction from video footage                          |
| `@isis/audio-generation`   | Audio/TTS/voice generation and QA                                  |
| `@isis/music-generation`   | Music generation: provider, guardrails, stems, provenance          |
| `@isis/voice-cloning`      | Voice-cloning and synthesis orchestration                          |
| `@isis/visual-dubbing`     | Visual dubbing and dialogue-editing orchestration                  |
| `@isis/face-synthesis`     | Face synthesis, de-aging, identity-transfer orchestration          |
| `@isis/seedance-provider`  | Seedance video-generation provider integration                     |
| `@isis/post-production-ai` | Per-production post-production intelligence for cinematic dailies  |
| `@isis/ai-texturing`       | AI texture upscaling, seamless tiling, material-ID extraction      |

### 3D generation

| Package                           | Role                                                                                   |
| --------------------------------- | -------------------------------------------------------------------------------------- |
| `@isis/3d-generation`             | Multi-provider 3D generation (Rodin, Meshy, Tripo, Trellis, Hunyuan, ThreeDFY, Marble) |
| `@isis/3d-generation-benchmarks`  | Cross-provider 3D quality/throughput benchmarking                                      |
| `@isis/3d-inference-local`        | Self-hosted 3D model serving                                                           |
| `@isis/3d-post-pipeline`          | Mesh optimization, UV unwrapping, LOD generation, texture baking                       |
| `@isis/3d-quality-gates`          | Topology, UV-coverage, rig, LOD-chain validation                                       |
| `@isis/3d-semantic-editing`       | Text-guided semantic editing of 3D models                                              |
| `@isis/3d-asset-library`          | 3D-asset browsing and management                                                       |
| `@isis/3d-browser`                | In-browser 3D model preview and interaction                                            |
| `@isis/3d-scene-assembly`         | 3D scene-assembly modules                                                              |
| `@isis/3d-marketplace-ops`        | 3D-marketplace operations modules                                                      |
| `@isis/3d-product-parity`         | 3D product-parity modules                                                              |
| `@isis/three-d-pipelines`         | 3D pipeline-class, provider, topology, provenance contracts                            |
| `@isis/universal-rigging`         | Automated skeletal rigging, skin weights, animation retargeting                        |
| `@isis/gaussian-splatting`        | NeRF/Gaussian-splatting reconstruction, mesh extraction                                |
| `@isis/scene-from-image-composer` | End-to-end scene composition from a single image                                       |
| `@isis/model-governance-3d`       | 3D model license tracking and compliance                                               |

### Models, quality, and operations

| Package                       | Role                                                                      |
| ----------------------------- | ------------------------------------------------------------------------- |
| `@isis/model-fine-tuning`     | LoRA training and fine-tuning utilities                                   |
| `@isis/lora-training-surface` | LoRA training-run, model-merging, quality-view, lineage-tree surface      |
| `@isis/anomaly-detection`     | Suspicious-activity detection, chargeback prediction, account protection  |
| `@isis/curated-cards`         | Curated-card types, validators, preflight, entitlement gate               |
| `@isis/entitlements`          | Generation-tier and studio-boundary entitlements                          |
| `@isis/output-gallery`        | Output-record gallery: lineage, branch-replay, bulk actions, compare-grid |
| `@isis/runpod-surface`        | RunPod endpoint registry, cost-quota, queue inspector, secret rotation    |

(`@oshun/web` host: `apps/isis/web`, package `@isis/web` — front-end app.)

---

## Validation Rules

All write paths use Zod (`@hono/zod-validator` on the REST routes). The
following table records the constraints that are most likely to affect callers
integrating with the API:

| Field / object                    | Rule                                                                 |
| --------------------------------- | -------------------------------------------------------------------- |
| `JobSubmitRequest.type`           | Coerced via `normalizeIsisGenerationType` (accepts aliases)          |
| `JobSubmitRequest.prompt`         | Optional string, max 2000 chars                                      |
| `JobSubmitRequest.negativePrompt` | Optional string, max 1000 chars                                      |
| `JobSubmitRequest.inputUrl`       | Optional, must be a valid URL                                        |
| `JobSubmitRequest.callbackUrl`    | Optional, must be a valid URL                                        |
| `JobSubmitRequest.priority`       | `low\|normal\|high\|urgent`, default `normal`                        |
| `JobSubmitRequest.idempotencyKey` | Optional, non-empty, max 128 chars                                   |
| `JobParameters.width` / `height`  | Integer, 64–4096                                                     |
| `JobParameters.steps`             | Integer, 1–150                                                       |
| `JobParameters.guidanceScale`     | Number, 0–30                                                         |
| `JobBatchSubmitRequest.jobs`      | Array, 1–100 entries                                                 |
| `IsisJobEnvelope`                 | `.strict()` — rejects unknown top-level keys                         |
| `IsisJobEnvelope.jobId`           | Must be a UUID                                                       |
| `IsisJobEnvelopeMetadata`         | `userId`/`projectId`/`correlationId` typed; catch-all extras allowed |

`JobParametersSchema` is `.passthrough()` and accepts both camelCase and
snake_case aliases (`controlnet`/`controlNet`, `control_blend`/`controlBlend`,
etc.) so callers and ComfyUI graphs interoperate. `JobConsistencyStrengthSchema`
is `low\|medium\|high\|strict`.

---

## Configuration and Environment Variables

All Isis services are configured purely through environment variables. No
configuration files are read at runtime. The variables below are organized by
the service or subsystem that reads them.

### Database and infrastructure

```bash
ISIS_DATABASE_URL=postgresql://oshun:oshun_dev@localhost:5432/isis
REDIS_URL=redis://localhost:6379
```

### Generation API

```bash
PORT=3000                         # Listen port (default 3000)
BASE_URL=http://localhost:3000    # Public base URL
JWT_SECRET=<secret>               # Required in production — service refuses to boot without it
JWT_ISSUER=oshun                  # JWT issuer (default 'oshun')
JWT_AUDIENCE=oshun-generation-api # JWT audience
CORS_ORIGINS=                     # Comma-separated allowed origins
NODE_ENV=development|production
```

### Queue producer

```bash
ISIS_QUEUE_NAME=...                       # Queue name
ISIS_QUEUE_PREFIX=...                     # BullMQ key prefix
ISIS_QUEUE_JOB_NAME=...                   # Job name on the queue
ISIS_QUEUE_REDIS_URL=...                  # Queue Redis URL (defaults to REDIS_URL)
ISIS_QUEUE_DEFAULT_ATTEMPTS=...           # Default retry attempts
ISIS_QUEUE_DEFAULT_BACKOFF_MS=...         # Default backoff
ISIS_QUEUE_PRODUCER_ENABLED=true          # Master dispatch switch
ISIS_QUEUE_PRODUCER_CANARY_ENABLED=false  # Canary-mode switch
ISIS_QUEUE_PRODUCER_CANARY_PERCENTAGE=0   # Percent of traffic to the new queue
ISIS_QUEUE_PRODUCER_CANARY_PROJECT_IDS=   # Comma-separated project allowlist
```

When `ISIS_QUEUE_PRODUCER_ENABLED` is true the app calls
`validateQueueProducerEnvRequirements()` at boot and fails fast if queue
connection config is missing.

### Event publisher

```bash
ISIS_EVENTS_ENABLED=true   # Set 'false' to disable cross-domain event publishing
```

### GPU worker

```bash
GPU_DEVICES=0,1                       # Comma-separated CUDA device indices
QUEUE_NAME=...                        # Redis queue to poll
WORKER_ID=...                         # Unique worker identifier (registered in GpuWorker)
WORKER_TYPE=general                   # Worker-type enum value
WORK_DIR=/tmp/isis-work               # Temporary working directory
MODEL_CACHE_DIR=/models/cache         # Model-checkpoint cache
LOG_LEVEL=info
ISIS_ALLOW_SIMULATED_EXECUTION=...    # Test/dev gate; real execution required in production
BLENDER_BIN=...                       # Blender executable path
GAUSSIAN_SPLATTING_PATH=...           # Operator-supplied 3DGS train.py (@isis/gaussian-splatting);
                                      # Isis bundles no trainer, see tracker T.01.10
MESH_PIPELINE_PYTHON_BIN / MESH_PIPELINE_SCRIPT_PATH
TEXTURE_UPSCALE_PYTHON_BIN / TEXTURE_UPSCALE_SCRIPT_PATH
AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY / AWS_REGION / AWS_DEFAULT_REGION
```

The GPU worker reads S3-style credentials from the standard `AWS_*` environment
variables for output upload.

### AI provider credentials

Provider API keys are read by `@isis/ai-providers` adapters; configure the keys
for whichever providers are enabled (Anthropic, OpenAI, Google AI, xAI,
ElevenLabs, Stability AI, Black Forest Labs, Civitai, RunPod, etc.).

---

## Operational Tooling

`scripts/isis/` contains the operational toolchain. Canary and release scripts
referenced by the architecture doc all exist here:

| Script                            | Purpose                                        |
| --------------------------------- | ---------------------------------------------- |
| `validate_compose_app_paths.sh`   | Validate Docker Compose path wiring            |
| `smoke_compose_health.sh`         | `/health` + `/ready` smoke checks              |
| `verify_canary_slo_cost.sh`       | Verify SLO/cost release gate from job history  |
| `advance_queue_canary_rollout.sh` | Advance the queue canary (promote/rollback)    |
| `run_release_gameday.sh`          | Pre-cutover game-day harness                   |
| `run_post_cutover_validation.sh`  | Post-cutover validation with sign-off evidence |

RunPod-specific tooling also lives in `scripts/isis/`:

- `apply_runpod_warm_cold_policy.mjs` — apply warm/cold tier policies to RunPod
  endpoints
- `detect_runpod_endpoint_drift.py` — detect configuration drift between
  registered and live RunPod endpoints
- `evaluate-runpod-release-gate.mjs` — evaluate whether a RunPod endpoint change
  meets release criteria
- `execute_runpod_endpoint_canary_strategy.sh` — execute the canary rollout
  strategy for RunPod endpoint changes

`check-generation-type-enum-drift.mjs` detects mismatches between the
`ISIS_GENERATION_TYPES` constant in `@isis/job-envelope` and the Prisma
`GenerationType` enum — this must be run whenever a new generation type is
added.

SLO definitions are in `docs/domains/isis/remediation/ISIS_SLO_DEFINITIONS.json`
and `.../remediation-v2/`.

---

## Architecture Decision Records

Five ADRs under `docs/domains/isis/adr/` document the key architectural choices
made during Isis's design:

| ADR      | Decision                                                   |
| -------- | ---------------------------------------------------------- |
| ADR-0001 | Queueing model and job-envelope contract                   |
| ADR-0002 | Workflow-schema canonicalization and version compatibility |
| ADR-0003 | RunPod serverless execution strategy                       |
| ADR-0004 | RunPod endpoint provisioning mechanism                     |
| ADR-0005 | API contract parity and SDK deprecation policy             |

ADR-0023, referenced by the `CanonicalAuditEvent` model comment, is a
platform-wide ADR defining the canonical audit-event envelope. It is not an
Isis-local ADR.

---

## Acceptance Criteria

A change to Isis is acceptance-complete when all of the following conditions are
satisfied:

1. **Schema integrity** — `npx prisma validate` passes against
   `libs/isis/database/prisma/schema.prisma`; any new model/enum is reflected in
   the generated client and in this document.
2. **Envelope compatibility** — Any new generation type is added to
   `ISIS_GENERATION_TYPES`, `ISIS_GENERATION_TYPE_MANIFEST`, and the database
   `GenerationType` enum together; `check-generation-type-enum-drift.mjs`
   reports no drift.
3. **Event-contract parity** — New events are defined in `@oshun/contracts`
   (`IsisEventTypes` + payload schema) before any publisher method is added; the
   event-publisher cross-service contract specs pass.
4. **API validation** — Every new route has a Zod request schema wired through
   `@hono/zod-validator`; the OpenAPI contract spec
   (`generation-api/src/openapi.contract.spec.ts`) passes.
5. **Health endpoints** — `/health` and `/ready` remain unauthenticated and
   `/ready` continues to reflect real dependency state (DB, queue, storage,
   provider).
6. **Tests** — Unit and integration tests pass under Vitest, including the
   route-parity and schema-compatibility contract specs.
7. **No simulated execution in production** — `gpu-worker` execution paths must
   not be gated to simulated runtimes when `NODE_ENV=production`.
