Release & Operations Architecture — Stella Ops Suite (2025 Q4)
Audience: release engineers, platform operators, and architects.
Draws from the AOC guardrails, Orchestrator, Export Center, and Observability module plans to describe how Stella Ops is built, signed, distributed, and operated.
Scope. Implementation‑ready blueprint for how Stella Ops is built, versioned, signed, distributed, upgraded, licensed (PoE), and operated in customer environments (online and air‑gapped). Covers reproducible builds, supply‑chain attestations, registries, offline kits, migration/rollback, artifact lifecycle (RustFS default + PostgreSQL, S3 fallback), monitoring SLOs, and customer activation.
Deployment scope. Kubernetes and Helm are explicitly unsupported. Stella Ops release operations target Docker Compose, Offline Kit, and signed release manifests for non-Kubernetes container estates.
0) Product vision (operations lens)
Stella Ops must be trustable at a glance and boringly operable:
- Every release ships with first‑party SBOMs, provenance, and signatures; services verify each other’s integrity at runtime.
- Customers can deploy by digest and stay aligned with LTS/stable/edge channels.
- Paid customers receive attestation authority (Signer accepts their PoE) while the core platform remains free to run.
- Air‑gapped customers receive offline kits with verifiable digests and deterministic import.
- Artifacts expire predictably; operators know what’s kept, for how long, and why.
1) Release trains & versioning
1.1 Channels
- LTS (12‑month support window): quarterly cadence (Q1/Q2/Q3/Q4).
- Stable (default): monthly rollup (bug fixes + compatible features).
- Edge: weekly; for early adopters, no guarantees.
Reality check (flagged). The release tooling recognises the channels
stable,airgap, andedge(produce_image_digests.pydefaults to("stable", "airgap");components.jsonsetsdefaultChannel: "edge"). There is noltschannel in the tooling today, andairgapis a first-class channel not listed above. The default channel in tooling isedge, whereas this section namesstableas the default. Reconcile the channel taxonomy withdevops/release/before relying on the list above.
1.2 Version strings
Semantic core + calendar tag:
<MAJOR>.<MINOR>.<PATCH> (<YYYY>.<MM>) e.g., 2.4.1 (2027.06)
- MAJOR: breaking API/DB changes (rare).
- MINOR: new features, compatible schema migrations (expand/contract pattern).
- PATCH: bug fixes, perf and security updates.
- Calendar tag exposes release year used by Signer for PoE window checks.
Divergence (flagged). The semver-plus-calendar scheme above is the stated policy, but the release manifests actually checked into
devops/releases/use a calendar-versionedversionstring directly — e.g.version: "2025.09.2"withcalendar: "2025.09"(and2025.09.2-airgapfor the air-gap channel). There is no separate2.4.1-style semver field on disk. Reconcile this section with the product owner before treating theMAJOR.MINOR.PATCHform as authoritative.
1.3 Component alignment
A release is a bundle of image digests, Compose assets, offline-kit metadata, and manifests. All services in a bundle are wire‑compatible. Mixed minor versions are allowed within a bounded skew:
- Web UI ↔ backend:
±1 minor. - Scanner ↔ Policy/Excititor/Concelier:
±1 minor. - Authority/Signer/Attestor triangle: must be same minor (crypto and DPoP/mTLS binding rules).
At startup, services self‑advertise their semver & channel; the UI surfaces mismatch warnings.
2) Supply‑chain pipeline (how a release is built)
2.1 Deterministic builds
- Builders: isolated BuildKit workers with pinned base images (digest only).
- Pinning: lock files or
go.mod,package-lock.json,global.json,Directory.Packages.propsare frozen at tag. - Reproducibility: timestamps normalized; source date epoch; deterministic zips/tars.
- Multi‑arch: linux/amd64 + linux/arm64 (Windows images track M2 roadmap).
2.2 First‑party SBOMs & provenance
- Each image gets CycloneDX (JSON+Protobuf) SBOM and SLSA‑style provenance attached as OCI referrers.
- Scanner’s Buildx generator is used to produce SBOMs during build; a separate post‑build scan verifies parity (red flag if drift).
- Release manifest (see §6.1) lists all digests and SBOM/attestation refs.
2.3 Signing & transparency
- Images are cosign‑signed (keyless) with a Stella Ops release identity; inclusion in a transparency log (Rekor) is required.
- SBOM and provenance attestations are DSSE and also transparency‑logged.
- Release keys (Fulcio roots or public keys) are embedded in Signer policy (for scanner‑release validation at customer side).
2.4 Gates & tests
- Static: linters, codegen checks, protobuf API freeze (backward‑compat tests).
- Unit/integration: per-component, plus end-to-end flows (scan→vex→policy→sign→attest).
- Perf SLOs: hot paths (SBOM compose, diff, export) measured against budgets.
- Security: dependency audit vs Concelier export; container hardening tests; minimal caps.
- Deployment assets: profile validation covers Compose and Offline Kit packaging only. Helm charts and Kubernetes manifests are not release artifacts.
- Analyzer smoke: restart-time language plug-ins (currently Python) verified via
dotnet run --project src/Tools/LanguageAnalyzerSmoketo ensure manifest integrity plus cold vs warm determinism (< 30 s / < 5 s budgets); the harness logs deviations from repository goldens for follow-up. - Canary cohort: internal staging + selected customers; one week on edge before stable tag.
2.5 Debug-store artefacts
- Every release exports stripped debug information for ELF binaries discovered in service images. Debug files follow the GNU build-id layout (
debug/.build-id/<aa>/<rest>.debug) and are generated viaobjcopy --only-keep-debug. debug/debug-manifest.jsoncaptures build-id → component/image/source mappings with SHA-256 checksums so operators can mirror the directory into debuginfod or offline symbol stores. The manifest (and its.sha256companion) ships with every release bundle and Offline Kit.
3) Distribution & activation
3.1 Registries
- Primary:
registry.stella-ops.org(OCI v2, supports Referrers API). - Mirrors: GHCR (read‑only), regional mirrors for latency.
- Operational runbook: see
docs/modules/concelier/operations/mirror.mdfor deployment profiles, CDN guidance, and sync automation.
- Operational runbook: see
- Pull by digest only in Compose profiles and Offline Kit manifests.
Gating policy:
- Core images (Authority, Scanner, Concelier, Excititor, Attestor, UI): public read.
- Enterprise add‑ons (if any) and pre‑release: private repos via the Registry Token Service (
src/Registry/StellaOps.Registry.TokenService) which exchanges Authority-issued OpToks for short-lived Docker registry bearer tokens.
Monetization lever is signing (PoE gate), not image pulls, so the core remains simple to consume.
3.2 OAuth2 token service (for private repos)
Docker Registry’s token flow backed by Authority:
- Client hits registry (
401withWWW-Authenticate: Bearer realm=…). - Client gets an access token from the token service (validated by Authority) with
scope=repository:…:pull. - Registry allows pull for the requested repo.
- Client hits registry (
Tokens are short‑lived (60–300 s) — guideline only; the actual lifetime is configurable via
Signing.Lifetime, not a hard-coded bound (seeRegistryTokenIssuer.cs).
Flagged (unsubstantiated). Earlier drafts described these registry tokens as DPoP‑bound, but
StellaOps.Registry.TokenServiceshows no DPoP /cnf/jktproof-of-possession binding — the issued JWT is a short-lived bearer token scoped torepository:…:pull. Either DPoP binding is not yet implemented for registry tokens (roadmap) or it lives elsewhere; verify before presenting DPoP as a current registry-token control.
The token service enforces plan gating via registry-token.yaml (see docs/modules/registry/operations/token-service.md) and exposes Prometheus metrics (registry_token_issued_total, registry_token_rejected_total). Revoked licence identifiers halt issuance even when scope requirements are met.
3.3 Offline kits (air‑gapped)
Tarball per release channel:
stellaops-kit-<ver>-<channel>.tar.zst /images/ OCI layout with all first-party images (multi-arch) /sboms/ CycloneDX JSON+PB for each image /attest/ DSSE bundles + Rekor proofs /compose/ docker-compose.yml + .env template /plugins/ Concelier/Excititor connectors (restart-time) /policy/ example policies /manifest/ release.yaml (see §6.1)Import via CLI
stellaops offline import --bundle <kit>.tar.zst; DSSE and Rekor verification are on by default (--verify-dsse/--verify-rekor, both default true), with--trust-root,--dry-run, and--force-activatemodifiers. Usestellaops offline statusto inspect the active kit. (The command isoffline import, notoffline kit import— there is no intermediatekitsubcommand; seesrc/Cli/StellaOps.Cli/Commands/OfflineCommandGroup.cs.)
4) Licensing (PoE) & monetization
Principle: Only paid Stella Ops issues valid signed attestations. Running the stack is free; signing requires PoE.
4.1 PoE issuance
Customers purchase a plan and obtain a PoE artifact from
www.stella-ops.org:- PoE‑JWT (DPoP/mTLS‑bound) or PoE mTLS client certificate.
- Contains:
license_id,plan,valid_release_year,max_version,exp, optionaltenant/customerIDs.
4.2 Online enforcement
- Signer introspects a proof-of-entitlement (PoE) before signing (see
IProofOfEntitlementIntrospectorinsrc/Attestor/StellaOps.Signer/StellaOps.Signer.Coreand theConfiguredProofOfEntitlementIntrospectorimplementation under…/StellaOps.Signer.Infrastructure/ProofOfEntitlement/). Implementation note: the shipped introspector resolves the entitlement definition (LicenseId, plan window, etc.) from configuration/environment, not from a live HTTP call to awww.stella-ops.org /license/introspectendpoint on every request. The hosted-introspection flow described here is the intended online model; the current code path is the configured/offline-capable variant. Note also that Signer is consolidated under Attestor — there is nosrc/Signer/top-level module; the project lives atsrc/Attestor/StellaOps.Signer/. - If revoked/expired/out‑of‑window → deny with machine‑readable reason.
- All valid bundles are DSSE‑signed and Attestor logs them; Rekor UUID returned.
- UI badges: “Verified by Stella Ops” with link to the public log.
4.3 Air‑gapped / offline
- Customers obtain a time‑boxed PoE lease (signed JSON, 7–30 days).
- Signer accepts the lease and emits provisional attestations (clearly labeled).
- When connectivity returns, a background job endorses the provisional entries with the cloud service, updating their status to verified.
- Operators can export a verification bundle for auditors even before endorsement (contains DSSE + local Rekor proof + lease snapshot).
4.4 Stolen/abused PoE
- Customers report theft; Licensing flags
license_idas revoked. - Subsequent Signer requests deny; previous attestations remain but can be marked contested (UI shows badge, optional re‑sign path upon new PoE).
5) Deployment path (customer side)
5.1 First install
Stella Ops first install is Compose or Offline Kit based. Kubernetes and Helm are not supported deployment targets.
The Compose entry point is devops/compose/docker-compose.stella-ops.yml, a thin wrapper that include:s docker-compose.stella-infra.yml (Postgres, Valkey, RustFS, zot registry, Rekor) and docker-compose.stella-services.yml (the application services). Generate local environment values, then bring the stack up:
cd devops/compose
./scripts/init-local-env.sh
docker compose --env-file .env -f docker-compose.stella-ops.yml up -d
Note. Earlier drafts of this blueprint referenced
devops/compose/env/prod.envanddevops/compose/docker-compose.prod.yaml. Neither exists; local dev usesdevops/compose/env/stellaops.env.local-dev.examplethroughscripts/init-local-env.*; operator/release installs usedevops/compose/env/stellaops.env.example. The canonical Compose file isdocker-compose.stella-ops.yml. Overlays such asdocker-compose.telemetry.yml,docker-compose.dev-ui.yml,docker-compose.blue-green.yml, and thedocker-compose.compliance-*.ymlprofiles layer on top with additional-fflags.
Offline environments import the signed Offline Kit first, then apply the included Compose profile and release manifest. Post-install registration still creates Authority clients for Scanner, Signer, Attestor, and UI, and the UI banner shows the release bundle and verification state.
5.2 Updates
Blue/green: pull new bundle by digest; deploy side‑by‑side; cut traffic.
Rolling: upgrade stateful components in safe order:
- Authority (stateless, dual‑key rotation ready)
- Signer/Attestor (same minor)
- Scanner WebService & Workers
- Concelier, then Excititor (schema migrations are expand/contract)
- UI last
DB migrations are expand/contract:
- Phase A (release N): add new fields/indexes, write old+new.
- Phase B (N+1): read new fields; drop old.
- Rollback is a matter of redeploying previous images and keeping both schemas valid.
Reconcile with ADR-004 (flagged). The platform migration policy is now forward-only (see
docs/architecture/decisions/ADR-004-forward-only-migrations.md, Accepted 2026-05-18, and the migration-recovery runbook). Under forward-only, a true schema downgrade is not performed by redeploying prior images; downgrades are recovered by PostgreSQL snapshot restore. Services auto-migrate their own schema on startup (CLAUDE.md §2.7), so the “keep both schemas valid and roll back images” model above only holds for the brief expand window — past Phase B (drop) it does not. Treat snapshot restore as the authoritative downgrade path.
5.3 Rollback
- Images referenced by digest; keep previous release manifest
Kversions back. docker compose -f release-K.yml up -d.- PostgreSQL migrations are additive; no destructive changes within a single minor.
6) Release payloads & manifests
6.1 Release manifest (release.yaml)
The released-manifest schema as actually emitted and validated lives under devops/releases/ (e.g. 2025.09-stable.yaml, 2025.09-airgap.yaml). Each manifest carries a components: list (name + digest-pinned image), an infrastructure: block (the postgres, valkey, and rustfs images), and a single checksums.releaseManifestSha256:
release:
version: "2025.09.2"
channel: "stable"
date: "2025-09-20T00:00:00Z"
calendar: "2025.09"
components:
- name: authority
image: registry.stella-ops.org/stellaops/authority@sha256:b0348bad…
- name: signer
image: registry.stella-ops.org/stellaops/signer@sha256:8ad574e6…
- name: scanner-web
image: registry.stella-ops.org/stellaops/scanner-web@sha256:14b23448…
# … attestor, scanner-worker, concelier, excititor, notify-web,
# advisory-ai-web, advisory-ai-worker, web-ui …
infrastructure:
postgres:
image: docker.io/library/postgres@sha256:8e97b852…
valkey:
image: docker.io/valkey/valkey@sha256:9a2cf7c9…
rustfs:
image: registry.stella-ops.org/stellaops/rustfs:2025.09.2
checksums:
releaseManifestSha256: dc3c8fe1ab83941c838ccc5a8a5862f7ddfa38c2078e580b5649db26554565b7
PARTIALLY IMPLEMENTED (forward-looking shape). The richer per-component manifest envisioned by this blueprint — embedding
sbom:/provenance:OCI referrer URIs, per-componentsignature: { rekorUUID }, and a top-levelcompose:/charts:block — is not populated in any of the manifests underdevops/releases/(2025.09-stable,2025.09-airgap,2025.10-edge,2025.09-mock-dev). Those manifests carry onlyname+ digest-pinnedimageper component. SBOM, provenance, and transparency-log entries are attached to images as OCI referrers (§2.2–2.3) and tracked outsiderelease.yaml. The format is forward-compatible: the Offline Kit builder (devops/offline/kit/build_offline_kit.py) does read and stage per-componentsbom/provenanceentries andcharts/composecollections when present, and the validator (devops/release/check_release_manifest.py) toleratescharts:/compose:section headers. But nothing currently emits them — treat the SBOM/provenance/signature manifest fields above as roadmap, not current contract.
The manifest is intended to be cosign‑signed so UI/CLI can verify a bundle without talking to registries.
Deployment guardrails - The repository keeps channel-aligned release manifests in
devops/releases/and Compose bundles indevops/compose/. Helm overlays and Kubernetes manifests are not active release assets. Release engineering still runsdevops/release/check_release_manifest.py, which fails if any required component or infrastructure image is missing from the local release manifest or is still tag-only (not@sha256:-pinned). Required components areauthority,signer,attestor,scanner-web,scanner-worker,concelier,excititor,notify-web,advisory-ai-web,advisory-ai-worker,web-ui; required infrastructure ispostgres,valkey,rustfs. The digest producer/patcher path (devops/release/produce_image_digests.py,apply_image_digests.py) remains useful for non-Kubernetes packaging because it builds local, digest-pinned release-manifest authority without resolving mutable tags.
Flagged (sample manifests do not pass the validator). The
REQUIRED_COMPONENTSlist above is transcribed accurately fromcheck_release_manifest.py, but the sample manifests checked intodevops/releases/would fail that validator today:2025.09-stable.yamland2025.09-airgap.yamlomitnotify-webfrom theircomponents:lists entirely, and they pinadvisory-ai-web/advisory-ai-workerby tag (:2025.09.2,:2025.09.2-airgap) rather than@sha256:. Both conditions are hard failures incheck_manifest()(“missing required component” / “not digest-pinned”).2025.10-edge.yamladditionally carries an extraissuer-directory-webcomponent not in the required set (extra components are tolerated). Treat the committed manifests as illustrative fixtures, not validator-clean release authority; a real release run must addnotify-weband digest-pin the advisory-ai images. Reconcile with release engineering before citing these files as canonical.
6.2 Image labels (release metadata)
Each image sets OCI labels:
org.opencontainers.image.version = "2.4.1"
org.opencontainers.image.revision = "<git sha>"
org.opencontainers.image.created = "2027-06-20T12:00:00Z"
org.stellaops.release.calendar = "2027.06"
org.stellaops.release.channel = "stable"
org.stellaops.build.slsaProvenance = "oci://…"
Signer validates scanner image’s cosign identity + calendar tag for release window checks.
7) Artifact lifecycle & storage (RustFS/PostgreSQL)
7.1 Buckets & prefixes (RustFS)
rustfs://stellaops/
scanner/
layers/<sha256>/sbom.cdx.json.zst
images/<imgDigest>/inventory.cdx.pb
images/<imgDigest>/usage.cdx.pb
diffs/<old>_<new>/diff.json.zst
attest/<artifactSha256>.dsse.json
concelier/
json/<exportId>/...
trivy/<exportId>/...
excititor/
exports/<exportId>/...
attestor/
dsse/<bundleSha256>.json
proof/<rekorUuid>.json
7.2 ILM classes
short: working artifacts (diffs, queues) — TTL 7–14 days.default: SBOMs & indexes — TTL 90–180 days (configurable).compliance: signed reports & attested exports — retention enforced via RustFS hold or S3 Object Lock (governance/compliance) 1–7 years.
7.3 Artifact Lifecycle Controller (ALC)
A background worker (part of Scanner.WebService) enforces TTL and reference counting:
- Artifacts referenced by reports or tickets are pinned.
- ILM actions logged; UI shows per‑class usage & upcoming purges.
Migration note. Follow
docs/modules/scanner/operations/rustfs-migration.mdwhen transitioning existing MinIO buckets to RustFS. The provided migrator is idempotent and safe to rerun per prefix.
Flagged (ALC / ILM-class scheme is design-level). The named Artifact Lifecycle Controller background worker and the three ILM classes (
short/default/compliance) described in §7.2–§7.3 are a blueprint:src/Scanner/__Libraries/StellaOps.Scanner.Storage/carries artifact-storage rows, object-store adapters (S3ArtifactObjectStore), and EPSS cache retention, but there is no single component named “Artifact Lifecycle Controller” enforcing those exact TTL classes and reference-counting in the tree today. Treat the ILM-class taxonomy and per-class UI purge view as intended design, and verify againstStellaOps.Scanner.Storage/Scanner.WebServicebefore presenting them as shipped controls.
7.4 PostgreSQL retention
- Scanner:
runtime.eventsuse TTL (e.g., 30–90 days); catalog permanent. - Concelier/Excititor: raw docs keep last N windows; canonical stores permanent.
- Attestor:
entriespermanent;dedupeTTL 24–48h.
7.5 PostgreSQL server baseline
- Minimum supported server: PostgreSQL 16+. Earlier versions lack required features (e.g., enhanced JSON functions, performance improvements).
- Deploy images: Compose defaults stay on
postgres:18.1. For air-gapped installs, refresh Offline Kit bundles so the packaged PostgreSQL image matches ≥18.1. - Upgrade guard: During rollout, verify PostgreSQL major version ≥16 before applying schema migrations; automation should hard-stop if version check fails.
8) Observability & SLOs (operations)
Uptime SLO: 99.9% for Signer/Authority/Attestor; 99.5% for Scanner WebService; Excititor/Concelier 99.0%.
Error budgets: tracked per month; dashboards show burn rates.
Golden signals:
- Latency: token issuance, sign→attest round‑trip, scan enqueue→emit, export build.
- Saturation: queue depth, PostgreSQL write IOPS, RustFS throughput / queue depth (or S3 metrics when in fallback mode).
- Traffic: scans/min, attestations/min, webhook admits/min.
- Errors: 5xx rates, cosign verification failures, Rekor timeouts.
Prometheus + OTLP; Grafana dashboards ship in the monitoring bundle.
9) Security & compliance operations
Key rotation:
- Authority JWKS: 60‑day cadence, dual‑key overlap.
- Release signing identities: rotate per minor or quarterly.
- Sigstore roots mirrored and pinned; alarms on drift.
FIPS mode (Gov build):
- Enforce
ES256+ KMS/HSM; disable Ed25519; MLS ciphers only. - Local Rekor v2 and Fulcio alternatives; air‑gapped CA.
- Enforce
Vulnerability response:
- Concelier red-flag advisories trigger accelerated stable patch rollout; UI/CLI “security patch available” notice.
SharpCompressis centrally pinned to 0.38.0 insrc/Directory.Packages.props(DEVOPS-SEC-10-301) to eliminate NU1903 warnings; future bumps follow the central override pattern. (Earlier drafts cited 0.41.0; the pinned version on disk is 0.38.0 — bump the central package version, not just the prose, when this changes.)
Corrected (MongoDB not fully removed). Earlier drafts asserted “MongoDB dependencies were removed (no
MongoDB.Driverreferences remain undersrc/); all persistence now uses PostgreSQL.” That is not accurate as written.src/Directory.Packages.propsstill declaresMongoDB.Driver(3.3.0) andMongoDB.Bson, and an active library —src/Workflow/__Libraries/StellaOps.Workflow.DataStore.MongoDB/(plus its__Testsproject) — referencesMongoDB.Driverand contains live Mongo-backed stores (MongoWorkflowDatabase, projection/runtime/signal stores, etc.). The accurate statement is narrower: the platform/release services (Authority, Scanner, Concelier, Excititor, Attestor, Signer, Notify, Advisory-AI) persist to PostgreSQL (per CLAUDE.md §2.7 auto-migration), and no top-level release service in this blueprint takes a Mongo dependency — but the Workflow datastore is a MongoDB-backed exception still present in the tree. Verify againstsrc/Workflow/before repeating the blanket “no MongoDB anywhere” claim.
Backups/DR:
- PostgreSQL nightly snapshots; RustFS object-store versioning + replication (if configured). (The default object store is RustFS, backed by SeaweedFS — see the
rustfsservice indocker-compose.stella-infra.yml. MinIO appears only as a historical migration source, per §7.3.) - Restore runbooks tested quarterly with synthetic data.
- PostgreSQL nightly snapshots; RustFS object-store versioning + replication (if configured). (The default object store is RustFS, backed by SeaweedFS — see the
10) Customer update flow (how versions are fetched & activated)
10.1 Online clusters
- UI surfaces update banner with release manifest diff and risk notes.
- Operator approves → Controller pulls new images by digest; health‑checks; moves traffic; deprecates old revision.
- Post‑switch, schema Phase B migrations (if any) run automatically.
10.2 Air‑gapped clusters
- Operator downloads offline kit from a mirror →
stellaops offline import --bundle <kit>.tar.zst(command isoffline import, notoffline kit import). - The import validates bundle checksums, DSSE signatures, and Rekor receipts (both verifications default-on); apply the included Compose profile by digest.
- After install, verify page shows green checks: image sigs, SBOMs attached, provenance logged.
10.3 CLI self‑update (optional)
stellaops self update(subcommand ofstellaops self, “Manage the local Stella CLI binary”; seesrc/Cli/StellaOps.Cli/Commands/Agent/UpdateCommands.cs) checks, verifies, and applies a signed CLI update before swapping (admin can disable). The verb isself update, not the hyphenatedself-update.
11) Compatibility & deprecation policy
- APIs are stable within a major; breaking changes imply MAJOR++ and deprecation period of one minor.
- Storage: expand/contract; “drop old fields” only after one minor grace.
- Config: feature flags (default off) for risky features (e.g., eBPF).
12) Runbooks (selected)
For the full promote/upgrade/rollback procedure (digest pinning, manifest validation, migration gating, and the image-staleness self-check), see the Deployment upgrade & rollback runbook.
12.1 Lost PoE
- Suspend automatic attestation jobs.
- Confirm the entitlement-denied state from the Signer service (the PoE introspector rejects signing requests when the entitlement is revoked/expired/out-of-window). Note: there is no
stellaops signer statusCLI command — Signer has no dedicated CLI command group; check Signer service health/logs or the attestation UI instead. (Flagged: this runbook step references a CLI verb that does not exist.) - Obtain new PoE from portal; reconfigure the Signer entitlement.
- Re‑enable; optionally re‑sign last N reports (UI button → batch).
12.2 Rekor outage (self‑hosted)
- Attestor returns
202 (pending)with queued proof fetch. - Keep DSSE bundles locally; re‑submit on schedule; UI badge shows Pending.
- If outage > SLA, you can switch to a mirror log in config; Attestor writes to both when restored.
12.3 Emergency downgrade
- Identify prior release manifest (UI → Admin → Releases).
docker compose -f release-K.yml up -dusing the previous release profile.- Services tolerate skew per §1.3; ensure Signer/Authority/Attestor are rolled together.
13) Example: cluster bootstrap (Compose)
Illustrative only. This is a hand-written teaching example, not a real file from the repo. The actual stack is assembled from
docker-compose.stella-ops.yml(whichinclude:s the infra and services files — see §5.1). The top-levelversion:key shown below is obsolete in modern Docker Compose (the repo’s active Compose files omit it and Compose now warns when it is present); it is retained here only to keep the example self-contained.
version: "3.9" # obsolete in current Compose; omit in real files
services:
authority:
image: registry.stella-ops.org/stellaops/authority@sha256:...
env_file: ./env/authority.env
ports: ["8440:8440"]
signer:
image: registry.stella-ops.org/stellaops/signer@sha256:...
depends_on: [authority]
environment:
# Illustrative only. The shipped configured introspector reads the
# entitlement definition (LicenseId, plan window) from prefixed env vars
# (see ConfiguredProofOfEntitlementIntrospector); SIGNER__POE__LICENSING__INTROSPECTURL
# is NOT a recognised key. Consult the Signer module dossier for the
# current configuration surface.
- SIGNER__POE__LICENSING__INTROSPECTURL=https://www.stella-ops.org/api/v1/license/introspect
attestor:
image: registry.stella-ops.org/stellaops/attestor@sha256:...
depends_on: [signer]
scanner-web:
image: registry.stella-ops.org/stellaops/scanner-web@sha256:...
environment:
- SCANNER__ARTIFACTSTORE__ENDPOINT=http://rustfs:8080
scanner-worker:
image: registry.stella-ops.org/stellaops/scanner-worker@sha256:...
deploy: { replicas: 4 }
concelier:
image: registry.stella-ops.org/stellaops/concelier@sha256:...
excititor:
image: registry.stella-ops.org/stellaops/excititor@sha256:...
web-ui:
image: registry.stella-ops.org/stellaops/web-ui@sha256:...
postgres:
image: postgres:18.1
valkey:
image: valkey/valkey:9.0.1
rustfs:
image: registry.stella-ops.org/stellaops/rustfs@sha256:...
rekor-cli:
image: ghcr.io/sigstore/rekor-cli:v1.4.3
profiles: ["sigstore"]
cosign:
image: ghcr.io/sigstore/cosign:v3.0.4
profiles: ["sigstore"]
The cosign (ghcr.io/sigstore/cosign:v3.0.4) and rekor-cli (ghcr.io/sigstore/rekor-cli:v1.4.3) tool containers ship as one-shot helpers in devops/compose/docker-compose.stella-infra.yml under the sigstore profile; enable them with docker compose --profile sigstore. The default Postgres (postgres:18.1), Valkey (valkey/valkey:9.0.1), and RustFS images are supplied via the POSTGRES_IMAGE / VALKEY_IMAGE / RUSTFS_IMAGE env variables (see env/stellaops.env.example) rather than hard-coded in the Compose files, so prod deployments can override with audited digests.
Corrected. There is no
devops/compose/docker-compose.rekor-v2.yamloverlay file. A self-hosted Rekor v2 (tiles) server is defined inline as therekor-v2service indocker-compose.stella-infra.ymlunder thesigstore-localprofile (image fromREKOR_TILES_IMAGE). It is configured via therekor-server serveflags (--http-port 3322,--grpc-port 3323,--signer-filepath,--gcp-bucket,--gcp-spanner) — there is noREKOR_SERVER_URLknob on that service. Enable it withdocker compose --profile sigstore-local up -d rekor-v2.
14) Governance & keys (who owns the trust root)
- Release key policy: only the Release Engineering group can push signed releases; 4‑eyes approval; TUF‑style manifest possible in future.
- Signer acceptance policy: embedded release identities are updated only via minor upgrade; emergency CRL supported.
- Customer keys: none needed for core use; enterprise add‑ons may require per‑customer registries and keys.
15) Roadmap (Ops)
- Windows containers GA (Scanner + Zastava).
- Key Transparency for Signer certs.
- Delta‑kit (offline) for incremental updates.
- Kubernetes/Operator CRDs remain out of scope unless the product decision is reopened.
- **SBOM protobuf as default transport at rest (smaller, faster).
Appendix A — Minimal SLO monitors
authority.tokens_issued_totalslope ≈ normal.signer.requests_total{result="success"}/minute> 0 (when scans occur).attestor.submit_latency_seconds{quantile=0.95}< 0.3.scanner.scan_latency_seconds{quantile=0.95}< target per image size.concelier.export.duration_secondsstable;excititor.consensus.conflicts_totalnot exploding after policy changes.- RustFS request error rate near zero (or
s3_requests_errors_totalwhen operating against S3); PostgreSQLpg_stat_bgwritercounters hit expected baseline.
Appendix B — Upgrade safety checklist
- Verify release manifest signature.
- Ensure Signer/Authority/Attestor are same minor.
- Verify DB backups < 24h old.
- Confirm ILM won’t purge compliance artifacts during upgrade window.
- Roll one component at a time; watch SLOs; abort on regression.
End — Release & Operations Architecture
