Skip to main content

🚀 Beta: All Pro and Team features are free. Install on GitHub →

Enforcement status

See where your posture reports — and where it prevents.

The cross-layer status surface gives an honest picture of the enforcement posture your configuration currently exposes.

What status reports

coderifts status is a read-only cross-layer enforcement report for Runtime, Merge, Deploy, and Content. It prints the statuses the endpoint measured: no GitHub writes and no branch-protection changes.

REPORTS

The result is visible while merge or deploy can still proceed.

PREVENTS

The action physically cannot proceed on that path.

coderifts status owner/repo
coderifts status --repo owner/repo --json

What enforce does

coderifts enforce closes enforcement gaps by chaining existing setup commands: Merge → setup-required-check; Runtime → hook install (apply only) plus agent-guard guidance; Deploy → deploy-gate CD-step guidance; Content → guidance only.

Dry-run by default

--apply is required to mutate. The command does not silently flip enforcement, does not bypass underlying command safety, does not label Runtime or Content as server ENFORCING, and does not upgrade UNKNOWN.

coderifts enforce owner/repo
coderifts enforce --repo owner/repo --apply

The reporting-to-enforcement bridge

status shows the posture the endpoint measured. enforce is the dry-run-first setup path for closing gaps. The gates enforce; these commands surface and configure the posture.

Make the check block a merge

A CodeRifts check appears on a pull request as soon as the App is installed. It does not block anything at that point. Four conditions have to hold together before GitHub will actually stop a merge; miss any one and the check is advisory, which looks identical on the PR page.

  1. Branch protection requires the context by name. The name is CodeRifts — API Contract Check, and the separator is an em dash (U+2014). A hyphen never matches, and a context that never matches never blocks.
  2. The context is bound to the App, not just to the name. Under name-only matching (app_id: null) any user with write access can post a success status under that name and open the merge. Bind it to app_id: 2860592.
  3. An analysable schema is present. With no spec to read, the check reports neutral — and GitHub does not treat neutral as a failure. A required check can stay green while looking at nothing.
  4. enforce_admins is on. Without it an administrator walks straight past a red check, and the merge happens anyway.

Binding by app_id is what the checks[] form of the branch-protection API is for:

gh api -X PUT repos/OWNER/REPO/branches/main/protection/required_status_checks \
  --input - <<'JSON'
{
  "strict": true,
  "checks": [
    { "context": "CodeRifts — API Contract Check", "app_id": 2860592 }
  ]
}
JSON

One name is not a candidate for this. CodeRifts / contract-gate is posted by two different surfaces, and the App-side one is advisory — requiring that context does not give you a blocking gate. What each path does separates the two.

Everything above is GitHub, and it is the “how to make it block” side. Below is the other side, for all three providers we read: what a VERIFIED result means there, and what it cannot mean. It is generated from the CLI’s own statements, so this page cannot drift from the tool that produces the verdict.

Two app ids appear below, and they are not the same control. The section above binds CodeRifts — API Contract Check to app_id: 2860592, the CodeRifts App. The section below describes a required check named contract-gate, which the GitHub Action posts under 15368 — the GitHub Actions App, shared by every workflow in the repository. Both are real surfaces and both can be required; only the first identifies a single issuing app. What each path does separates them per path.

What VERIFIED means, per provider

GitHub

VERIFIED on GitHub means a required status check named contract-gate is bound to a specific app id, on a surface that blocks the merge — either classic branch protection's required_status_checks.checks[], or an active repository ruleset that targets this branch. Only that app can satisfy the check; a passing status posted by anything else does not clear it.

What it cannot mean:

  • It does not identify the WORKFLOW. The bound id is normally 15368, the GitHub Actions App, which is shared by every workflow in the repository — anyone who can write .github/workflows can post a passing check under it. A required workflow pinned by sha is what narrows this to specific bytes.
  • It does not bind a repository admin. With enforce_admins off, an admin merges past the check.
  • It is a configuration fact, not a run: it says the gate is set up, not that any particular pull request was gated by it.
  • It does not cover bypass actors, which are not readable from the ruleset document.

GitLab

VERIFIED on GitLab means the merge was gated: the protected branch restricts who may merge and forbids force-push, the project requires all status checks to pass, and an external status check passed for the merge request HEAD SHA.

What it cannot mean:

  • It does not identify WHO satisfied the check. GitLab external status checks bind to the merge request HEAD SHA and carry no issuer identity — the API records that a check passed, not which integration passed it. Any actor holding a token permitted to post external status checks can satisfy this control.
  • There is no GitLab equivalent of the GitHub app-id binding. This is a platform limit, not a configuration gap: no setting on GitLab closes it.
  • External status checks are a GitLab Ultimate feature. On a lower tier the project cannot express a merge-blocking check at all, which we report as UNSUPPORTED_PLAN rather than as a misconfiguration.

Bitbucket

We do not currently issue VERIFIED for Bitbucket from configuration alone. Branch restrictions are readable and we report exactly which are present; the result is capped at UNVERIFIABLE until a behavioural canary observes the provider actually refusing a merge.

What it cannot mean:

  • A green build is not an unforgeable gate. require_passing_builds_to_merge gates on build statuses, and any actor with repository write can overwrite a status by posting a new one on the same commit.
  • The control that WOULD be unforgeable — a required custom merge check, which is a Forge app and Premium-only — exposes no API for reading its configuration, so whether it is present and required cannot be determined by reading.
  • Because of the two limits above, a configuration read on Bitbucket can never rise above UNVERIFIABLE. Only the negative canary can settle it.

Honest bound

Status reflects configuration, not a guarantee. A layer shown as preventing depends on repository and host configuration. Prevention holds inside the wired boundary; an unwired surface can be bypassed.