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 8.7.2, measured 2026-10-06 offline: a deny (STOP or REQUEST_APPROVAL), and a receipt that is missing, unsigned, forged, expired, or bound to another operation, environment or artifact, each exit 1; --enforce does not change the exit. The measured binding is: 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). The verdict line is identical either way; advisory mode adds ADVISORY MODE — this gate did not block 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. On 2026-10-06, --artifact set to the commit SHA the receipt was bound to exited 1 with stale_artifact. The same receipt with --artifact set to that receipt's artifact digest exited 0.
coderifts deploy-gate --env production --artifact "$ARTIFACT_DIGEST" --receipt receipt.json
CODERIFTS_DEPLOY_ADVISORY=1 coderifts deploy-gate --env production --artifact "$ARTIFACT_DIGEST" --receipt receipt.json
Run on 2026-10-06 against coderifts@8.7.2, in an empty directory with no receipt.json. The stderr verdict from that run:
$ 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
CodeRifts deploy-gate: BLOCKED reason=no_receipt status=pending
- action: re-preflight this { environment, artifact } — the receipt does not authorize it.
ADVISORY MODE — this gate did not block
$ echo $?
0
The verdict line is identical either way; advisory mode adds ADVISORY MODE — this gate did not block and exits 0.
--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.