What each proof proves — and what it does not
CodeRifts issues several kinds of proof. Each one is load-bearing only inside a named bound. This page is the honesty table: what the product asserts, and the residual it refuses to dress as proof.
Agents still branch on execution_action only. Unknown values are not
permission.
Three different limit sets exist, and this page is only one of them. Measured 2026-09-22:
- This page — the prose honesty table, written per claim.
- Eight surface-wide limits, served as data in
.well-known/coderifts.jsonunderdoes_not_prove. They are printed in full, with the command that fetches them, on the verify page. Flat statements, not categories. - Per-endpoint tables — a separate
does_not_provelist that six analysis surfaces return inline on their own responses (23 lines in total). They are visible in the API response itself; pricing states their scope.
None of the three is a restatement of another, and a decision response carries none of them:
does_not_prove is not a field on the preflight envelope.
The three does_not_prove scopes, platform 8 · decision 6 · receipt 3, are three questions with zero lines in common, and does_not_prove_scope names which list a document carries. CodeRifts enforces only at the measured, wired boundaries; there the operation-bound grant is verifiable. About the model's intent, paths outside the boundary and the human approver it claims nothing beyond the available evidence. The record-keeping reading of one receipt is one line of evidence.
The four claim levels
Every proof below belongs to one of four levels. The level tells you what kind of claim it is and who stands behind it. We ship all four; they are listed here so you can tell them apart, because they are not interchangeable and a stronger-sounding one is not automatically a stronger claim.
1. Mediated
Asserts: these calls went through the gate.
Does not assert: that the calls we never saw went through it. The gate observes what is routed to it; anything a host invokes outside the returned tool table is invisible to this level.
Backed by: signed decision receipts (crchain.v1), verifiable offline against a pinned public key.
What you can reach today: Public. Any receipt can be checked with the open-source verifier at coderifts/receipt-verifier — no API key and no CodeRifts account.
2. Reconciled
Asserts: here is the target’s history set against the grants we issued, and here are the exceptions.
Does not assert: that an exception is benign, or that the history we read is complete. It names differences; a human still judges them.
Backed by: a ledger of issued grants reconciled against observed changes.
What you can reach today: Customer-reachable. GET /api/v1/reconciliation on app.coderifts.com, authenticated with your API key (X-API-Key or Authorization: Bearer) — the account is read from the credential, so the report covers your own proven-bound repositories and nothing else. Supply platform, repository, since and until; add format=text for the plain-text rendering. A repository you have not proven a binding for returns 403 binding_not_proven rather than an empty report, because an empty report would read as “no exceptions”. On GitHub the report is read through the installed GitHub App; on GitLab and Bitbucket, pass a short-lived token in X-Coderifts-Scm-Token, which is never stored.
One field is withheld, and the report says so. An EXCEPTION_SCOPE_MISMATCH row — content that matches a decision we issued, but a decision bound to a different repository than yours — arrives with decision_id: null and decision_id_withheld: "cross_scope". That identifier belongs to a decision outside your binding, so it is withheld rather than shown. A withheld id does not mean no decision existed. It means one existed and is not yours to read. The row still counts as an exception and is still listed as one: withholding narrows what you can see, never what the report admits to.
3. Tested
Asserts: probe results, dated and pinned to the versions they were measured against.
Does not assert: that a clean run means no bypass exists, and not that the host cannot reach the target. The probe searches the host for unmediated paths, so its strongest possible result is “none of these classes found one here”. Whether the host is excluded from writing at all is a property of the target-side permission model, which the probe does not inspect and cannot infer from its own silence. It covers the probe classes it ran, in the process it ran in, against the versions named in the report — and it says so in its own output.
Backed by: @coderifts/bypass-probe, which attempts to reach a target you designate by paths the gate does not mediate, and reports what it found.
What you can reach today: Public. npx @coderifts/bypass-probe runs against your own wiring; the source is at coderifts/bypass-probe. Findings rot when a dependency moves, which is why every result carries its version pins.
4. Represented
Asserts: for the tool set with this digest, every entry declared mutating is wrapped by the guard. The host signs the declaration; we co-sign that it is internally consistent.
Does not assert: that every tool which can mutate a governed target is in the declaration. We co-sign the consistency of what was declared, not its truth. If the host omits a mutating tool, the attestation is still internally valid and still wrong — and the host, not CodeRifts, is accountable for that omission. This is the narrow reading, and it is the only one we make.
Backed by: cr.toolset.attest.v1 — a host-signed tool-set declaration with a self-verifying digest.
What you can reach today: Public. The declaration verifies offline with verify-toolset.js / verify_toolset.py in coderifts/receipt-verifier.
Represented + Tested is the audit pattern
The pairing is what makes these more than a list. Represented supplies accountability: a named party signed a declaration and can be held to it. Tested supplies sampling: an adversarial probe goes looking for what the declaration would have missed. Neither is sufficient alone — a declaration nobody probes is an assertion, and a probe with nothing to compare against is an anecdote. Sampling is also not structure: a probe reports what it reached from the host, while a target-side permission model is what would exclude the host in the first place. Where such a check exists it belongs beside these two, and finding nothing by sampling is never a substitute for it.
The two are linked by the tool-set digest: the probe reports which tool set it measured, and the declaration says which tool set was claimed. When the digests match, the probe’s findings and the host’s claim are about the same thing — and when they differ, that difference is itself the finding.
The ceiling, stated once
None of the four proves that no ungoverned path exists. That claim is not available from where we stand: we can observe what reaches the gate, reconcile what we issued against what changed, probe the paths we thought to try, and hold a signer to what they declared — but the absence of an unmediated path is not something any of these can establish. These four are what we ship instead of that claim, and you should read every proof on this page inside that limit.
The three distinguishers
Decision semantic hash
Proves: “fresh and replay say the same thing.” “The hash therefore proves equivalence over what a replay carries, not over the full analysis tier.”
Does not prove: identity of the input bundle or scoring config (that is a different fingerprint); verbatim equality of receipt tokens; that timestamps, correlation ids, retrieval packaging, or analysis-tier sections omitted on replay are the same.
The hash is deliberately broader than the input fingerprint and narrower than the full response, so a later lookup can still be the same decision.
Approver count
Proves: “Count proves: N distinct login strings on the list (not N real people).” “Membership proves: subject was on the supplied list at evaluation time.” “Identity: approved_by is the reviewer's GitHub login. Proves GitHub asserts this account approved a commit SHA — not that the account holds any org role.”
Does not prove: “It does NOT prove the list is correct, current, or authorised by anyone.” “Distinctness is login-string only — one person with two accounts defeats this; the code does not claim otherwise.” Approval is never “safe”: the machine verdict is unchanged (“authorized to proceed despite machine verdict”).
The count is a string-set check, not a people census.
Evidence / waiver gate suppression
Proves: “The gate is suppressed only on the full happy path: the token verifies against a registry-trusted kid AND its payload.scope is user_authorization AND payload.tool matches the request tool (or is *) AND payload.op is among the request capabilities.” For source attestation: attested is true “ONLY on the full happy path” of trusted signature plus content binding to the transmitted data.
Does not prove: “Every other case — absent, malformed, unknown kid, bad signature, wrong scope, tool or op mismatch — behaves EXACTLY as if no evidence were supplied (fail-closed).” “A suppressed A1 gate does not disable the other gates: an input that also triggers a data-laundering gate still lands on BLOCK.” Replay of the same evidence re-authorizes the same action; it is request-bound, not single-use, and is not a clock-expiry proof. A fingerprint-bound policy waiver “does not apply” when the current fingerprint is absent or mismatched (fail closed on binding). Engine-verdict approval is a different claim from a policy waiver and “does not rewrite the machine verdict.”
Suppression is a narrow, conjunctive unlock. Anything short of the full path is the unsuppressed gate.
Further boundaries
Change-set completeness commitment
Proves: a later omission against a host-submitted commitment is detectable. Self-consistency of submitted artifacts against that commitment.
Does not prove: “A cryptographic commitment does NOT prove the
host sent every changed file.” “Mode ATTESTED_UNVERIFIED always carries
both words; not a proof.” Never a boolean completeness:true on the
generic path.
On a generic API without repo access, completeness is theoretically unprovable at issuance; the product stays honest about that.
execution_action (and unknown values)
Proves: the closed set CONTINUE, CONTINUE_WITH_MONITORING, REQUEST_APPROVAL, STOP is the branch key. A known continue-valued action is a necessary condition, never a sufficient one.
Does not prove: “An unrecognised execution_action is not
permission: fail closed (halt or re-preflight).” Do not branch on
decision or safe_for_agent. Additive / unknown envelope fields
are tolerated for validation; they are not permission. Analyze mode is
informational risk only (may_execute: false) — not permission.
Unknown is deny, not a creative reading of nearby fields.
next_agent_step
Proves: structured remediation guidance the agent may follow after a non-CONTINUE decision.
Does not prove: permission to act. “next_agent_step is
suggestion, not permission.” Agents still branch on
execution_action.
How to remediate is not whether to proceed.
Preflight vs merge / runtime enforcement
Proves: this preflight evaluates the change only.
Does not prove: “CodeRifts reports a governance decision and execution_action; it does not by itself block merges. Blocking requires separate repository configuration (required status checks, enforcement) that this rule file does not set.” Runtime enforcement of tool calls is the client-side guard; merge enforcement depends on the repository’s branch protection — “it is NOT determined by this preflight response.”
Install is not branch protection.
Guard execution proof
Proves: what the guarded path checked and whether that call executed, with explicit non-claims always set so missing fields cannot be read as “ok.”
Does not prove: that the change is safe; that the host cannot
bypass; that an absent field is compliance; that change_fp is what
executed (it is what was checked); that calls outside the guarded table
are visible; that the execution-result hash is artifact-match proof;
that a host-asserted conditional write was a verified compare-and-swap.
The package cannot force the host to only call the returned table.
An opt-out arm is a different residual from that one: with requireExecutionStateMatch: false (execution_state_check_disabled), in observeOnly, or on a 'warn' mismatch (runUnenforced), the call still runs and the proof records enforced: false. A proof is not a claim that the path enforced.
The coverage aggregator is scoped the same way: FULLY_ENFORCED and may_claim_full_tetrad hold for the applicable tetrad only. Neither is a product-wide inescapability claim.
CAS attestation
Proves: linkage of a frozen execution proof with a
conditional-write outcome; authorized_and_committed only on a clean
committed branch.
Does not prove: only-write-on-host; that a version token proves change-fingerprint match; that committed-stale is safe; that the execution-result hash equals CAS bytes; that the host cannot bypass; a re-decision of governance ALLOW/BLOCK.
Attestation is pairing two inputs, not a new verdict.
Commit observation (T3)
Proves: the target, re-read after the host write,
matched the authorized after (content on filesystem adapters, version
token on API / DB / Registry adapters) at observation time.
Does not prove: atomicity; that no other writer acted between write and observation; content equality on token-only adapters; that the host’s attestation is true.
Observed at T3, not atomic: another writer may act between write and observation; token-only adapters compare version token not content; host attestation is a host claim layered on the measurement.
enforced is a pre-write fact and is unchanged by T3. The drift event commit_observed_drift is report-only, not a permission gate.
Remediation-loop attestation
Proves: typed closure linking a prior BLOCK’s remediation transaction to a later ALLOW execution chain; refuses when the input fingerprints match (unchanged input is not permission).
Does not prove: the patch addressed required changes; recheck scope was honored; no other changes rode along; the new ALLOW was caused by the remediation; that the host cannot bypass.
Correlation is not causation; fingerprint match is not a second authorize.
Receipt chain linkage (offline)
Proves: predecessor commitments inside the token bodies you present: none removed or reordered (tamper-evident).
Does not prove: Ed25519 signatures, expiry, keys, or
authorization. “Neither proves the predecessor was ever a real signed
receipt.” An intact chain does not prove session completeness, that
edits landed, or that downstream CI may skip re-analysis.
chain_status: absent is not “unlinked”; it is a different gate.
Prefer tamper-evident language over tamper-proof.
Channel-chain chain_status
Proves: a supplied previous receipt verified against the current
key (intact), was omitted (absent, annotation only), or failed
verification (broken).
Does not prove: a broken chain on a read-only action changes the decision (it does not). Absent is annotation only. Broken plus a destructive capability escalates to REQUIRE_APPROVAL and never silently passes.
Annotation is not authorization, except the one destructive escalation.
TOCTOU / measurement time
Proves: “Resolving content proves what was true at measurement time.”
Does not prove: the tree is still that content at write time. “A host that then writes unconditionally still races.” Opt-in execution-state recheck can detect or enforce against drift; it is not a full TOCTOU closure. Conditional write remains host-side.
Monitoring sink (CONTINUE_WITH_MONITORING)
Proves: agreement between a host declaration that a monitoring
sink is wired and a present onEvent callback. Without both, WARN
does not proceed (MONITORING_UNWIRED).
Does not prove: that any event reaches a destination. “A no-op
() => {} is indistinguishable from a real logger.” “A declaration
is a claim we record, not a fact we verify.”
CONTINUE_WITH_MONITORING “is not ‘proceed with caution’ without
monitoring.”
Required-check app_id
Proves: “only a real app_id proves the green came from OUR app.”
Does not prove: a required check matched by name only
(app_id null) was produced by CodeRifts; that path is satisfiable by
any repository writer.
Name match is not app binding.
Measured on coderifts/demo
Read from the GitHub API on 2026-09-02 against pull request #4. Values are copied from the provider, not derived. The name in the list below is that capture. On pull request 4 and pull request 26 both required contexts concluded failure: CodeRifts / issuer (App 2860592) and CodeRifts / contract-gate (Actions 15368). contract-gate (Action) is a third run, not a required context.
Current state — measured 2026-09-20: coderifts/demo main answers "protected": true on the public branches endpoint. The homepage records the same return from the other side, re-read 2026-09-19. So the 2026-09-15 reading below is history, not the current state — it is kept word for word because it is what was true then, and because the capture it annotates was taken while the branch was open. Historical capture — re-read 2026-09-15: two of the values below no longer hold. coderifts/demo main is no longer protected — the branch-protection endpoint answers 404 Branch not protected, enforcement_level is off and both contexts and checks are empty. So enforce_admins: true cannot be read at all today, and the pull request reports mergeable: MERGEABLE / mergeStateStatus: BEHIND rather than blocked. The 2026-09-02 reading is kept as the history it is; the row that still holds is negative test: NOT_RUN. Protection was removed from that repository at some point between the two readings, and nothing here noticed until it was read again.
- required check
CodeRifts / contract-gate (Action)- bound to source
true—app_id 15368- readback
EXACT— one poster carried that exact name- posted by
github-actions(app_id 15368), conclusionfailure- rollup state
blocked- enforce_admins
true- negative test
NOT_RUN
Does not prove:
that the check which satisfied the requirement came from the gate rather than from another workflow
under the same integration — app_id 15368 is GitHub Actions as a whole, not one
workflow. The negative test that would settle it has not been run, so nothing here reports whether a
foreign poster could satisfy this requirement.
Usage observation vs declaration
Proves: declaration answers who intends to use X; observation answers who read X (when). Element-level traffic without a consumer id still proves traffic arrived.
Does not prove: unobserved means unused. “ABSENT ≠ ZERO”: nobody sending traffic means every field is unobserved — unobserved must never mean unused. Declared intent is not measured traffic.
Tool annotations, including ours
Proves: a tool annotation such as readOnlyHint proves that the server declared an intent for that tool, and that a client reading the tool list received that declaration.
Does not prove: that the tool is read-only. An annotation is a server declaration, not a verified property, and that holds for the annotations we publish as much as for anyone else’s. Nothing on either side measures whether a tool annotated read-only writes. This is the same distinction as analysis is not permission, one layer down: annotation_declared is not annotation_verified.
A confirmation at the tool layer
Proves: a tool that asks for confirmation before a spending action proves that the confirmation was requested and answered at the tool layer.
Does not prove: that the spend required it. Where the credential lives inside the agent’s own configuration — an env block the agent can read — a caller that goes around the tool still holds the key, and the key still spends. A confirmation that lives in the tool layer is a convention unless something outside the agent’s scope holds the credential. This is a property of the configuration shape, not of any one implementation.
A signed ceiling is not a signed payment
Proves: a signed spending ceiling proves the holder agreed to an upper bound before any settlement happened.
Does not prove: that a later settlement matched the intent that produced the signature. A scheme whose first “up to” authorization also grants a one-time unlimited allowance to a permit contract has a ceiling that is bounded in the signature and unbounded on chain. Nothing in the signature identifies afterwards which settlement it authorized — the same gap as a grant that carries a nonce but is never observed being consumed.
Read-or-prepare, and the file that holds the measure
Proves: a tool surface where every tool is read-or-prepare proves that no tool in that surface commits a side effect on its own.
Does not prove: that the boundary holds while the measured party can edit what measures it. What is free may stay free; what holds the measure must not be editable by the party being measured. A surface can be entirely read-or-prepare and still be ungoverned if the threshold it is judged against lives inside the same session. Panickssery et al., NeurIPS 2024, measured that models recognize and favor their own generations, arXiv:2404.13076, and Zheng et al., NeurIPS 2023, measured a self-enhancement bias in LLM-as-a-judge, arXiv:2306.05685, so the agent must not grade its own change.
A tool table has a working size
Proves: an enumerated tool table proves which tools a host offered to the model in one context, and the guarded-table assurance proves which of them a mutator can reach.
Does not prove: that the model picked the right one. An independent catalogue of MCP server architectures measured tool-selection accuracy falling below 90% between 10 and 15 tools per context for Claude Haiku 4.5, and between 20 and 30 for Sonnet 4 (arXiv:2606.30317). A table that grows past a model’s working size does not become less guarded — coverage is a property of the table. Selection is a property of the context the table is read in, and nothing we sign measures it. A short fixed loop stays inside the measured band; a wide catalogue does not, and the receipt looks identical either way.
What VERIFIED means, per provider
Proves: The provider-enforcement statements name what VERIFIED means for each provider, in that provider’s own words, with the source. Three providers, three different guarantees — uniform prose is exactly what creeps in where the guarantees differ.
Does not prove: that one provider’s guarantee transfers to another. Read them side by side on Enforcement status; the section there is generated from the CLI’s own statements and a guard fails if the page and the source drift apart.
An analysis receipt is never a grant
Proves: an analysis call says what a change is. Measured on the live endpoint 2026-09-20, an analyze preflight answers may_execute: false, authorization_effect: NONE and receipt_kind: NONE — it does not merely withhold permission, it issues no receipt at all.
Does not prove: anything about permission, in any field. There is no analysis-shaped receipt that could be mistaken for a grant, because analysis returns none. And where a receipt does exist, a token on its own still answers currently_authorized: null. The hosted verify_receipt route, given a token alone, answers currently_authorized null. The open offline verifier prints VERIFIED_CURRENT and has no currently_authorized field. Measured the same day: valid: true, status: VERIFIED_CURRENT, and the note says the status “reflects signature and expiry only”. Null is not a no; it is the absence of the question’s inputs.
Decision outcomes API
Proves: post-hoc observed reality bound to a past decision id, when a row is recorded.
Does not prove: calibration, success rate, or that a missing row
means the decision was good. Empty list interpretation is
absence_is_unknown (absent ≠ zero / success).
Audience on a receipt
Proves: when set, the envelope audience is the authenticated key identity; a non-null intended audience that does not match is the wrong audience.
Does not prove: org or installation scope. Anonymous receipts do not bind a holder identity.
Blast-radius signals
Proves: caller-declared target sensitivity can only raise severity, never lower it.
Does not prove: absence of the signal is a finding. Absence changes nothing (the same absent-is-no-signal principle as chain attestation and evidence).
Retired signing key window
Proves: an issue timestamp inside a retired key’s closed validity window, when the window is fully stated.
Does not prove: “A retired key without retired_at cannot prove a closed window” — fail-closed false.
MCP gateway core
Proves: a derived allow / deny / require_approval from the
product execution_action map (unknown or missing → deny).
Does not prove: that this module sits on a wire in front of arbitrary MCP servers. “This module alone does not sit on a wire.” Scoring is not reimplemented here.
Incomplete analysis and approval
Proves: only a completed analysis with real findings may be approved. The label may be BLOCK or REQUIRE_APPROVAL (severity, not permission).
Does not prove: that an approval on incomplete analysis is risk acceptance. “It is risk ignorance wearing process.”
Last verified: 2026-08-20. Statement changes require source quotes.
Conformance END_TO_END (2 vectors, RECORDED)
@coderifts/conformance@0.8.11 reports END_TO_END COVERED / RECORDED, 2 vector(s) via TARGET_STATE_TRANSITION_PROVEN: a governed ref moved to the authorized commit under a signed grant, observed afterwards by a separate read-only process. Seven profiles exist, 2 on LIVE evidence and 5 on RECORDED. That count is not this profile's 2 vectors. It is trusted-executor-integrity, not a provider merge.
Proves: in one recorded contract-publish run, a trusted executor updated a hermetic bare-Git ref to the commit the grant authorized, and a separate process that cannot write then read the object database and found that end state. The profile names that TARGET_STATE_TRANSITION_PROVEN.
Does not prove: that CodeRifts witnessed or signed the provider state. Boundary, exactly as the profile records it: proof_scope TRUSTED_EXECUTOR, provider_witness NOT_APPLICABLE, externally_witnessed false. Not a provider merge (PATH B). Not externally witnessed. A customer who installs this package is not looking at a GitHub merge CodeRifts performed.
The GitHub positive provider-loop (coderifts/demo PR #14) is a separate provider-integration claim. That loop’s readback stays unsigned (provider_witness: carried_unsigned) and is not this 2-vector profile. See provider canary.
Profile states live in the generated manifest: releases/atomic-stack.json (conformance.profiles). Replay on a stranger’s machine: VERIFY.md. What is a gate today versus planned / on-request (not available): claim table.
Last verified: 2026-08-20 (proof-type rows); END_TO_END 2 vectors, RECORDED, recorded in assurance-profiles-2026-09-23.json against @coderifts/conformance@0.8.11. Statement changes require source quotes.