# Artifact Generation ## Overview Every deployment generates immutable artifacts that enable reproducibility, audit, and rollback. ## Generated Artifacts ### 1. Compose Lock File **File:** `compose.stella.lock.yml` A Docker Compose file with all image references pinned to specific digests. ```yaml # compose.stella.lock.yml # Generated by Stella Ops - DO NOT EDIT # Release: myapp-v2.3.1 # Generated: 2026-01-10T14:30:00Z # Generator: stella-artifact-generator@1.5.0 version: "3.8" services: api: image: registry.example.com/myapp/api@sha256:abc123... # Original tag: v2.3.1 deploy: replicas: 2 environment: - DATABASE_URL=${DATABASE_URL} - REDIS_URL=${REDIS_URL} labels: stella.component.id: "comp-api-uuid" stella.release.id: "rel-uuid" stella.digest: "sha256:abc123..." worker: image: registry.example.com/myapp/worker@sha256:def456... # Original tag: v2.3.1 deploy: replicas: 1 labels: stella.component.id: "comp-worker-uuid" stella.release.id: "rel-uuid" stella.digest: "sha256:def456..." # Stella metadata x-stella: release: id: "rel-uuid" name: "myapp-v2.3.1" created_at: "2026-01-10T14:00:00Z" environment: id: "env-uuid" name: "production" deployment: id: "deploy-uuid" started_at: "2026-01-10T14:30:00Z" checksums: sha256: "checksum-of-this-file" ``` ### 2. Version Sticker **File:** `stella.version.json` Metadata file placed on deployment targets indicating current deployment state. ```json { "version": "1.0", "generatedAt": "2026-01-10T14:35:00Z", "generator": "stella-artifact-generator@1.5.0", "release": { "id": "rel-uuid", "name": "myapp-v2.3.1", "createdAt": "2026-01-10T14:00:00Z", "components": [ { "name": "api", "digest": "sha256:abc123...", "semver": "2.3.1", "tag": "v2.3.1" }, { "name": "worker", "digest": "sha256:def456...", "semver": "2.3.1", "tag": "v2.3.1" } ] }, "deployment": { "id": "deploy-uuid", "promotionId": "promo-uuid", "environmentId": "env-uuid", "environmentName": "production", "targetId": "target-uuid", "targetName": "prod-web-01", "strategy": "rolling", "startedAt": "2026-01-10T14:30:00Z", "completedAt": "2026-01-10T14:35:00Z" }, "deployer": { "userId": "user-uuid", "userName": "john.doe", "agentId": "agent-uuid", "agentName": "prod-agent-01" }, "previous": { "releaseId": "prev-rel-uuid", "releaseName": "myapp-v2.3.0", "digest": "sha256:789..." }, "signature": "base64-encoded-signature", "signatureAlgorithm": "RS256", "signerKeyRef": "stella/signing/prod-key-2026" } ``` ### 3. Evidence Packet **File:** Evidence stored in database (exportable as JSON/PDF) See [Evidence Schema](../appendices/evidence-schema.md) for full specification. ### 4. Deployment Script (Optional) **File:** `deploy.stella.script.dll` or `deploy.stella.sh` When deployments use C# or shell scripts with hooks: ```csharp // deploy.stella.csx (source, compiled to DLL) #r "nuget: StellaOps.Sdk, 1.0.0" using StellaOps.Sdk; // Pre-deploy hook await Context.RunPreDeployHook(async (ctx) => { await ctx.ExecuteCommand("./scripts/backup-database.sh"); await ctx.HealthCheck("/ready", timeout: 30); }); // Deploy await Context.Deploy(); // Post-deploy hook await Context.RunPostDeployHook(async (ctx) => { await ctx.ExecuteCommand("./scripts/warm-cache.sh"); await ctx.Notify("slack", "Deployment complete"); }); ``` ## Artifact Storage ### Storage Structure ``` artifacts/ ├── {tenant_id}/ │ ├── {deployment_id}/ │ │ ├── compose.stella.lock.yml │ │ ├── deploy.stella.script.dll (if applicable) │ │ ├── deploy.stella.script.csx (source) │ │ ├── manifest.json │ │ └── checksums.sha256 │ └── ... └── ... ``` ### Manifest File ```json { "version": "1.0", "deploymentId": "deploy-uuid", "createdAt": "2026-01-10T14:30:00Z", "artifacts": [ { "name": "compose.stella.lock.yml", "type": "compose-lock", "size": 2048, "sha256": "abc123..." }, { "name": "deploy.stella.script.dll", "type": "script-compiled", "size": 8192, "sha256": "def456..." } ], "totalSize": 10240, "signature": "base64-signature" } ``` ## Artifact Generation Process ``` ┌─────────────────────────────────────────────────────────────────────────────┐ │ ARTIFACT GENERATION FLOW │ │ │ │ ┌─────────────────┐ │ │ │ Promotion │ │ │ │ Approved │ │ │ └────────┬────────┘ │ │ │ │ │ ▼ │ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │ │ ARTIFACT GENERATOR │ │ │ │ │ │ │ │ 1. Load release bundle (components, digests) │ │ │ │ 2. Load environment configuration (variables, secrets refs) │ │ │ │ 3. Load workflow template (hooks, scripts) │ │ │ │ 4. Generate compose.stella.lock.yml │ │ │ │ 5. Compile scripts (if any) │ │ │ │ 6. Generate version sticker template │ │ │ │ 7. Compute checksums │ │ │ │ 8. Sign artifacts │ │ │ │ 9. Store in artifact storage │ │ │ │ │ │ │ └────────────────────────────┬────────────────────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │ │ DEPLOYMENT ORCHESTRATOR │ │ │ │ │ │ │ │ Artifacts distributed to targets via agents │ │ │ └─────────────────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────────────┘ ``` ## Artifact Properties ### Immutability Once generated, artifacts are never modified: - Content-addressed storage (hash in path/metadata) - No overwrite capability - Append-only storage pattern ### Integrity All artifacts are: - Checksummed (SHA-256) - Signed with deployment key - Verifiable at deployment time ### Retention | Environment | Retention Period | |-------------|------------------| | Development | 30 days | | Staging | 90 days | | Production | 7 years (compliance) | ## API Operations ```yaml # List artifacts for deployment GET /api/v1/deployment-jobs/{id}/artifacts Response: Artifact[] # Download specific artifact GET /api/v1/deployment-jobs/{id}/artifacts/{name} Response: binary # Get artifact manifest GET /api/v1/deployment-jobs/{id}/artifacts/manifest Response: ArtifactManifest # Verify artifact integrity POST /api/v1/deployment-jobs/{id}/artifacts/{name}/verify Response: { valid: boolean, checksum: string, signature: string } ``` ## Drift Detection Version stickers enable drift detection: ```typescript interface DriftCheck { targetId: UUID; expectedSticker: VersionSticker; actualSticker: VersionSticker | null; driftDetected: boolean; driftType?: "missing" | "corrupted" | "mismatch"; details?: { expectedDigest: string; actualDigest: string; field: string; }; } ``` ## References - [Deployment Overview](overview.md) - [Deployment Strategies](strategies.md) - [Evidence Schema](../appendices/evidence-schema.md)