Decide Rulebook v1
June 14, 2026 ยท View on GitHub
Status: Declarative runtime, trusted adapter contract, immutable registry, and historical replay implemented
Schema version: rulebook_v1
Effective: 2026-06-11
JSON Schema: https://api.decide.fyi/schemas/rulebook-v1.schema.json
Architecture Decision
Decide uses a hybrid architecture with a strict trust boundary:
- Customer-facing production rulebooks are declarative data.
- Trusted executable adapters may exist only as registered, first-party code.
- Arbitrary customer code is never accepted or executed inside Decide.
The public v1 runtime implements both boundaries. The first registered adapter normalizes facts for the Krafthaus Solana Execution Gate.
Why Declarative Is The Core
Production rulebooks need to be:
- reviewable by operators and customers
- portable across environments
- canonicalizable and hashable
- safe to store in Decision Records
- replayable without rebuilding an old application deployment
- constrained enough to validate before execution
- independent of network access, clocks, randomness, and process state
Allowing arbitrary code would weaken each property and turn rulebook execution into an untrusted code-hosting problem.
Where Trusted Code Fits
Some domains require calculations or fact normalization that are awkward in a small condition language. Registered first-party adapters may provide those facts.
A trusted adapter must be:
- registered at deploy time
- identified by a stable adapter ID and version
- pure for the same canonical input
- bounded in execution time and output size
- prohibited from network, clock, randomness, and mutable environment access
- tested independently
- bound to a manifest hash and bundled implementation source hash
- included in the resulting Decision Record and immutable rulebook snapshot
Adapters produce normalized facts. The declarative rulebook still selects the binding outcome.
Rulebook v1 does not accept adapter source code, expressions, JavaScript, or user-defined functions. Unknown object fields are rejected rather than ignored, so callers cannot mistake inert code-shaped data for supported behavior.
The v1 runtime additionally validates adapter output against its registered schema before Rulebook v1 can consume it. Adapter execution failure or output drift fails closed and never falls back to an LLM.
See Trusted Adapters v1.
Public Interface
Rulebook evaluation uses the existing Decision API:
POST /api/decide
Content-Type: application/json
{
"mode": "rulebook",
"rulebook": {
"schema_version": "rulebook_v1",
"rulebook_id": "pricing_exception",
"version": "2026-06-11",
"input_schema": {
"required": ["discount_percent", "margin_percent"],
"properties": {
"discount_percent": { "type": "number" },
"margin_percent": { "type": "number" }
}
},
"rules": [
{
"rule_id": "block_below_margin_floor",
"priority": 100,
"condition": {
"field": "margin_percent",
"operator": "lt",
"value": 15
},
"outcome": {
"decision": "no",
"verdict": "BLOCK",
"action": "reject_discount",
"reason_code": "MARGIN_FLOOR_BREACH"
}
},
{
"rule_id": "approve_standard_exception",
"priority": 50,
"condition": {
"all": [
{
"field": "discount_percent",
"operator": "lte",
"value": 15
},
{
"field": "margin_percent",
"operator": "gte",
"value": 15
}
]
},
"outcome": {
"decision": "yes",
"verdict": "APPROVE",
"action": "approve_discount",
"reason_code": "STANDARD_EXCEPTION_ALLOWED"
}
}
],
"default_outcome": {
"decision": "review",
"verdict": "REVIEW",
"action": "route_to_owner",
"reason_code": "NO_RULE_MATCHED"
}
},
"context": {
"inputs": {
"discount_percent": 10,
"margin_percent": 22
}
}
}
An application that needs registered fact normalization sends adapter instead
of context.inputs:
{
"mode": "rulebook",
"adapter": {
"adapter_id": "solana_execution_gate",
"version": "1.0.0",
"manifest_hash": "fd95907fb68ecc45be3ad9608410e2e3ea29a52b0e33b756086c21c6f520e967",
"input": {
"sol_amount": 48,
"risk_level": "medium",
"evidence_level": "strong",
"quorum_signed": true,
"budget_within_policy": true,
"recipient_verified": true
}
},
"rulebook": {
"schema_version": "rulebook_v1",
"rulebook_id": "solana_execution_gate",
"version": "2026-06-11",
"rules": [
{
"rule_id": "approve_policy_compliant_execution",
"priority": 100,
"condition": {
"field": "decision_score",
"operator": "gte",
"value": 70
},
"outcome": {
"decision": "yes",
"verdict": "APPROVE",
"action": "authorize_execution",
"reason_code": "EXECUTION_GATE_APPROVED"
}
}
],
"default_outcome": {
"decision": "review",
"verdict": "DEFER",
"action": "defer_execution",
"reason_code": "NO_RULE_MATCHED"
}
},
"context": {
"workflow": "solana_execution_gate",
"requested_action": "treasury_payout"
}
}
The abbreviated example omits the additional production block and defer rules.
A request cannot combine adapter.input with context.inputs.
Outcome Model
Each rule and the required default outcome define:
decision: normalizedyes,no, orreviewverdict: purpose-specific uppercase token such asAPPROVE,BLOCK, orNEEDS_REVIEWaction: bounded action identifierreason_code: uppercase machine-readable reason
The normalized decision keeps Decision Record consumers stable. The application verdict preserves the vocabulary required by a specific Krafthaus application.
Evaluation Order
Rules are evaluated by:
- higher
priorityfirst - lexical
rule_idorder when priorities are equal
The first matching rule wins. If no rule matches, default_outcome is used.
This order is independent of JSON object key order and does not depend on an LLM.
Input Schema
input_schema.required lists required dotted input paths.
input_schema.properties may type those paths as:
stringnumberintegerbooleanarrayobjectnull
Missing or type-invalid inputs return:
- normalized decision:
review - application verdict:
NEEDS_INPUT - action:
collect_required_input - reason code:
INPUT_SCHEMA_FAILED
This is a valid bounded Decision result, not a runtime failure.
Conditions
Condition combinators:
allanynot
Leaf operators:
existsnot_existseqneqgtgteltlteinnot_incontainsnot_contains
Rulebook v1 intentionally excludes regular expressions, source code, expressions, network calls, dates derived from the current clock, and dynamic function invocation.
Validation And Limits
- maximum 100 rules
- maximum 256 condition nodes
- maximum condition depth 8
- maximum 32 children per
allorany - stable lowercase IDs
- unique rule IDs
- priorities from
-1000to1000 decisionvalues exactly restricted to lowercaseyes,no, orreview
An invalid rulebook returns HTTP 422 with RULEBOOK_INVALID and structured
field errors. It is never sent to an LLM as a fallback.
An explicit unsupported runtime request such as
binding_mode: "customer_executable_rulebook" returns HTTP 422 with
RULEBOOK_BINDING_MODE_UNSUPPORTED. The API does not ignore that field or
reinterpret it as direct_declarative_rulebook.
Supported binding_mode values must match the request material; a trusted
adapter binding mode without adapter returns RULEBOOK_BINDING_MODE_CONFLICT.
Rulebook v1 rejects caller-supplied response-only Decision Record material before
semantic evaluation. Fields such as runtime_binding, trusted_adapter,
adapter_facts, rulebook_attestation, application_verdict, and action
cannot be supplied at the request boundary, inside context.inputs, or through
adapter facts. These attempts return HTTP 422 with
RULEBOOK_OUTPUT_MATERIAL_FORBIDDEN.
The production path validates each request rulebook against the published JSON
Schema before semantic evaluation. Successful and needs_input responses include
rulebook_contract so downstream systems can record the exact contract that was
enforced:
{
"schema_version": "rulebook_v1",
"schema_url": "https://api.decide.fyi/schemas/rulebook-v1.schema.json",
"schema_hash": "<sha256>",
"evaluator_version": "decide_rulebook_v1"
}
They also include runtime_binding, which records the active production core,
binding mode, verdict authority, adapter authority when present, and
customer_supplied_code: "rejected". The current binding modes are
direct_declarative_rulebook and
trusted_adapter_facts_then_declarative_rulebook.
Hashing And Lineage
The runtime computes a SHA-256 hash over canonical rulebook JSON.
The response exposes that value as:
rulebook.hashpolicy_hashsource_hash
The runtime also computes input_hash over the canonical inputs or trusted
adapter facts actually consumed by the declarative rulebook. The raw inputs do
not need to be returned for downstream systems to bind the Decision Record to
the replay material.
Each successful Rulebook v1 response also includes rulebook_attestation:
schema_version:rulebook_attestation_v1bundle: canonical semantic execution materialbundle_hash: SHA-256 over canonical bundle JSONsignature: Ed25519 signature envelope forbundle_hashwhen a signing key is configured
The bundle contains the engine, evaluator version, rulebook identity and hash, input hash, runtime binding, outcome fields, and trusted adapter attestation when present. The bundle hash lets callers bind a Decision Record to the exact deterministic execution tuple without depending on mutable response formatting.
The signature envelope uses schema version
rulebook_attestation_signature_v1, algorithm Ed25519, and
signed_field: "bundle_hash".
status: "signed"means the response includes a base64url signature and active public key metadata.status: "unsigned"means no signing key is configured in that environment.status: "error"means signing was configured but the key could not be used.
Verification keys are published at:
GET /.well-known/rulebook-attestation-keys.json
The key endpoint returns active_key_id, key_history_count, and a keys
array. The active signing key is marked status: "active". Retired verifier
keys are marked status: "retired" and can include not_before and
not_after timestamps.
Production deployments can require signed Rulebook attestations by setting
DECIDE_RULEBOOK_ATTESTATION_SIGNATURE_REQUIRED=true. When that guard is
enabled, a Rulebook evaluation without a usable signing key returns HTTP 503
with RULEBOOK_ATTESTATION_SIGNATURE_REQUIRED instead of returning a successful
unsigned Decision result.
Rotated verification keys can be published with
DECIDE_RULEBOOK_ATTESTATION_KEY_HISTORY_JSON, a JSON array of retired Ed25519
public keys:
[
{
"key_id": "decide-rulebook-attestation-2026-06-01-prod",
"algorithm": "Ed25519",
"public_key_pem": "-----BEGIN PUBLIC KEY-----\\n...\\n-----END PUBLIC KEY-----",
"status": "retired",
"not_before": "2026-06-01T00:00:00.000Z",
"not_after": "2026-06-11T00:00:00.000Z",
"use": "rulebook_attestation_signature"
}
]
Invalid key history is not partially published. The key endpoint returns
RULEBOOK_ATTESTATION_KEY_HISTORY_INVALID until the configured history is
valid.
The rulebook ID becomes policy_id, and its version becomes policy_version.
The decidesite proxy then incorporates those values into Decision Record v1.
Adapter-backed responses additionally expose:
trusted_adapter.adapter_idtrusted_adapter.versiontrusted_adapter.implementation_revisiontrusted_adapter.implementation_hashtrusted_adapter.manifest_hashtrusted_adapter.input_hashtrusted_adapter.output_hashadapter_facts
The current adapter execution contract is ambient_capability_deny_v2.
Environment, high-resolution clock, Web Crypto randomness, network, and timer
globals are locked before execution. A runtime violation fails closed with
TRUSTED_ADAPTER_CAPABILITY_DENIED.
The public registry binds one rulebook ID/version to both an evaluator version and, when present, one trusted adapter dependency. Adapter drift requires an explicit rulebook or adapter version migration.
Reference Application Patterns
The Solana Execution Gate, Decision Memo Readiness Gate, and Krafthaus Workflow Readiness Binding are adapter-backed reference applications. Their reviewed first-party adapters derive bounded workflow facts, then Rulebook v1 selects the binding outcome.
The Refund, Trial, Cancel, and Return Policy MCP notaries are the direct
declarative reference applications. Their existing deterministic policy-source
lookups normalize explicit facts, then Rulebook v1 selects the binding notary
verdict without a trusted adapter. The inspectable application rulebooks live at
rules/refund-policy-notary-v1.json,
rules/trial-policy-notary-v1.json,
rules/cancel-policy-notary-v1.json, and
rules/return-policy-notary-v1.json.
The stable REST responses remain backward compatible and include the complete
Rulebook v1 result and signed rulebook attestation under rulebook_result. MCP
tool calls expose the same payload as structured content.
Public Conformance Fixtures
The Rulebook v1 conformance index is published at
https://api.decide.fyi/conformance/rulebook-v1/index.json.
Success fixtures assert deterministic semantic output, rulebook_contract
schema URL/hash/evaluator metadata, registry attestation, signature envelope
shape, and trusted-adapter facts when present. Rejection fixtures assert
fail-closed handling for executable-shaped payload fields.
Golden Replay Corpus
The Rulebook v1 golden replay corpus is published at
https://api.decide.fyi/replay/rulebook-v1/index.json.
- corpus version:
rulebook_v1_golden_replay_v1 - replay contract:
historical_rulebook_replay_v1 - generator:
npm run generate:golden-replay - migration dry-run:
npm run rulebook:migration-dry-run -- --json - migration manifest:
rulebook_migration_v1 - migration manifest schema:
https://api.decide.fyi/schemas/rulebook-migration-v1.schema.json
Each fixture freezes the stored rulebook snapshot, evaluator version, direct
input or trusted-adapter dependency, semantic output, rulebook hash, input hash,
and attestation bundle hash. Compatibility changes must keep existing corpus
fixtures replayable before they can ship. Use --candidate-rulebook,
--candidate-adapter, and --candidate-evaluator-version to test proposed
versioned migrations before routing production traffic to them. For release
gates, use --migration path/to/migration.json so expected drift and approval
status are machine-readable. The CLI validates the manifest against the
published closed JSON Schema before replay.
Current Production Boundary
mode: "rulebook" is the deterministic production evaluation path.
The legacy modes remain separate:
single: AI-assisted yes/no responsemulti: AI-assisted comparative scoringruntime: AI-assisted recommendation structure
Those modes must not be used as evidence that arbitrary business judgment is deterministic.
Implemented Public Boundary
The public Decision Record layer now:
- registers successful Rulebook v1 evaluations in a tenant-scoped immutable registry keyed by rulebook ID, version, and canonical hash
- rejects reuse of one rulebook ID/version with different content
- binds one rulebook ID/version to one evaluator version, so evaluator changes require an explicit rulebook version migration
- binds adapter-backed rulebooks to one adapter ID, version, manifest hash, and implementation hash
- stores the immutable snapshot, evaluator version, and adapter dependency with the ledger record
- defaults Rulebook v1 replay to historical mode using the stored canonical input and snapshot
- rejects caller input overrides and adapter-lineage drift during historical replay
- exposes exact tenant-scoped metadata lookup without listing or returning the stored rulebook body
- tests historical semantic reproduction through the public Decision Record endpoint
- powers the Krafthaus Solana Execution Gate without browser-local verdict logic
Compatibility Policy
Evaluator, rulebook, trusted-adapter, replay, and public response migrations are governed by Rulebook Compatibility Policy.
Worked evaluator, adapter, and rulebook changes are documented in Rulebook Migration Examples.
The current next contract work is to expand the corpus with customer-specific golden records as new production workflows are added.