Configuration Reference
Environment variables and OPA policy examples for the Release Orchestrator.
Status: Mixed reference; implemented sections identify their source of truth. Source: Architecture Advisory Section 15.2 Related Modules: Security Overview, Promotion Manager Sprint: 101_001 Foundation
Overview
This document provides the configuration reference for the Release Orchestrator, including environment variables and OPA policy examples.
Environment Variables
Core Configuration
# Database
STELLA_DATABASE_URL=postgresql://user:pass@host:5432/stella
STELLA_REDIS_URL=redis://host:6379 # Valkey (Redis-compatible)
STELLA_SECRET_KEY=base64-encoded-32-bytes
STELLA_LOG_LEVEL=info
STELLA_LOG_FORMAT=json
Authentication (Authority)
# OAuth/OIDC
STELLA_OAUTH_ISSUER=https://auth.example.com
STELLA_OAUTH_CLIENT_ID=stella-app
STELLA_OAUTH_CLIENT_SECRET=secret
Agents
# Agent TLS
STELLA_AGENT_LISTEN_PORT=8443
STELLA_AGENT_TLS_CERT=/path/to/cert.pem
STELLA_AGENT_TLS_KEY=/path/to/key.pem
STELLA_AGENT_CA_CERT=/path/to/ca.pem
Plugins
# Plugin configuration
STELLA_PLUGIN_DIR=/var/stella/plugins
STELLA_PLUGIN_SANDBOX_MEMORY=512m
STELLA_PLUGIN_SANDBOX_CPU=1
Integrations
# Vault integration
STELLA_VAULT_ADDR=https://vault.example.com
STELLA_VAULT_TOKEN=hvs.xxx
Release Environment Limits
Administrators can restrict release creation and artifact-derived successor versions to a known set of environments. This protects self-service developer updates and operator release creation from accidentally targeting environments outside the tenant’s approved release path.
The normal administrator control is persisted per tenant through GET/PUT /api/v1/release-orchestrator/release-environment-limit and the Platform Setup Defaults & Guardrails page. The configuration keys below are a bootstrap/fallback path: they apply only until a tenant-stored setting exists.
# Require every release create/update/clone/successor request to name a target environment.
ReleaseOrchestrator__ReleaseEnvironmentLimit__RequireTargetEnvironment=true
# Array form, preferred in appsettings.json and Kubernetes/compose env expansion.
ReleaseOrchestrator__ReleaseEnvironmentLimit__AllowedEnvironments__0=env-dev
ReleaseOrchestrator__ReleaseEnvironmentLimit__AllowedEnvironments__1=env-stage
# CSV fallback for simpler deployment systems.
ReleaseOrchestrator__ReleaseEnvironmentLimit__AllowedEnvironmentsCsv=env-dev,env-stage
When RequireTargetEnvironment=true and no target environment is supplied, the API returns 400 with release_target_environment_required. When an allow-list is present and the target is outside the list, the API returns 403 with release_environment_not_allowed.
Auto-deploy on approval (durable approval → deployment transition)
Status: Implemented (Sprint 20260703_002 / DTC-8). Source of truth:
src/ReleaseOrchestrator/__Apps/StellaOps.ReleaseOrchestrator.WebApi/Services/DeploymentDispatchProcessor.cs,DispatchOnApprovalReleaseTruthRepository.cs, and migrationStellaOps.ReleaseOrchestrator.Persistence/Migrations/008_deployment_dispatches.sql.
When a promotion approval reaches approved state (manual quorum met or auto-approved by policy), a deployment-dispatch intent is persisted into release_orchestrator.deployment_dispatches in the same transaction as the approval write. A hosted dispatcher drains due intents with bounded retry/backoff and starts the deployment through the same code path POST /releases/{id}/deploy uses (identical ReleaseTruthGuard fail-closed checks and deploy-engine entry). Terminal dispatch failure surfaces as release status dispatch_failed plus a deployment_dispatch_failed release event.
# Kill-switch (default: true). false = approvals no longer enqueue dispatch
# intents and the dispatcher stays idle; operators deploy via POST /deploy.
ReleaseOrchestrator__AutoDeployOnApproval=true
# Tuning knobs (defaults shown).
ReleaseOrchestrator__AutoDeployDispatch__PollIntervalSeconds=5
ReleaseOrchestrator__AutoDeployDispatch__MaxAttempts=5
ReleaseOrchestrator__AutoDeployDispatch__RetryBaseDelaySeconds=10 # doubles per attempt (deterministic)
ReleaseOrchestrator__AutoDeployDispatch__RetryMaxDelaySeconds=600
ReleaseOrchestrator__AutoDeployDispatch__ClaimBatchSize=10
ReleaseOrchestrator__AutoDeployDispatch__ClaimLeaseSeconds=600 # crash self-heal lease
Scheduled topology readiness
Status: Implemented, disabled by default. Source of truth:
src/ReleaseOrchestrator/__Apps/StellaOps.ReleaseOrchestrator.WebApi/Services/TopologyReadinessScheduler.cs(sectionReleaseOrchestrator:TopologyReadiness).
The optional WebApi background pass refreshes target connection health and persists readiness reports for the Environments Command view. Enabling it causes periodic outbound probes to operator-configured target or binding destinations and persistent health/readiness writes. The service validates all durations at startup; Interval and PerTargetTimeout must be positive and InitialDelay must not be negative. Positive intervals below 60 seconds are clamped to 60 seconds.
# Opt in on exactly ONE ReleaseOrchestrator WebApi replica. Default false.
ReleaseOrchestrator__TopologyReadiness__Enabled=true
# Cadence and per-target bounds (defaults shown).
ReleaseOrchestrator__TopologyReadiness__InitialDelay=00:00:45
ReleaseOrchestrator__TopologyReadiness__Interval=00:05:00
ReleaseOrchestrator__TopologyReadiness__PerTargetTimeout=00:00:12
# Independent steps (both default true when the scheduler is enabled).
ReleaseOrchestrator__TopologyReadiness__RefreshHealth=true
ReleaseOrchestrator__TopologyReadiness__EvaluateReadiness=true
There is no distributed lease for this hosted service. Do not enable it on more than one WebApi replica: each enabled replica would repeat the same probes and writes. For sealed/air-gap operation, the scheduler does not select any public endpoint itself, but configured targets and infrastructure bindings can cross a network boundary. Leave it disabled unless all destinations are local or explicitly allow-listed; operators can instead run the authenticated POST /api/v1/release-orchestrator/environments/readiness/validate-all action when a manual, bounded evaluation is appropriate. Periodic cadence is the only automatic trigger; deployment and agent-heartbeat events do not immediately run the pass.
Approval transition safety
Status: Implemented (RDT-3). Source of truth:
Services/ApprovalSafetyGuard.cs,ApprovalEndpoints.cs,ReleaseControlV2Endpoints.cs, andReleaseDashboardEndpoints.cs.
Every approval route rejects incomplete gate/evidence truth before mutating quorum. Environment protection class is persisted configuration; the optional list below adds decision-signing enforcement to selected target environments. The global OperatorDecisionEnforcement:Approve=true switch remains the all-environments equivalent.
# Per-environment signing rollout. Repeat the numeric suffix for more targets.
ReleaseOrchestrator__ApprovalSafety__SigningRequiredEnvironments__0=production
# Global all-environment approval signing (default false).
ReleaseOrchestrator__OperatorDecisionEnforcement__Approve=false
Protected or signing-required environments also require a signed, basis-bound gate decision and a genuinely verified policy-decision evidence packet. Configure trust roots under ReleaseOrchestrator__EvidenceVerification__TrustedPublicKeys__N; without a trust anchor signed evidence remains honestly recorded and the protected transition fails closed.
SBOM-readiness gate
Status: Implemented. Source of truth:
src/ReleaseOrchestrator/__Apps/StellaOps.ReleaseOrchestrator.WebApi/Services/SbomReadinessGateServices.cs(SbomReadinessGateOptions, sectionReleaseOrchestrator:SbomReadinessGate).
The promotion gate that blocks dispatch until the Scanner reports SBOM results for every digest-pinned release component. The gate fails closed: a probe timeout or transport error maps to failed and denies promotion, so TimeoutSeconds must comfortably exceed the Scanner’s real /api/v1/sbom-readiness latency (observed ~8s on live deployments — the historical 5s default false-blocked promotions with 409 even though the SBOMs existed).
# Master switch (default: true).
ReleaseOrchestrator__SbomReadinessGate__Enabled=true
# Scanner base address the gate probes.
ReleaseOrchestrator__SbomReadinessGate__ScannerBaseAddress=http://scanner.stella-ops.local
# HttpClient timeout (seconds) for the readiness/scan calls. Default 20.
# Fail-closed: a timeout DENIES promotion, so keep this above real scanner latency.
ReleaseOrchestrator__SbomReadinessGate__TimeoutSeconds=20
# Require the SBOM to be attached to the EXTERNAL registry (default: false).
ReleaseOrchestrator__SbomReadinessGate__RequireExternalAttachment=false
# Internal-first fallback: read the deployment registry's OCI referrers when the
# internal store reports `absent` (default: true; fail-safe, never relaxes a DENY).
ReleaseOrchestrator__SbomReadinessGate__ExternalRegistryFallback=true
ReleaseOrchestrator__SbomReadinessGate__ExternalRegistryFallbackTimeoutSeconds=5
# Orchestrator's OWN service identity for the scanner calls (see architecture.md);
# HttpTimeoutSeconds bounds only the Authority token mint, not the readiness probe.
ReleaseOrchestrator__SbomReadinessGate__ServiceIdentity__Enabled=false
ReleaseOrchestrator__SbomReadinessGate__ServiceIdentity__HttpTimeoutSeconds=10
Full Configuration File
# stella-config.yaml
database:
url: postgresql://user:pass@host:5432/stella
pool_size: 20
ssl_mode: require
redis:
url: redis://host:6379 # Valkey (Redis-compatible)
prefix: stella
auth:
issuer: https://auth.example.com
client_id: stella-app
client_secret_ref: vault://secrets/oauth-client-secret
agents:
listen_port: 8443
tls:
cert_path: /etc/stella/agent.crt
key_path: /etc/stella/agent.key
ca_path: /etc/stella/ca.crt
heartbeat_interval: 30
task_timeout: 600
plugins:
directory: /var/stella/plugins
sandbox:
memory: 512m
cpu: 1
network: restricted
evidence:
storage_path: /var/stella/evidence
signing_key_ref: vault://secrets/evidence-signing-key
retention_days: 2555 # 7 years
logging:
level: info
format: json
output: stdout
telemetry:
enabled: true
otlp_endpoint: otel-collector:4317
service_name: stella-release-orchestrator
OPA Policy Examples
Security Gate Policy
# security_gate.rego
package stella.gates.security
default allow = false
allow {
input.release.components[_].security.reachable_critical == 0
input.release.components[_].security.reachable_high == 0
}
deny[msg] {
component := input.release.components[_]
component.security.reachable_critical > 0
msg := sprintf("Component %s has %d reachable critical vulnerabilities",
[component.name, component.security.reachable_critical])
}
Approval Gate Policy
# approval_gate.rego
package stella.gates.approval
default allow = false
allow {
count(input.approvals) >= input.environment.required_approvals
separation_of_duties_met
}
separation_of_duties_met {
not input.environment.require_sod
}
separation_of_duties_met {
input.environment.require_sod
approver_ids := {a.approver_id | a := input.approvals[_]; a.action == "approved"}
not input.promotion.requested_by in approver_ids
}
Freeze Window Gate Policy
# freeze_window_gate.rego
package stella.gates.freeze
default allow = true
allow = false {
window := input.environment.freeze_windows[_]
time.now_ns() >= time.parse_rfc3339_ns(window.start)
time.now_ns() <= time.parse_rfc3339_ns(window.end)
not input.promotion.requested_by in window.exceptions
}
API Error Codes
| Code | HTTP Status | Description |
|---|---|---|
RELEASE_NOT_FOUND | 404 | Release with specified ID does not exist |
ENVIRONMENT_NOT_FOUND | 404 | Environment with specified ID does not exist |
PROMOTION_BLOCKED | 403 | Promotion blocked by policy gates |
APPROVAL_REQUIRED | 403 | Additional approvals required |
FREEZE_WINDOW_ACTIVE | 403 | Environment is in freeze window |
DIGEST_MISMATCH | 400 | Image digest does not match expected |
AGENT_OFFLINE | 503 | Required agent is offline |
WORKFLOW_FAILED | 500 | Workflow execution failed |
PLUGIN_ERROR | 500 | Plugin returned an error |
QUOTA_EXCEEDED | 429 | Digest analysis quota exceeded |
VALIDATION_ERROR | 400 | Request validation failed |
UNAUTHORIZED | 401 | Authentication required |
FORBIDDEN | 403 | Insufficient permissions |
Default Values
| Setting | Default | Description |
|---|---|---|
| Agent heartbeat interval | 30s | Frequency of agent heartbeats |
| Task timeout | 600s | Maximum time for agent task |
| Deployment batch size | 25% | Percentage of targets per batch |
| Health check timeout | 60s | Timeout for health checks |
| Evidence retention | 7 years | Audit compliance requirement |
| Max workflow steps | 50 | Maximum steps per workflow |
| Max parallel tasks | 10 | Per-agent concurrent tasks |
