Runbook: Release Orchestrator - Required Evidence Not Found
Audience: Platform and Security on-call engineers responding to a Stella Ops release promotion blocked by the Security Gate for missing evidence (SBOM, scan, or reproducibility/attestation). Use this runbook to read the gate’s violation codes, locate the missing evidence, and produce it in the owning service so the promotion can re-evaluate.
Sprint: SPRINT_20260117_029_DOCS_runbook_coverage Task: RUN-004 - Release Orchestrator Runbooks
Reconciliation note (verify against
src/ReleaseOrchestrator): This runbook was reconciled against the implemented Release Orchestrator. “Required evidence not found” is not a free-standing error — it is what the blocking Security Gate (StellaOps.ReleaseOrchestrator.Promotion.Gate.Security.SecurityGate,GateName = "security-gate",IsBlocking = true) reports when a promotion’s components are missing SBOMs, scans, or reproducibility/attestation evidence. The gate emits structured violation codes (e.g.SEC_SBOM_MISSING,SEC_SCAN_MISSING,SEC_SCAN_TOO_OLD,SEC_REPRO_EVIDENCE_MISSING,SEC_REPRO_DSSE_PROVENANCE_MISSING,SEC_REPRO_REKOR_UNVERIFIED,SEC_REPRO_EVIDENCE_SCORE_MISSING) that surface in the promotion’sPromotion.GateResults. Evidence inputs come fromISbomService/SbomRequirementChecker.HasSbomAsync(digest),IScannerService.GetLatestScanAsync(digest)(scan +ReproducibilityEvidence), andIEvidenceScoreService(Evidence Locker). Earlier drafts referenced acheck.orchestrator.evidence-availabilityDoctor check, anOrchestratorEvidenceMissingalert, and a large CLI surface (stella promote {start|status|approve|reject|list},stella promotion evidence/retry/status,stella evidence list/chain/store health/retry-store/policy show,stella scanner jobs/queue list,stella scanner config set,stella scan image --sbom-only/--force,stella attest build/verify-offline/predicates/create/status) — none of those exist in the shipped CLI. (APromoteCommandHandler+BuildPromoteCommand()forstella promote …live insrc/Cli/StellaOps.Cli/CliApplication.cs, but that command tree is not wired into the program entry point:Program.csbuilds the root viaCommandFactory.Create(...), which registers no top-levelpromote.) They have been corrected to the implemented surface or flagged NOT IMPLEMENTED below.
Metadata
| Field | Value |
|---|---|
| Component | Release Orchestrator |
| Severity | High |
| On-call scope | Platform team, Security team |
| Last updated | 2026-05-30 |
| Doctor check | check.release.promotion.gates (Release Pipeline plugin; default severity Warn) |
The Doctor check above is the closest real diagnostic —
PromotionGateHealthCheck(src/Doctor/__Plugins/StellaOps.Doctor.Plugin.Release/Checks/PromotionGateHealthCheck.cs). It queries pending approvals fromGET /api/v1/release-orchestrator/approvals?statuses=pendingand evaluates their persistedgateResults, including denied, advisory, skipped, exception, and unevaluated outcomes. There is nocheck.orchestrator.evidence-availabilitycheck in source. The full Release Pipeline plugin shipscheck.release.active,check.release.promotion.gates,check.release.rollback.readiness,check.release.environment.readiness, andcheck.release.environment.matches-approved— there is nocheck.orchestrator.*family.
Symptoms
- [ ] Promotion blocked by the blocking Security Gate with violations such as
SEC_SBOM_MISSING/SEC_SCAN_MISSING(these are the “required evidence not found” cases) - [ ]
Promotion.GateResultsshows a failedsecurity-gateGateResult(Passed=false,Blocking=true) - [ ] Error message lists “Component
<name>has no SBOM” or “Component<name>has no security scan” - [ ]
SEC_REPRO_EVIDENCE_MISSING/SEC_REPRO_DSSE_PROVENANCE_MISSING/SEC_REPRO_REKOR_UNVERIFIEDwhen the gate config requires reproducibility/attestation evidence - [ ]
stella doctor --check check.release.promotion.gatesreports a Warn/Fail - [ ] Approval evidence reference set (
GET /api/v1/approvals/{id}/evidence) is missing SBOM/attestation refs
NOT IMPLEMENTED: there is no
OrchestratorEvidenceMissingalert in source. The evidence-readiness signal is the per-component evidence check insideSecurityGate(its violation codes) plus the Doctorcheck.release.promotion.gatesresult. Verify any dashboard alert is wired to those, not to a nonexistent metric.
Impact
| Impact Type | Description |
|---|---|
| User-facing | Promotion blocked by the blocking Security Gate until evidence is generated |
| Data integrity | Artifact is safe; the gate is fail-closed by design. A missing SBOM/scan/attestation is the correct blocking outcome, not data loss |
| SLA impact | Release blocked; security/compliance requirements not met |
Diagnosis
Quick checks
Run the Doctor promotion-gate health check:
stella doctor --check check.release.promotion.gatesThis verifies required policies are loaded, the attestor is reachable, and approvers are configured. (
--checktakes a single check ID — there are no wildcards.)Inspect the blocked promotion’s status and gate results via the API. A failed
security-gatewith violation codes (SEC_SBOM_MISSING,SEC_SCAN_MISSING, etc.) on the promotion’s gate results is the “required evidence not found” condition. The v2 approval API surfaces the gate trace:# GET /api/v1/approvals/{id}/gates → { approvalId, decisionDigest, gates[] } curl -s "$ORCH_URL/api/v1/approvals/<approval-id>/gates" \ -H "Authorization: Bearer $TOKEN" -H "X-Tenant-Id: $TENANT"Requires
release:read(ReleaseControlV2Endpoints.cs,MapGroup("/api/v1/approvals")).NOT IMPLEMENTED: there is no
stella promote status <promotion-id>command in the shipped CLI. APromoteCommandHandler(StartAsync/StatusAsync/ApproveAsync/RejectAsync/ListAsyncagainst/api/v1/promotions) and a matchingBuildPromoteCommand()exist only insrc/Cli/StellaOps.Cli/CliApplication.cs, which is not wired to the program entry point —Program.csbuilds the root command viaCommandFactory.Create(...), and that root registers no top-levelpromotecommand. The onlypromoteverbs in the real CLI arestella policy promote <policy-id> --from --to(env-to-env policy promotion, no lifecycle/status) andstella orch(the Source & Job Orchestrator, unrelated to release promotion). Inspect promotion/approval state through the orchestrator API or Console, not apromoteCLI.List evidence packets registered for the release (Release Orchestrator evidence API):
# GET /api/release-orchestrator/evidence?releaseId=<release-id> (also /api/v1/release-orchestrator/evidence) curl -s "$ORCH_URL/api/release-orchestrator/evidence?releaseId=<release-id>" \ -H "Authorization: Bearer $TOKEN" -H "X-Tenant-Id: $TENANT"Requires the
release:readscope.typeandreleaseIdare the supported filters; each row carriesid,releaseId,type,hash,algorithm, andimageDigest.
Deep diagnosis
Read the Security Gate violation codes. The blocking
security-gate(…/Promotion/Gate/Security/SecurityGate.cs) checks each release component and emits apolicyViolationCodesarray in the gatedetails. Map the code to the missing evidence:SEC_SBOM_MISSING— component has no SBOM (SbomRequirementChecker.HasSbomAsync→ISbomService.GetByDigestAsyncreturned null). Only emitted whenrequireSbomis on (defaulttrue).SEC_SCAN_MISSING— component has no security scan (IScannerService.GetLatestScanAsyncreturned null). Also gated byrequireSbom— withrequireSbom=falsea missing scan does not raise this code (the gate skips the component’s scan-derived checks).SEC_SCAN_TOO_OLD— scan age exceedsmaxScanAge(default 24h).SEC_REPRO_EVIDENCE_MISSING— gate requires reproducibility/attestation evidence but none is attached.SEC_REPRO_DSSE_PROVENANCE_MISSING/SEC_REPRO_DSSE_INTOTO_MISSING/SEC_REPRO_REKOR_UNVERIFIED/SEC_REPRO_EVIDENCE_SCORE_MISSING— specific required evidence facets absent (only enforced when the matchingrequire*config flag is set; all default tofalse).
Confirm which evidence the gate config requires. The gate is permissive by default — only
requireSbom(defaulttrue) is on; allrequireDsse*,requireRekorVerification,requireEvidenceScoreMatch, etc. default tofalse. If aSEC_REPRO_*violation fires, the environment’s gate config turned that requirement on. Review the environment gate configuration (EnvironmentGateConfig/SecurityGateConfig) before generating evidence.Check the approval’s structured evidence reference set (v2 approval API):
# GET /api/v1/approvals/{id}/evidence → { packet, manifestDigest, decisionDigest } curl -s "$ORCH_URL/api/v1/approvals/<approval-id>/evidence" \ -H "Authorization: Bearer $TOKEN" -H "X-Tenant-Id: $TENANT"Used to verify the SBOM/attestation/scan reference completeness for an approval decision.
Verify the evidence packet integrity (Release Orchestrator evidence API):
# POST /api/release-orchestrator/evidence/{id}/verify — recomputes and compares the sha256 content hash curl -s -X POST "$ORCH_URL/api/release-orchestrator/evidence/<evidence-id>/verify" \ -H "Authorization: Bearer $TOKEN" -H "X-Tenant-Id: $TENANT"
NOT IMPLEMENTED: there is no
stella promotion evidence <id> --missing, nostella evidence list/chain, nostella scanner jobs/queue list, and nostella attest status. Verified againstsrc/Cli/StellaOps.Cli/Commands/CommandFactory.cs(the real CLI root):
stella promotionbuilds promotion attestations — subcommands areassemble,attest, andverify(stella.ops/promotion@v1), not lifecycle/evidence queries. (detscoreis a separate top-level command,stella detscore run, not apromotionsubcommand.)stella evidencesubcommands areexport,verify,store,status,card,reindex,verify-continuity,migrate,holds,audit,replay,proof,provenance,seal,push-referrer, andlist-referrers— there is noevidence listorevidence chain.stella attestsubcommands aresign,verify,list,show,fetch,key,bundle,attach,oci-list,oci-verify, andlink— there is nobuild,verify-offline,create, orpredicatessubcommand. (attest verifyalready verifies a DSSE envelope offline against policy/trust roots;attest listfilters by--subject/--type/--issuer/--tenant/--scope, while--imagebelongs toattach/oci-list/oci-verify.)
Resolution
There is no orchestrator-side “regenerate evidence” command. The orchestrator consumes evidence produced by Scanner (SBOM + scan), the Attestor/Signer (attestations), and the Evidence Locker (evidence score). Resolve a
SEC_*violation by producing the missing evidence in the owning service for the component digest, then re-evaluating the gate.
Immediate mitigation
Scan the component image to produce SBOM + scan evidence. Use the implemented scan surface (
stella scan run …/stella scan upload …,src/Cli/StellaOps.Cli/Commands/CommandFactory.cs) — there is nostella scan image --sbom-only/--force.stella scan imageonly hasinspect/layers. The Security Gate reads the latest scan for the component digest, so a fresh successful scan clearsSEC_SCAN_MISSING/SEC_SCAN_TOO_OLD.Produce missing attestations (only needed when the gate config requires them). Sign and attach via the attestor surface:
stella attest sign --envelope provenance.json ... # create + sign a DSSE attestation stella attest attach --image <image-ref> ... # attach the attestation to the OCI artifact stella attest list --subject <image-digest> # confirm the attestation is recorded(
stella attestsubcommands aresign/verify/list/show/fetch/key/bundle/attach/oci-list/ oci-verify/link; there is noattest buildorattest create.) Seeattestor-signing-failed.mdif signing itself fails.Register the evidence packet with the orchestrator so promotion/deployment gates can rely on durable evidence truth:
# POST /api/release-orchestrator/evidence (requires release:write) # body: { releaseId, type, rawContentBase64, algorithm? } — the service recomputes the sha256 hash
Root cause fix
If the scan never ran for the component:
- The gate evaluates the component digest, so confirm the release component digest matches a scanned artifact. Components are registered via the release/component API (
/api/release-orchestrator/...,release:write). - Re-run the scan against that exact digest (
stella scan run …), then re-evaluate.
If evidence exists but the gate config requires more than is present:
- A
SEC_REPRO_*violation means arequire*flag is on in the environment’sSecurityGateConfig(e.g.requireDsseProvenance,requireRekorVerification,requireEvidenceScoreMatch,minEvidenceScore). Either produce the required evidence facet, or correct the gate configuration if the requirement was set in error.
If attestation signing failed:
- See
attestor-signing-failed.mdandattestor-rekor-unavailable.md. The Doctor promotion-gate check pings{Attestor:Url}/health; an unreachable attestor surfaces as acheck.release.promotion.gatesWarn.
If the evidence score is not ready (Evidence Locker):
SEC_REPRO_EVIDENCE_SCORE_MISSING/SEC_REPRO_EVIDENCE_SCORE_NOT_READYmeansIEvidenceScoreService.GetScoreAsyncreturned null or a non-readystatus. IfasyncHoldSlaHoursis configured the gate emits a non-blockinghold_asyncoutcome (SEC_HOLD_ASYNC_EVIDENCE_NOT_READY) instead of a hard fail; wait for the score to becomereadyor escalate per the SLA. Seeevidence-locker-ops.md.
Verification
# Confirm the evidence packet is registered and integrity-verified
curl -s -X POST "$ORCH_URL/api/release-orchestrator/evidence/<evidence-id>/verify" \
-H "Authorization: Bearer $TOKEN" -H "X-Tenant-Id: $TENANT"
# Re-evaluate the promotion: re-check the gate trace via the v2 approval API
# (there is no `promote`/`promotion` lifecycle CLI and no `promotion retry`)
curl -s "$ORCH_URL/api/v1/approvals/<approval-id>/gates" \
-H "Authorization: Bearer $TOKEN" -H "X-Tenant-Id: $TENANT"
# Re-run the Doctor gate health check
stella doctor --check check.release.promotion.gates
NOT IMPLEMENTED:
stella promote status,stella promotion retry,stella promotion status,stella scanner queue list,stella scanner config set auto_scan.*,stella evidence store health,stella evidence retry-store, andstella evidence policy showdo not exist. (The orchestrator promotion lifecycle has no dedicated CLI at all in the shippedCommandFactoryroot — see the Diagnosis note above.) Auto-scan triggers and evidence retention are not configured through the CLI surface documented here — verify the relevant service config (Scanner, Evidence Locker) directly. AFailedpromotion re-enters the lifecycle viaRolledBackorAwaitingApproval(PromotionStateMachine), not aretryverb.
Prevention
- [ ] Scan before promote: Ensure every release component digest has a fresh SBOM + scan before a promotion is created, so the Security Gate has evidence to read.
- [ ] Gate config hygiene: Set
SecurityGateConfigrequire*flags per environment deliberately — turning onrequireDsseProvenance/requireRekorVerification/requireEvidenceScoreMatchadds evidence that must actually be produced. - [ ] Mind scan age: Keep
maxScanAge(default 24h) and scan cadence aligned soSEC_SCAN_TOO_OLDdoes not block promotions. - [ ] Monitoring: Wire dashboards to the Doctor
check.release.promotion.gatesresult and thesecurity-gateviolation codes (no dedicated evidence-missing metric exists). - [ ] Async holds: Where evidence is computed asynchronously (Evidence Locker score), configure
asyncHoldSlaHoursso the gate holds non-blocking instead of hard-failing.
Related Resources
- Security Gate (ground truth):
src/ReleaseOrchestrator/__Libraries/StellaOps.ReleaseOrchestrator.Promotion/Gate/Security/SecurityGate.cs - Evidence API:
src/ReleaseOrchestrator/__Apps/StellaOps.ReleaseOrchestrator.WebApi/Endpoints/EvidenceEndpoints.cs - Doctor check:
src/Doctor/__Plugins/StellaOps.Doctor.Plugin.Release/Checks/PromotionGateHealthCheck.cs - Architecture:
docs/modules/evidence-locker/architecture.md - Promotion evidence contract:
docs/modules/evidence-locker/promotion-evidence-contract.md - Related runbooks:
orchestrator-promotion-stuck.md,orchestrator-gate-timeout.md,attestor-signing-failed.md,attestor-rekor-unavailable.md,evidence-locker-ops.md
NOT IN REORG TREE:
docs/operations/evidence-requirements.md(referenced by earlier drafts) does not exist underdocs/operations/. Use the evidence-locker dossier (docs/modules/evidence-locker/architecture.md) and the promotion-evidence contract above instead.
