CodeRifts Decision Spec
Machine-readable, mode-discriminated JSON for API contract governance. Preflight is a discriminated union on preflight_mode: analyze is informational only; authorize is operation-bound and may mint a receipt. Analyze responses cannot be read as permission.
Contents
- Preflight modes (v2 union)
- Response shapes (analyze vs authorize)
- Authorize decision values
- safe_for_agent (authorize only)
- Pattern Registry
- Extended Decision Object
- How Agents Should Use This Spec
- How Agents Use the Decision Spec (integration guide)
- Integration Examples
- Auto-Discovery
- Versioning Policy
Preflight modes (Decision Spec 2.0)
preflight_mode is required on every preflight request (analyze or authorize). A request without it returns 400 with a machine-readable error naming both modes.
Legacy pin (30 days): send decision_spec_version: "1.0" to receive the pre-v2 shape (including soft-default mode and analyze responses that still carried execution vocabulary). Responses and HTTP headers mark deprecation; sunset is 2026-09-07T00:00:00Z. After sunset, only the v2 contract remains.
| Mode | Purpose | JSON Schema branch |
|---|---|---|
| analyze | Informational risk / impact only. Branch on analysis_outcome and may_execute (always false). Not permission. | Prohibits decision, execution_action, safe_for_agent |
| authorize | Operation-bound path. Requires context.operation. May mint chain_receipt. Downstream gates verify the receipt conjunctively. | Requires decision + execution_action (+ safe_for_agent) |
Honest note (risk vs permission): Analyze responses do not carry decision, execution_action, or safe_for_agent. Risk classification is analysis_outcome (closed set: NO_BREAK_DETECTED | BREAKS_DETECTED | ANALYSIS_FAILED) plus risk/impact payload fields. That is not authorization. Permission requires the authorize path and a verified receipt: receipt present and currently_authorized and operation match and fingerprint match and allow-class execution_action. No single field alone permits proceed.
Response shapes (analyze vs authorize)
The published preflight consumer schema is a oneOf on preflight_mode. The first example below is analyze (informational). The second is authorize (operation-bound).
ANALYZE response (informational — not permission)
{
"preflight_mode": "analyze",
"decision_spec_version": "2.0",
"analysis_outcome": "BREAKS_DETECTED",
"authorization_effect": "NONE",
"may_execute": false,
"receipt_kind": "NONE",
"risk_score": 87,
"breaking_changes": 3,
"patterns": [
"AUTH_SCOPE_REDUCTION",
"FIELD_REMOVED",
"ENDPOINT_REMOVED"
],
"requires_migration": true,
"timestamp": "2026-08-08T10:00:00Z"
}
No execution_action, no safe_for_agent, no decision, no chain_receipt. Branch on may_execute / analysis_outcome only for risk handling — never treat this body as a green light to merge, deploy, or call tools.
AUTHORIZE response (operation-bound)
{
"preflight_mode": "authorize",
"decision_spec_version": "2.0",
"receipt_kind": "operation_authorization",
"decision": "BLOCK",
"execution_action": "STOP",
"safe_for_agent": false,
"risk_score": 87,
"breaking_changes": 3,
"patterns": ["AUTH_SCOPE_REDUCTION", "FIELD_REMOVED", "ENDPOINT_REMOVED"],
"requires_migration": true,
"operation": "merge",
"chain_receipt": "<signed token when signer configured>",
"timestamp": "2026-08-08T10:00:00Z"
}
Branch on execution_action for proceed/halt. Use decision as explanation. A downstream merge/deploy/runtime gate must verify the receipt (conjunctive checks) — possession of execution_action alone is not enough.
Field Definitions (by mode)
| Field | Mode | Description |
|---|---|---|
| preflight_mode | both | Required discriminator: analyze | authorize. |
| analysis_outcome | analyze | Risk classification only: NO_BREAK_DETECTED | BREAKS_DETECTED | ANALYSIS_FAILED. Not authorization. |
| may_execute | analyze | Always false on analyze. Analyze never grants execute. |
| authorization_effect | analyze | Always NONE on analyze. |
| receipt_kind | both | analyze: NONE. authorize: operation_authorization when a receipt was issued, else NONE. |
| decision | authorize only | ALLOW | WARN | REQUIRE_APPROVAL | BLOCK. Explanation of the authorize verdict. Omitted on analyze. |
| execution_action | authorize only | CONTINUE | CONTINUE_WITH_MONITORING | REQUEST_APPROVAL | STOP. Proceed signal. Omitted on analyze. |
| safe_for_agent | authorize only | Dashboard/legacy flag. Do not branch on it alone. Omitted on analyze. |
| chain_receipt | authorize | Signed token when issuer configured. Absent key when none issued. Never on analyze. |
| risk_score | both | 0–100 composite risk under supplied evidence. |
| breaking_changes | both | Count of breaking changes detected. |
| patterns | both | Named patterns. See Pattern Registry. |
| decision_spec_version | both | "2.0" on current contract; "1.0" under the legacy pin. |
Decision Values
The change violates a governance rule or exceeds the risk threshold. The requested operation must not proceed through an enforcing path.
When agents see BLOCK: Do not proceed. The API contract has changed in a way that will break this agent's tool calls or workflow steps.
The change is high-risk but does not automatically block. Human approval required before merge.
When agents see REQUIRE_APPROVAL: Pause execution. Wait for human sign-off before calling the updated API.
The change is potentially risky but within policy. Not itself permission: on acting paths, proceed only with a verified receipt that is currently authorized and matches operation, fingerprint and required context — the warning travels with the decision.
When agents see WARN: not itself permission. On acting paths, proceed only with a currently authorized receipt matching operation, fingerprint and required context — and monitor downstream behavior after deployment.
No breaking changes detected. ALLOW means no configured blocking signal was detected under the supplied evidence. A contract-level ALLOW is not a runtime deployment guarantee.
When agents see ALLOW: no configured blocking condition was found. ALLOW alone is not sufficient authorization to execute. On acting paths, proceed only after the associated receipt is currently authorized and matches operation, fingerprint and required context.
safe_for_agent Flag (authorize only)
On authorize responses only. Analyze responses omit this field entirely. Prefer branching on execution_action for control flow; treat safe_for_agent as a dashboard/legacy signal. safe_for_agent: false is set when any of the following agent-breaking patterns are detected:
- • Tool schema drift (
TOOL_CALLING_SCHEMA_DRIFT) - • Tool result shape change (
TOOL_RESULT_SHAPE_DRIFT) - • Agent protocol change (
AGENT_PROTOCOL_DRIFT) - • Workflow chain break (
WORKFLOW_CHAIN_BREAK) - • Auth delegation change (
AUTH_DELEGATION_DRIFT) - • Shared state schema change (
SHARED_STATE_SCHEMA_DRIFT)
If safe_for_agent: false, agents must not call the updated API without human review.
Pattern Registry (v1.0)
Patterns are named identifiers for categories of breaking changes. They are stable across spec versions.
Contract Patterns
| Pattern | Severity | Description |
|---|---|---|
| FIELD_REMOVED | HIGH | A response or request field was removed |
| FIELD_RENAMED | HIGH | A field was renamed (old name no longer exists) |
| TYPE_CHANGED | HIGH | A field's type changed incompatibly |
| REQUIRED_ADDED | HIGH | A previously optional parameter is now required |
| ENDPOINT_REMOVED | CRITICAL | An endpoint was removed |
| AUTH_SCOPE_REDUCTION | CRITICAL | Authentication requirements were tightened |
| ENUM_RESTRICTED | MEDIUM | Enum values were removed |
Agent Patterns
| Pattern | Severity | Description |
|---|---|---|
| TOOL_CALLING_SCHEMA_DRIFT | CRITICAL | MCP/function calling schema changed |
| TOOL_RESULT_SHAPE_DRIFT | CRITICAL | Tool return value structure changed |
| AGENT_PROTOCOL_DRIFT | CRITICAL | Agent communication protocol changed |
| WORKFLOW_CHAIN_BREAK | CRITICAL | A field used by a downstream workflow step was removed |
| AUTH_DELEGATION_DRIFT | CRITICAL | Agent authentication delegation changed |
| SHARED_STATE_SCHEMA_DRIFT | CRITICAL | Shared state between agent steps changed |
Behavioral Patterns (roadmap — requires traffic capture)
| Pattern | Severity | Description |
|---|---|---|
| LATENCY_DRIFT | MEDIUM | Response time degradation detected |
| SIGNAL_LOSS | HIGH | API signal quality degrading |
| SYNAPTIC_NOISE_RISE | MEDIUM | Inconsistent response patterns |
| AUTH_CONDUCTION_DECAY | HIGH | Auth success rate declining |
Extended Decision Object (Authenticated)
With an API key, the full decision object is returned including blast radius, migration plan, compliance index, and workflow simulation:
{
"preflight_mode": "authorize",
"decision_spec_version": "2.0",
"decision": "BLOCK",
"execution_action": "STOP",
"safe_for_agent": false,
"risk_score": 87,
"breaking_changes": 3,
"patterns": ["AUTH_SCOPE_REDUCTION", "FIELD_REMOVED"],
"requires_migration": true,
"timestamp": "2026-08-08T10:00:00Z",
"extended": {
"omega_api": 87.3,
"reflex_triggers": [
{ "rule": "endpoint_removed ∧ public_api", "decision": "BLOCK" }
],
"blast_radius": {
"affected_consumers": 4,
"estimated_cost": "$12,000–$45,000",
"migration_effort_days": 8
},
"migration_plan": "Restore removed field as deprecated with x-sunset date. Notify consumers via POST /api/v1/scar/create.",
"compliance_index": "F",
"workflow_simulation": {
"simulation_result": "WORKFLOW_BROKEN",
"first_failure_step": 2
}
}
}
Configurable heuristic estimate (engineer rate × migration hours) — see methodology
What the fingerprint covers
The verdict_fingerprint is a SHA-256 hash computed over the canonical verdict core: the decision, per-module risk scores, gate results, and the aggregation values — nothing else.
Transport metadata is deliberately outside the hash: timestamps, correlation IDs and the receipt signature are not fingerprint inputs. The Ed25519 receipt signs over the fingerprint — a downstream step, never an input to it.
The same analysis therefore yields a byte-identical fingerprint across runs, regardless of when it ran or which receipt attests it. Determinism lives in the verdict core; freshness lives in the receipt.
How Agents Should Use This Spec
Always set preflight_mode. Use analyze for risk inspection; use authorize when a merge/deploy/tool path needs a receipt. Never treat an analyze body as permission.
For a language-by-language integration walkthrough (Python, Node.js, Go) built on this spec, see How Agents Use the Decision Spec — a practical guide, not a second protocol definition.
Step 1a: Analyze (informational)
POST https://app.coderifts.com/api/v1/preflight
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
{
"preflight_mode": "analyze",
"artifacts": [{ "id": "api", "type": "openapi", "before": "...", "after": "..." }]
}
// Analyze: no execution_action / safe_for_agent / decision — branch on may_execute / analysis_outcome
if (response.may_execute !== false) throw new Error("unexpected analyze body");
if (response.analysis_outcome === "ANALYSIS_FAILED") {
// incomplete analysis — re-preflight or escalate; not permission
}
// Risk only: BREAKS_DETECTED is informational here, not a green light to proceed
logRisk(response.analysis_outcome, response.risk_score, response.patterns);
Step 1b: Authorize (operation-bound)
POST https://app.coderifts.com/api/v1/preflight
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
{
"preflight_mode": "authorize",
"context": { "operation": "merge" },
"artifacts": [{ "id": "api", "type": "openapi", "before": "...", "after": "..." }]
}
Step 2: Branch on execution_action (authorize only)
const { execution_action, decision, patterns, chain_receipt } = response;
// Branch on execution_action (proceed signal); decision explains why.
// CONTINUE_WITH_MONITORING requires a wired monitoring sink (@coderifts/agent-guard).
if (execution_action !== "CONTINUE") {
throw new Error(`CodeRifts halted: execution_action=${execution_action} (decision=${decision}); patterns=${(patterns||[]).join(",")}`);
}
// Downstream gates must still verify chain_receipt conjunctively (receipt + currently_authorized
// + operation + fingerprint + execution_action). Do not treat CONTINUE alone as permission.
await handToMergeGate(chain_receipt);
Step 3: Handle STOP gracefully
if (execution_action === "STOP") {
// 1. Log the full authorize response (decision explains why)
// 2. Notify the team
// 3. Do not retry as if it were ALLOW — remediate, then re-preflight authorize
// 4. Check extended.migration_plan when present
}
Integration Examples
LangChain
from langchain.tools import tool
from coderifts import CodeRifts
coderifts = CodeRifts(api_key="cr_live_...")
@tool
def safe_api_call(endpoint: str, payload: dict):
"""Call an API endpoint with CodeRifts governance check."""
result = coderifts.authorize_change_set(
context={"operation": "tool_call"},
artifacts=[{
"id": endpoint,
"type": "openapi",
"before": get_cached_schema(endpoint),
"after": get_current_schema(endpoint),
}],
)
# Authorize only: branch on execution_action; decision explains why.
# Analyze would omit execution_action — never treat analyze as permission.
action, decision = result.execution_action, result.decision
# CONTINUE_WITH_MONITORING requires @coderifts/agent-guard monitoringSinkWired:true
# (plus a real monitor callback); this example has no sink — proceed only on CONTINUE.
if action != "CONTINUE":
return {"error": f"CodeRifts aborted: execution_action={action!r} (decision={decision})"}
# A valid signature is not authorization: currently_authorized comes from verify_receipt.
receipt = getattr(result, "chain_receipt", None)
authz = coderifts.verify_receipt(
receipt,
operation="tool_call",
environment=getattr(result, "environment", None),
target_id=getattr(result.decision_result, "artifact_digest", None),
fingerprint=getattr(result, "verdict_fingerprint", None),
decision_result=result.decision_result.to_dict(),
) if receipt else None
if getattr(authz, "currently_authorized", None) is not True:
return {"error": "CodeRifts aborted: receipt not currently_authorized"}
return call_endpoint(endpoint, payload)
AutoGen
import autogen
from coderifts import CodeRifts
coderifts = CodeRifts(api_key="cr_live_...")
def coderifts_preflight_hook(agent, message):
# One operation label for both calls: the receipt is scoped to the operation it was
# authorized for, so the check must name the SAME one the preflight used.
operation = message.get("operation", "tool_call")
result = coderifts.authorize_change_set(
context={"operation": operation},
artifacts=message["artifacts"], # [{id, type, before, after}, ...]
)
# Authorize: branch on execution_action; decision explains why.
action = result.execution_action
# CONTINUE_WITH_MONITORING requires @coderifts/agent-guard monitoringSinkWired:true
# (plus a real monitor callback); this example has no sink — proceed only on CONTINUE.
if action != "CONTINUE":
raise ValueError(f"CodeRifts aborted: execution_action={action!r} (decision={result.decision})")
# A valid signature is not authorization: currently_authorized comes from verify_receipt.
receipt = getattr(result, "chain_receipt", None)
authz = coderifts.verify_receipt(
receipt,
operation=operation,
environment=getattr(result, "environment", None),
target_id=getattr(result.decision_result, "artifact_digest", None),
fingerprint=getattr(result, "verdict_fingerprint", None),
decision_result=result.decision_result.to_dict(),
) if receipt else None
if getattr(authz, "currently_authorized", None) is not True:
raise ValueError("CodeRifts aborted: receipt not currently_authorized")
return message
agent = autogen.AssistantAgent(
name="SafeAgent",
pre_message_hooks=[coderifts_preflight_hook]
)
Claude / MCP
{
"mcpServers": {
"coderifts": {
"url": "https://app.coderifts.com/mcp",
"headers": { "x-api-key": "YOUR_API_KEY" }
}
}
}
Add the instruction below to your agent's system prompt to have it run preflight_change_set before tool invocations.
Auto-Discovery
Agents can discover CodeRifts governance endpoints automatically:
GET https://coderifts.com/.well-known/coderifts.json
Returns the full manifest including available tools, endpoints, and this spec URL.
Versioning Policy
- • Current: Decision Spec 2.0. Preflight responses are a mode-discriminated union. Analyze omits authorization vocabulary; authorize requires
decision+execution_action. - • v1.0 legacy pin: request
decision_spec_version: "1.0"until 2026-09-07T00:00:00Z for the old shape (soft-default mode; analyze could still carry execution fields). Deprecation headers mark the pin. - • Within a major, additive optional fields may appear without a major bump. Removing or renaming required control fields is a major.
- • The authorize envelope schema for stored receipts remains under
decision-result.v1*; the preflight flat body ispreflight-response.v2.
Changelog
| Version | Date | Changes |
|---|---|---|
| 2.0 | 2026-08 | Mode-required preflight; analyze structurally omits decision/execution_action/safe_for_agent; oneOf schema; 30-day v1.0 pin |
| 1.0 | 2026-03-18 | Initial stable release (legacy pin until 2026-09-07) |