High-Level Architecture
Verified against: commit
ab4b3ca1d9(2026-09-26). Re-verify the service list withpython tools/scripts/generate/service-inventory.py --check, which fails when the service inventory no longer matchessrc/, the compose estate and the release bundle.
Stella Ops Suite is a self-hosted release control plane for container estates outside Kubernetes. Its product outcome is a governed release: an immutable CI artifact, complete policy inputs, scoped approval, attributable target execution and recovery, and evidence a separate reader can verify offline. Later risk assessments retain the historical decision and its exact evidence revision. It runs within the operator’s trust boundary with no cloud-managed dependency.
Flow and ownership review: verified against
60913a04352cb4899ab6443e596811b11cc3f01aon 2026-09-30. This source review does not establish deployed completion. The accepted decisions and core acceptance scenarios identify the remaining work. Recheck the current owner endpoints through the linked contracts below.
This page is the system at one level of detail: the services, who owns which data, how the pieces are deployed, and which hosts were retired into which successor. For trust boundaries, flows and failure behaviour read ARCHITECTURE_OVERVIEW.md. For the index into module dossiers, contracts and schemas read ARCHITECTURE_REFERENCE.md.
Services
The authoritative per-service table is the generated service inventory. It gives each service’s source project, image, database and role, compose file, bundle presence, Doctor wiring and dossier, and lists every disagreement between the sources. The families below group those services by what they do.
Entry, identity and control plane
| Service | Source | Database | What it does |
|---|---|---|---|
router-gateway | src/Router/ | none | The single HTTP ingress. It authenticates requests, signs the identity envelope and routes to services over the Valkey messaging transport. |
authority | src/Authority/ | stellaops_authority | OAuth2 and OIDC: users, clients, tenants, scopes and the issuer directory. It issues short-lived, sender-constrained tokens. |
platform | src/Platform/ | stellaops_platform | Console backend: read-models across services, environment settings, and the environment-state custodian that holds sealed air-gap posture. |
release-orchestrator | src/ReleaseOrchestrator/ | stellaops_release_orchestrator | Releases, promotions, gates, approvals, deployments, environments and topology. It is the durable release truth. |
agent-core | src/ReleaseOrchestrator/__Agents/ | none | Deployment executor, opt-in through the agents profile. Placement and local/remote target access follow the selected executor capability. |
jobengine-web, jobengine-worker, jobengine-estate-worker | src/JobEngine/ | stellaops_jobengine | Scheduling and execution with hybrid logical clock ordering, and the task-pack registry. The estate worker runs privileged estate packs under the estate-doctor profile. |
integrations-web | src/Integrations/ | stellaops_integrations | Connectors to SCM, CI, registries and secret stores, loaded as plugins. |
notify-web, notify-worker | src/Notify/ | stellaops_notify | Notification rules, channels and delivery. |
timeline-web | src/Timeline/ | stellaops_timeline | Event indexing, timelines, and the hash-chained audit record that every service’s audit emission lands in. |
Security decision pipeline
| Service | Source | Database | What it does |
|---|---|---|---|
scanner-web, scanner-worker | src/Scanner/ | stellaops_scanner | Pulls an image by digest, runs the OS and language analyzers, and produces the SBOM and reachability facts. |
sbomservice | src/SbomService/ | stellaops_sbomservice | SBOM documents, versions and lineage. |
vulnerabilities-web, vulnerabilities-worker | src/Vulnerabilities/ | stellaops_vuln | The vulnerability hub. It ingests advisories and VEX, keeps them as immutable observations, correlates them, and publishes the corpus that Scanner, Policy and offline sites consume. Binary and symbol workflow also live here. |
signals | src/Signals/ | stellaops_signals | Reachability signals, runtime observations and coverage. |
graph-api | src/Graph/ | stellaops_graph | The dependency graph and the reachability subgraph store. |
policy-engine | src/Policy/ | stellaops_policy | Deterministic policy-as-code evaluation into verdicts, overlays and gate decisions. |
findings-web, findings-worker | src/Findings/ | stellaops_findings | The findings ledger, risk scoring and the vulnerability explorer. |
unknowns-web | src/Unknowns/ | stellaops_unknowns | Unknown and unresolved state as a first-class record. |
advisoryai-web, advisoryai-worker | src/AdvisoryAI/ | stellaops_advisoryai | Advisory explanation, knowledge search and operations memory, with configurable local or remote model providers. |
Evidence, signing and replay
| Service | Source | Database | What it does |
|---|---|---|---|
evidence-web, evidence-worker | src/Evidence/ | stellaops_evidence | DSSE attestation, the local transparency log, proof chains, sealed decision capsules, evidence exports and legal holds. |
attestor-tileproxy | src/Attestor/StellaOps.Attestor.TileProxy | none | Caches transparency-log tiles for offline verification. It belongs to the Evidence family by ownership. |
tsa | devops/docker/tsa | none | The local RFC 3161 timestamp authority, built from an OpenSSL base rather than from src/. |
signer | src/Attestor/StellaOps.Signer/ | stellaops_signer | Key custody and signing. It stays outside the Evidence family on purpose. |
replay-web | src/Replay/ | stellaops_replay | Deterministic replay capture and verification. |
Registry and offline exchange
| Service | Source | Database | What it does |
|---|---|---|---|
registry-web, registry-token | src/Registry/ | stellaops_registry | The product’s own OCI registry and its token issuer (ADR-041). |
offlinekit-web, offlinekit-worker | src/OfflineKit/ | stellaops_offlinekit | Offline exchange: export runs, signed carriers, mirror bundles and their import custody. |
Infrastructure
postgres is one PostgreSQL server that hosts every stellaops_* database, each with its own role. valkey is the messaging transport and cache. rustfs is the S3-compatible object store. The sigstore and sigstore-local profiles add Rekor and the Sigstore client tools. The compose estate and the bundle both fail to render until the operator sets the PostgreSQL, Valkey and object-store images to digest-pinned references.
Hosts in src/ that no service runs
The inventory’s findings list every host project that no publish key, compose file or bundle runs. The workflow-web publish key remains, because its engine is dormant by owner ruling. No host project is left without a service: on 2026-09-27 (PCD-73) five were withdrawn to src/__Obsoleted/: Doctor.WebService, Policy.Gateway, RuntimeInstrumentation.Worker, Scanner.Cartographer and Verdict.WebService. Tester.WebService is listed separately as an opt-in QA overlay, which must never reach a production stack.
Ownership boundaries
- One service, one database. Each service owns one PostgreSQL database and its own role on the shared server. It resolves only its own
STELLAOPS_POSTGRES_<SERVICE>_CONNECTIONand fails closed without it. A web and a worker of the same family share that family’s database.REVOKE CONNECTon every sibling database is the boundary. Detail: ADR-039 and the database ownership matrix. - Schema by startup migration. Each service converges its own schema from embedded SQL when it starts. Migrations are forward-only.
- Across services: the owner’s API or events. A service reads another service’s data through that owner’s API behind the Router, through events, or through a registered read contract. It never opens a sibling’s database.
- One service, one source graph. A deployable’s transitive project references contain only its own family, classified neutral foundations and verified-closed client contracts. The legacy edge register holds zero pins, so any new cross-service implementation edge fails the build-boundary gate.
- Plugins. Connectors, crypto providers, analyzers and deployment executors load from mounted, signed plugin bundles through one fail-closed admission path. See
dev/sdks/plugin-development.mdandplugins/ARCHITECTURE.md. - Tenancy. Tenants are logical scopes inside one operator’s trust boundary. The tenant comes from the Authority identity envelope, never from a raw header. See ADR-005 and ADR-002.
Governed release and proof flow
- Receive the artifact and its source evidence. Evidence receives subject-bound producer attestations; Scanner owns scan attempts and results. A scan or manually entered commit does not prove that CI supplied build evidence. Receipt does not establish cryptographic verification.
- Evaluate and authorize. Policy owns policy evaluation. Release Orchestrator binds the selected release, policy, environment, approval and dispatch state. It enforces contributor ownership, approval/signing rules and current execution prerequisites through its own contracts.
- Observe and recover. An accepted dispatch is not a completed deployment. Target digest and health observations identify their observer. Retry and rollback retain the original operation and recovery evidence; a current topology change does not rewrite the recorded execution plan.
- Complete the exact proof. Evidence owns append-only bundle creation and verification; Signer remains a separate key owner. RO owns the committed decision revision and writes a durable, revision-bound seal intent in the same transaction; a reconciler delivers it to Evidence under a tenant-bound idempotency key, and Evidence returns the same bundle for a retried request (CCP-050, source; estate activation and acceptance need an authorized redeploy). Proof failure does not authorize redeployment or automatic rollback, and the existing disabled configuration and grants remain in force.
- Verify independently and respond to later risk. Offline verification uses the identified packet, packaged verifier and declared trust inputs. Replay requires the recorded subject/pack/version and historical inputs. New advisory, VEX and runtime evidence updates the current assessment while preserving the prior decision and proof.
Current APIs and their limits are documented in the promotion ownership contract and promotion evidence contract. The acceptance profile uses a supported Docker/Compose estate, two environments and a multi-component application within one operator boundary. It bounds validation; it does not remove other runtimes from the support matrix or claim the core journey has already passed.
Deployment shapes
| Shape | Defined by | What runs |
|---|---|---|
| Compose estate | devops/compose/docker-compose.stella-ops.yml and the family overlays | The default docker compose up starts infrastructure, the services in docker-compose.stella-services.yml, and the Evidence and OfflineKit families. Findings, AdvisoryAI, Vulnerabilities, the Notify worker and the JobEngine estate worker are added by their family overlay files. Profiles add the agent, Sigstore and the estate worker. |
| Release bundle | devops/release/bundle/ | A generated compose file with every image pinned by digest, installed by install.sh or install.ps1. It runs the long-running services and three init containers: scanner-cache-init, release-orchestrator-agent-ca-init and offlinekit-exportcenter-init. agent-core is behind the agents profile. The inventory lists which estate services the bundle does not carry. |
| Air-gapped site | OFFLINE_KIT.md, modules/offlinekit/ | The same bundle, mirrored by digest. Advisory and VEX data arrive as the Vulnerabilities hub’s corpus publication and the compact offline vulnerability database, carried and imported through OfflineKit. Sealed posture is held by Platform’s environment state. |
Retired hosts and their successors
Each retired host is named here once. The generated inventory lists every frozen host project under src/__Obsoleted/ with the successor its freeze record names.
| Retired | Successor |
|---|---|
scheduler-web, packsregistry-web | jobengine-web |
packsregistry-worker | jobengine-worker |
attestor, evidence-locker-web, evidence-locker-worker | evidence-web, evidence-worker |
export-web, export-worker (ExportCenter) and the src/Mirror/ module | offlinekit-web, offlinekit-worker |
| AirGap controller and time hosts | Platform’s environment state for posture; OfflineKit for carriers and time-anchor verification |
| Concelier, Excititor, VexHub and VexLens as services | vulnerabilities-web, vulnerabilities-worker |
binaryindex-web and the symbols server | the Vulnerabilities hub; shared analysis libraries stay in src/BinaryIndex/ |
reachgraph-web | graph-api |
issuer-directory-web | authority |
opsmemory-web | advisoryai-web |
notifier-worker | notify-worker |
findings-ledger-web, findings-security-web, riskengine-web, riskengine-worker, findings-vulncorrelation | findings-web, findings-worker |
| TimelineIndexer web and worker hosts | timeline-web |
doctor-web and the Doctor scheduler | Doctor checks registered by each service with Platform, plus the CLI; the doctor-trend job runs in jobengine-web |
| Remediation module | none; the Console remediation surfaces are AdvisoryAI’s autofix |
| Verdict library’s PostgreSQL persistence | none; the verdict build, replay and diff routes are stateless |
Related deep dives
Plugin extensibility
dev/sdks/plugin-development.md— the shared fail-closed admission chokepoint and the per-module loader statusplugins/ARCHITECTURE.md— loader internals and the code-plugin versus declarative-pack boundarymodules/platform/architecture-overview.md— plugin extensibility as a cross-cutting property
Controlled conversational interface
modules/advisory-ai/chat-interface.mdmodules/advisory-ai/unified-search-architecture.mdoperations/unified-search-operations.md
AI code guard
Audit evidence packs
