Evidence Flow + Execution Model
At a Glance
What: How Decision Gate evaluates evidence and produces decisions Why: Understand exactly what is fetched, validated, and compared Who: Developers, security teams, and architects integrating Decision Gate Prerequisites: getting_started.md
One Sentence You Must Remember
Decision Gate evaluates evidence; it does not execute tasks.
Core Data Flow
Trigger (scenario_next / scenario_trigger / precheck)
|
+-> Collect or accept evidence
| - Live run: call providers
| - Precheck: accept asserted payload
|
+-> Trust enforcement
| - Trust lane minimum (min_lane)
| - Signature policy (if required)
| - Anchor validation (if configured)
|
+-> Comparator evaluation -> TriState
+-> RET evaluation -> Gate outcomes
|
+-> Decision
- Live run: state mutation + runpack storage
- Precheck: no state mutation
Evidence Sources
1) Providers (Live Runs)
Providers fetch or compute evidence and return an EvidenceResult.
Built-in providers: time, env, json, http
External providers: MCP servers called via tools/call with evidence_query.
2) Asserted Evidence (Precheck)
Precheck does not call providers. The client supplies a payload that is:
- Validated against a registered data shape (JSON Schema).
- Converted into asserted
EvidenceResultvalues.
Payload mapping is exact:
- If payload is an object: keys are condition IDs.
- If payload is not an object: it is only accepted when the scenario has exactly one condition.
Trust Enforcement
Trust Lanes
Verified: evidence returned by providers.Asserted: evidence supplied via precheck payload.
Minimum Lane (min_lane)
Configured in decision-gate.toml:
[trust]
min_lane = "verified" # or "asserted"
When min_lane = "verified", asserted evidence is rejected (condition becomes unknown).
Dev-permissive: min_lane becomes asserted automatically, except for providers listed in dev.permissive_exempt_providers (those remain strict).
Per-Condition and Per-Gate Overrides
You can raise the minimum lane in the scenario spec:
{
"condition_id": "tests_ok",
"trust": { "min_lane": "verified" }
}
Gate-level trust can also raise requirements. Effective requirement is the stricter of base and overrides.
Signature Verification
Configured via trust.default_policy:
[trust]
# Audit mode accepts unsigned evidence.
default_policy = "audit"
# Require signatures from key files:
# default_policy = { require_signature = { keys = ["/etc/decision-gate/keys/provider.pub"] } }
When require_signature is active:
EvidenceResult.signature.schememust be"ed25519".signature.key_idmust match a configured key entry.- The signature is verified over canonical JSON of
evidence_hash.
If evidence_hash is missing, Decision Gate computes it from the evidence value.
If evidence_hash is present, it must match the canonical hash of the evidence
value or the provider response is rejected.
Anchor Validation
Anchors are enforced via config (not the scenario spec):
[anchors]
[[anchors.providers]]
provider_id = "json"
anchor_type = "file_path_rooted"
required_fields = ["root_id", "path"]
EvidenceResult.evidence_anchor.anchor_value must be a string containing canonical JSON that parses to an object. Required fields must exist and must be scalar (string/number). Violations produce error.code = "anchor_invalid" and the condition becomes unknown. For file_path_rooted, path is relative to the configured provider root.
Comparator Evaluation
Comparators produce TriState results:
truefalseunknown
Important exact behaviors (see condition_authoring.md):
equals/not_equalsreturn false/true on type mismatch (notunknown).- Ordering comparators (
greater_than, etc.) returnunknownunless both sides are numbers or RFC3339 date/time strings. exists/not_existstest presence ofEvidenceResult.value; JSONnullstill counts asexists.
Live Run Flow (scenario_next)
- A run exists (
scenario_start). scenario_nextis called withrun_id,tenant_id,namespace_id,trigger_id,agent_id, andtime.- Decision Gate calls providers for each condition.
- Trust requirements are enforced.
- Comparators and RET produce gate outcomes.
- A
DecisionRecordis returned and the run state is updated.
Output: NextResult { decision, packets, status } (no evidence values).
To inspect evidence and gate details, use runpack_export.
Precheck Flow (precheck)
- Client calls
schemas_registerto register a data shape. - Client calls
precheckwith:tenant_id,namespace_idscenario_idor inlinespecdata_shape(schema id + version)payload
- Payload is validated against the schema.
- Payload is converted into asserted evidence.
- Gates are evaluated without mutating run state.
Output: PrecheckToolResponse { decision, gate_evaluations }.
gate_evaluations includes only gate status and condition trace (no evidence values).
Audit Submissions (scenario_submit)
scenario_submit appends a submission record to the run state without affecting gate evaluation. Each submission stores a content hash and metadata for audit.
Provider Interaction (External MCP)
Decision Gate calls external MCP providers with tools/call and a single tool: evidence_query. It does not depend on tools/list at runtime; provider capabilities are loaded from capabilities_path in config.
Common Misconceptions (Corrected)
- “DG runs the tools.” -> False. DG evaluates evidence; tools run elsewhere.
- “Precheck returns evidence errors.” -> False. It returns
decision+gate_evaluationsonly. - “scenario_next response includes evidence.” -> False by default. Local-only requests default to
tracefeedback, but evidence values still requirefeedback: "evidence"(if permitted) orrunpack_export/evidence_query. - “Anchor policy is in the scenario.” -> False. It is configured under
[anchors].
Glossary
EvidenceQuery: { provider_id, check_id, params }.
EvidenceResult: { value, lane, error, evidence_hash, evidence_ref, evidence_anchor, signature, content_type }.
Trust Lane: verified or asserted.
Runpack: Audit artifact bundle written for live runs.