Skip to content

Decisions & Routing

Every WCP dispatch begins with a RouteInput and ends with a RouteDecision. Nothing executes without a decision. Nothing is denied without a reason. Every decision is recorded.

RouteInput

RouteInput is the capability request envelope sent to the Hall. All six required fields must be present — the Hall rejects requests with empty or missing values.

FieldTypeRequiredDescription
capability_idstryesThe WCP capability requested, e.g. cap.doc.summarize
envdev | stage | prod | edgeyesDeployment environment
data_labelPUBLIC | INTERNAL | RESTRICTEDyesData sensitivity classification
tenant_risklow | medium | highyesRisk tier of the requesting tenant
qos_classP0 | P1 | P2 | P3yesQuality of Service priority
tenant_idstryesIdentifier of the requesting tenant. Must be non-empty.
correlation_idstryesUUID v4. Propagated through all downstream calls.
requestdictnoArbitrary payload for the target worker
blast_scoreintnoPre-computed blast score. Router computes it if absent.
blast_radiusdictnoPre-computed blast radius dimensions
privilege_contextdictnoPrivilege context for envelope enforcement
dry_runboolnoIf true, full decision is made but no worker executes
tenant_credentialstrnoSigned WCP credential (v0.2+)

QoS classes:

  • P0 — critical, maximum governance, human escalation may be required
  • P1 — high priority, full governance
  • P2 — standard, default governance
  • P3 — background, relaxed governance
from pyhall.models import RouteInput
import uuid
inp = RouteInput(
capability_id="cap.doc.summarize",
env="prod",
data_label="INTERNAL",
tenant_risk="low",
qos_class="P1",
tenant_id="org.acme",
correlation_id=str(uuid.uuid4()),
request={"document_id": "doc-1234"},
)

Routing Flow

The Hall processes a RouteInput through a fixed pipeline:

1. Validate RouteInput fields (tenant_id non-empty, correlation_id present)
2. Match first routing rule by capability_id + env + data_label
└─ No match → DENY (code: DENY_NO_WORKER) — fail closed
3. Check preconditions (correlation_id enforced, policy version propagated)
4. Verify declared controls against registry
└─ Required control missing → DENY (code: DENY_CONTROL_MISSING)
5. Compute blast score (or use pre-computed value)
└─ Score exceeds threshold → DENY (code: DENY_BLAST_EXCEEDED)
6. Evaluate policy gate
└─ REQUIRE_HUMAN → STEWARD_HOLD (supervisor_required: true)
7. Select first available worker candidate matching species
└─ No worker available → DENY (code: DENY_NO_WORKER)
8. Optional: verify worker code attestation (if require_worker_attestation: true)
└─ Hash mismatch → DENY (code: DENY_WORKER_TAMPERED)
9. Emit three mandatory telemetry events
10. Return RouteDecision

RouteDecision

RouteDecision is the evidence receipt returned by the Hall. It is populated for every dispatch — allowed, denied, or held.

FieldTypeDescription
decision_idstrUUID v4 identifying this specific decision
timestampstrISO 8601 UTC timestamp
correlation_idstrPropagated from RouteInput.correlation_id
tenant_idstrPropagated from RouteInput.tenant_id
capability_idstrThe capability that was requested
matched_rule_idstrThe routing rule that matched. NO_MATCH if none.
selected_worker_species_idstr | NoneSet on DISPATCH. Null on DENY.
envEnvPropagated from input
data_labelDataLabelPropagated from input
tenant_riskTenantRiskPropagated from input
qos_classQoSClassPropagated from input
deniedbooltrue if dispatch was denied
deny_reason_if_denieddict | NoneStructured deny reason (code + message)
required_controls_effectivelist[str]Controls that were verified
recommended_profiles_effectivelist[dict]Suggested profiles for this dispatch
escalation_effectiveEscalationEscalation policy that applied
preconditions_checkedPreconditionsCheckedWhich preflight checks ran
artifact_hashstr | NoneSHA-256 of the serialized RouteInput
worker_attestation_checkedboolWhether code attestation was verified
worker_attestation_validbool | Nonetrue = matched. false = tampered. None = not checked.
dry_runbooltrue if this was a dry-run decision
telemetry_envelopeslist[dict]Mandatory WCP telemetry events

Outcomes

DISPATCH — all checks passed. denied: false, selected_worker_species_id is set. The caller dispatches the returned worker species.

DENY — a check failed. denied: true, deny_reason_if_denied carries the deny code and human-readable message. No worker is dispatched.

STEWARD_HOLD — the policy gate returned REQUIRE_HUMAN. denied: true, deny_reason_if_denied["code"] = "DENY_REQUIRES_HUMAN_APPROVAL", deny_reason_if_denied["supervisor_required"] = true. Callers must check deny_reason_if_denied["code"] == "DENY_REQUIRES_HUMAN_APPROVAL" to detect STEWARD_HOLD specifically. Execution is held pending human approval via the configured H2A channel.

Deny Codes

Every denial includes a structured deny_reason_if_denied with a code field:

CodeCause
DENY_NO_WORKERNo routing rule matched the capability, or no enrolled worker is available for the matched species
DENY_POLICY_BLOCKPolicy gate evaluated and blocked dispatch based on risk tier, data label, or tenant risk
DENY_WORKER_TAMPEREDWorker code attestation check failed — hash mismatch between registered and current code
DENY_CONTROL_MISSINGA required control declared in the routing rule is not present in the registry
DENY_BLAST_EXCEEDEDComputed blast score exceeds the maximum allowed for this environment
DENY_UNKNOWN_TENANTrequire_signatory: true is set and the tenant_id is not in the registered signatory list
DENY_EMPTY_TENANT_IDtenant_id was empty or whitespace
decision = make_decision(inp, rules, controls_present, worker_available)
if decision.denied:
reason = decision.deny_reason_if_denied
print(f"Code: {reason['code']}")
print(f"Message: {reason['message']}")

Correlation IDs

The correlation_id is the backbone of WCP’s evidence chain. It originates in the RouteInput and propagates through:

  • All three mandatory telemetry events (evt.os.task.routed, evt.os.worker.selected, evt.os.policy.gated)
  • The RouteDecision itself
  • All downstream worker calls (the worker is responsible for propagating it)

This creates a traceable chain from the original capability request to every downstream action the worker takes. When something goes wrong, the correlation_id lets you reconstruct exactly what happened and in what order.

Idempotency. The same correlation_id submitted twice (when worker state is unchanged) produces the same RouteDecision. This makes dispatch safe to retry — if the network drops after you send the request but before you receive the response, resubmitting with the same correlation_id is safe.

Decision Log

Every RouteDecision — allowed and denied — is recorded. The artifact_hash in the decision is a SHA-256 of the serialized RouteInput, proving what was actually routed. Combined with the telemetry chain and correlation propagation, this creates a complete, auditable record of every governance decision the Hall made.

This record is the foundation of WCP’s attestation model: in a post-incident review or litigation, you can prove exactly what ran, when, under what policy, with what controls verified, and whether the worker’s code matched what was originally enrolled.