Deploy gate
Deploy gating is fail-closed by default. Advisory is opt-out.
The deploy gate evaluates a deploy operation for an artifact whose receipt is stale, mismatched or unverified. By default it fails closed: a deny exits 1 and the deploy step stops.
What the deploy gate does
coderifts deploy-gate gates a deploy on the current { environment, artifact } using a preflight receipt. Since CLI 4.3.0 the default is fail-closed, and since 4.4.0 the gate verifies the signed receipt rather than reading it — both still true on the shipped 8.6.3, where --enforce is “accepted silently (exit is fail-closed by default)”, measured 2026-09-15: signature, body hash, expiry, retired-key window, and the operation / environment / artifact binding. A deny, a missing receipt, an invalid one or an expired one all exit 1. A currently_authorized field supplied as input is ignored — the gate computes authorization from verification.
Default vs enforcement
Default
PREVENTS
Fail-closed, exit 1. A deny, or a receipt that is missing, unsigned, forged, expired or bound to a different operation, environment or artifact, all stop the step.
With opt-out
REPORTS
Set CODERIFTS_DEPLOY_ADVISORY=1 (or CODERIFTS_ADVISORY=1) and the gate prints the same verdict and exits 0.
How to opt out
The first form below stops the deploy on a deny. To soften it to reporting, set CODERIFTS_DEPLOY_ADVISORY=1.
coderifts deploy-gate --env production --artifact "$SHA" --receipt receipt.json
CODERIFTS_DEPLOY_ADVISORY=1 coderifts deploy-gate --env production --artifact "$SHA" --receipt receipt.json
Run on 2026-09-15 against the shipped coderifts@8.6.3, in an empty directory with no receipt.json — which is what a first run looks like:
$ coderifts deploy-gate --env production --artifact abc123 --receipt receipt.json
CodeRifts deploy-gate: BLOCKED reason=no_receipt status=pending
- action: re-preflight this { environment, artifact } — the receipt does not authorize it.
set CODERIFTS_DEPLOY_ADVISORY=1 to soften
$ echo $?
1
$ CODERIFTS_DEPLOY_ADVISORY=1 coderifts deploy-gate --env production --artifact abc123 --receipt receipt.json
(same message)
$ echo $?
0
The message is identical either way. What changes is the exit code — which is the whole of what “fail-closed by default” means here.
--enforce and CODERIFTS_DEPLOY_ENFORCE=true still exist, but they do not change the exit code — the default is already fail-closed. They attest ENFORCING for the inescapable_deploy claim, which is an observation about the step, not a change to what it does.
Honest bound
Fail-closed by default means the step stops unless someone opts out. Prevention holds inside the wired boundary: this gate stops this step, in a pipeline that actually runs it. A deploy path that never invokes the gate, or one that sets CODERIFTS_DEPLOY_ADVISORY=1, is outside that boundary. Merge enforcement is a separate question and depends on repository configuration, not on this gate.