AID-H-033.005: Effective Route Resolution & Enforcement
Pillars: app, infra
Lifecycle: operation
Scope boundary
Owns final resolution and fail-closed enforcement of provider, account, model, deployment, endpoint, region, route, and fallback identity immediately before dispatch. It does not resolve sampling or other invocation parameters.
AID-H-033.001: AID-H-033.005 owns final route eligibility resolution and allow/deny; AID-H-033.001 owns protected immutable provenance and the declared durable acknowledgment prerequisite. This gate locally verifies signed policy and trusted final input; it never accepts eligibility from the recorder. Shared decision evidence cannot earn duplicate route enforcement and provenance credit.
AID-H-033.006: AID-H-033.005 enforces where and to which model the request is dispatched; AID-H-033.006 enforces the effective sampling, output, log-probability, and provider safety settings. Route identity and invocation configuration must be resolved independently after all translations.
AID-D-004.006: AID-H-033.005 blocks a disallowed effective route at dispatch; AID-D-004.006 independently reconciles observed routing and reports drift or missing evidence. Preventive enforcement does not self-certify complete runtime coverage.
AID-I-002.002: AID-H-033.005 enforces the approved application route; AID-I-002.002 enforces network reachability to external destinations. A route that passes one layer must still pass the other.
Implementation guidance
- AID-H-033.005-G001: Normalize the trusted gateway's final provider route after every alias, default, header override, retry, translation, and fallback step, and load only a verified route contract.
- AID-H-033.005-G002: Deny provider dispatch unless every route-owned field exactly matches one entry in the verified contract.
- AID-H-033.005-G003: Verify complete per-attempt route eligibility enforcement against independent egress/provider evidence and replay bypass/failure cases without double-scoring durable provenance or detector results.
AID-H-033.005-G001
Normalize the final route and verify its signed contract
A trusted post-resolution gateway adapter, never caller-supplied fields, emits the final provider, provider account, model, deployment, endpoint, region, route, and fallback decision. The contract consumes signed decisions from the sibling route controls and contains no prompt, tool, retrieval, filter, sampling, retention, or other invocation configuration.
Concrete configuration
{
"contract": {
"schema_version":"aidefend.effective-route-contract.v1",
"workload_id":"spiffe://example.org/ai/claims-agent",
"environment":"production",
"route_policy_sha256":"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
"routes":[{
"provider":"azure-openai",
"provider_account_id":"azure-openai-prod",
"model_id":"gpt-4o",
"deployment_id":"gpt-4o-prod",
"endpoint":"https://example.openai.azure.com",
"region":"eastus2",
"route_id":"primary-us",
"fallback_decision_id":"fd-20260717-0042"
}]
}
}Apply and capture evidence
set -euo pipefail
SNAPSHOT_DIR=$(mktemp -d)
trap 'rm -rf -- "$SNAPSHOT_DIR"' EXIT
POLICY_SNAPSHOT="$SNAPSHOT_DIR/effective-route-data.json"
SIGNATURE_SNAPSHOT="$SNAPSHOT_DIR/effective-route.sig"
install -m 0600 -- policy/effective-route-data.json "$POLICY_SNAPSHOT"
install -m 0600 -- policy/effective-route.sig "$SIGNATURE_SNAPSHOT"
cosign verify-blob --key keys/route-policy.pub --bundle "$SIGNATURE_SNAPSHOT" "$POLICY_SNAPSHOT"
jq -e '.contract.schema_version == "aidefend.effective-route-contract.v1" and (.contract.workload_id|type=="string" and length>0) and (.contract.environment|type=="string" and length>0) and (.contract.route_policy_sha256|test("^[0-9a-f]{64}$")) and (.contract.routes|length>0) and ([.contract.routes[].route_id]|length == ([.contract.routes[].route_id]|unique|length))' "$POLICY_SNAPSHOT"
POLICY_SHA256=$(sha256sum "$POLICY_SNAPSHOT" | cut -d' ' -f1)
SIGNATURE_SHA256=$(sha256sum "$SIGNATURE_SNAPSHOT" | cut -d' ' -f1)
printf '%s %s\n%s %s\n' "$POLICY_SHA256" policy/effective-route-data.json "$SIGNATURE_SHA256" policy/effective-route.sig > evidence/effective-route-contract.sha256Independent verification
A gateway-independent identity verifies the signature, reads back the active normalizer and contract digest, then exercises direct, alias, gateway-default, route-header, retry, provider-translation, and fallback paths. Every path must emit the same complete route-owned field set after final resolution.
set -euo pipefail
SNAPSHOT_DIR=$(mktemp -d)
trap 'rm -rf -- "$SNAPSHOT_DIR"' EXIT
POLICY_SNAPSHOT="$SNAPSHOT_DIR/effective-route-data.json"
SIGNATURE_SNAPSHOT="$SNAPSHOT_DIR/effective-route.sig"
install -m 0600 -- policy/effective-route-data.json "$POLICY_SNAPSHOT"
install -m 0600 -- policy/effective-route.sig "$SIGNATURE_SNAPSHOT"
cosign verify-blob --key keys/route-policy.pub --bundle "$SIGNATURE_SNAPSHOT" "$POLICY_SNAPSHOT"
EXPECTED_CONTRACT_SHA256=$(sha256sum "$POLICY_SNAPSHOT" | cut -d' ' -f1)
jq -e --arg contract_sha256 "$EXPECTED_CONTRACT_SHA256" '.contract_sha256 == $contract_sha256 and .normalizer_source == "trusted_post_resolution_adapter" and (.effective | keys | sort) == (["deployment_id","endpoint","fallback_decision_id","model_id","provider","provider_account_id","region","route_id"] | sort)' evidence/effective-route-input.jsonFailure handling
An unverified or stale bundle, caller-supplied effective field, unknown or missing field, normalization ambiguity, sibling-decision mismatch, or normalizer/verification error denies dispatch before any provider connection; the gateway cannot silently use its own default.
Canonical per-attempt producer binding
Use stable invocation identity and a distinct attempt identity for each retry/fallback. Bind the verified full contract digest and version, final route, application/version/gateway, and exact predecessor attempt in H-033.001's aidefend.route-ledger-event.v2 DECISION event. Its aidefend.route-decision.v3 projection retains those source bindings plus the exact durable-intent event digest. Record the active normalizer version and authenticated deployment readback separately, bound to the same application/version/gateway and verified contract digest; the DECISION event and projection do not carry a normalizer-version field. Retain the originally requested model in independent ingress. The requested model is not the authorized effective route and need not equal an approved alias or provider model ID.
AID-H-033.005-G002
Enforce the resolved route immediately before dispatch
The policy evaluates only trusted post-resolution input and uses exact equality for all route-owned fields. It has no permissive fallback and must execute at the last gateway or router before the provider connection is created.
Concrete configuration
package aidefend.effective_route
import rego.v1
default allow := false
route_fields := {"provider","provider_account_id","model_id","deployment_id","endpoint","region","route_id","fallback_decision_id"}
allow if {
input.schema_version == "aidefend.effective-route-input.v1"
object.keys(input.effective) == route_fields
input.workload_id == data.contract.workload_id
input.environment == data.contract.environment
input.route_policy_sha256 == data.contract.route_policy_sha256
some route in data.contract.routes
object.keys(route) == route_fields
every field in route_fields {
is_string(route[field])
route[field] != ""
is_string(input.effective[field])
input.effective[field] != ""
}
route.provider == input.effective.provider
route.provider_account_id == input.effective.provider_account_id
route.model_id == input.effective.model_id
route.deployment_id == input.effective.deployment_id
route.endpoint == input.effective.endpoint
route.region == input.effective.region
route.route_id == input.effective.route_id
route.fallback_decision_id == input.effective.fallback_decision_id
}Apply and capture evidence
set -euo pipefail
umask 077
test -n "$VERIFIED_H033_OPA_TIMEOUT_SECONDS"
[[ "$VERIFIED_H033_OPA_TIMEOUT_SECONDS" =~ ^[1-9][0-9]*$ ]]
SNAPSHOT_DIR=$(mktemp -d)
chmod 0700 "$SNAPSHOT_DIR"
trap 'rm -rf -- "$SNAPSHOT_DIR"' EXIT
install -m 0400 -- policy/effective-route-data.json "$SNAPSHOT_DIR/effective-route-data.json"
install -m 0400 -- policy/effective-route.sig "$SNAPSHOT_DIR/effective-route.sig"
install -m 0400 -- keys/route-policy.pub "$SNAPSHOT_DIR/route-policy.pub"
install -m 0400 -- policy/effective-route.rego "$SNAPSHOT_DIR/effective-route.rego"
install -m 0400 -- evidence/effective-route-input.json "$SNAPSHOT_DIR/effective-route-input.json"
timeout --signal=KILL "$VERIFIED_H033_OPA_TIMEOUT_SECONDS" cosign verify-blob \
--key "$SNAPSHOT_DIR/route-policy.pub" --bundle "$SNAPSHOT_DIR/effective-route.sig" \
"$SNAPSHOT_DIR/effective-route-data.json"
timeout --signal=KILL "$VERIFIED_H033_OPA_TIMEOUT_SECONDS" opa check "$SNAPSHOT_DIR/effective-route.rego"
OPA_RESULT=$(timeout --signal=KILL "$VERIFIED_H033_OPA_TIMEOUT_SECONDS" opa eval --fail --format raw \
--data "$SNAPSHOT_DIR/effective-route.rego" --data "$SNAPSHOT_DIR/effective-route-data.json" \
--input "$SNAPSHOT_DIR/effective-route-input.json" \
'data.aidefend.effective_route.allow == true')
test "$OPA_RESULT" = trueIndependent verification
For each negative fixture, require the equality query to fail and prove zero provider dispatch in gateway egress records. Cover wrong provider/account/model/deployment/endpoint/region/route/fallback, missing and extra fields, header override, fallback activation, stale signature, and unavailable OPA.
set -euo pipefail
umask 077
test -n "$VERIFIED_H033_OPA_TIMEOUT_SECONDS"
[[ "$VERIFIED_H033_OPA_TIMEOUT_SECONDS" =~ ^[1-9][0-9]*$ ]]
SNAPSHOT_DIR=$(mktemp -d)
chmod 0700 "$SNAPSHOT_DIR"
trap 'rm -rf -- "$SNAPSHOT_DIR"' EXIT
install -m 0400 -- policy/effective-route-data.json "$SNAPSHOT_DIR/effective-route-data.json"
install -m 0400 -- policy/effective-route.sig "$SNAPSHOT_DIR/effective-route.sig"
install -m 0400 -- keys/route-policy.pub "$SNAPSHOT_DIR/route-policy.pub"
install -m 0400 -- policy/effective-route.rego "$SNAPSHOT_DIR/effective-route.rego"
timeout --signal=KILL "$VERIFIED_H033_OPA_TIMEOUT_SECONDS" cosign verify-blob \
--key "$SNAPSHOT_DIR/route-policy.pub" --bundle "$SNAPSHOT_DIR/effective-route.sig" \
"$SNAPSHOT_DIR/effective-route-data.json"
for fixture in wrong-provider wrong-account wrong-model wrong-deployment wrong-endpoint wrong-region wrong-route wrong-fallback missing-field extra-field; do
install -m 0400 -- "evidence/fixtures/$fixture.json" "$SNAPSHOT_DIR/$fixture.json"
set +e
timeout --signal=KILL "$VERIFIED_H033_OPA_TIMEOUT_SECONDS" opa eval --fail --format raw \
--data "$SNAPSHOT_DIR/effective-route.rego" --data "$SNAPSHOT_DIR/effective-route-data.json" \
--input "$SNAPSHOT_DIR/$fixture.json" \
'data.aidefend.effective_route.allow == true' >/dev/null
rc=$?
set -e
test "$rc" -eq 1
doneFailure handling
OPA, normalizer, contract, signature, or policy unavailability; a stale bundle; any unknown/missing field; or any mismatch returns deny before dispatch. A gateway default is never a recovery path for an enforcement error.
Bind this gate to the canonical route ledger without granting duplicate credit
The trusted adapter runs the signature and exact OPA evaluation above locally for each final route, including each retry and fallback. Capture and hold the exact verified bytes, final serialized route, policy version, workload, and deployment identity through dispatch; the signing key, Rego, normalizer, freshness/revocation policy, and service configuration are root-controlled. A boolean supplied by the caller, a record in H-033.001, or a telemetry flag is never eligibility evidence. Signature verification alone does not establish active freshness or revocation; enforce the versioned deployment policy and independently read back active key, contract digest, normalizer version, and OPA artifact.
After evaluation, append one DECISION through H-033.001's authenticated local recorder: bind invocation_id, unique attempt_id, exact previous_attempt_id, decision_id, boolean eligibility result, all eight effective fields, routing-policy version, and SHA-256 of the exact locally verified contract bytes. Keep contract.route_policy_sha256 (the upstream policy reference) distinct from this verified file digest. For a deny, terminate without provider dispatch and independently observe that denial. For an allow, require a new durably acknowledged INTENT and call guarded_dispatch with its expected event ID and the existing transport bound to that exact serialized request. Recorder outage, full storage, outbox failure, lost acknowledgment, or replayed intent stops the send even when OPA allows the route. Eligibility remains owned and credited here; immutable record custody and durability remain owned and credited by .001. A discovered drift can invalidate enforcement coverage without awarding or deducting a second provenance outcome.
AID-H-033.005-G003
Prove complete route enforcement across multiple attempts
Evaluate the eligibility objective, including direct requests, approved alias expansion, gateway defaults, caller route headers, provider translation, retry, fallback, and every relevant application/version/gateway surface. In a versioned test profile, vary each of the eight route fields, unauthorized policy/key, stale or revoked contract, unknown/missing fields, normalizer/OPA failures, and post-evaluation mutation. Independently prove that disallowed routes produce zero provider sends and allowed, unmodified routes can dispatch; an allowed route can still remain unsent because transport or durable-intent prerequisites fail. Do not treat a legitimate transport failure as evidence of a disallowed-route bypass or require exactly one attempt for an entire invocation.
Use v3 window receipts and decision projections over v2 policy and ledger schemas
Keep the common module from H-033.001 installed as a root-controlled shared dependency. Its verify_window captures stable regular files, verifies their exact captured bytes with actual Cosign, and evaluates those same bytes. Supply policy.json, inventory.json, receipt.json, ingress.jsonl, decisions.jsonl, gateway.jsonl, provider.jsonl, and ledger.json, each with a same-basename .bundle.json and a separately authorized <label>.pub under the key root. Do not replace cryptographic verification with a signature_verified boolean or reread mutable live files after verification.
The signed observation policy is aidefend.route-observation-policy.v2: exact application/version/gateway subject; exact expected canonical recorder-policy SHA-256; approved routing-policy version-to-file-digest map; environment-defined freshness, future skew, and minimum invocation count. The signed aidefend.route-architecture-inventory.v2 binds that same subject and actual gateway_present. The signed aidefend.route-window-receipt.v3 binds subject, window ID/start/end, exact policy/inventory hashes, independently enumerated expected invocation IDs, closed status, and each source's exact digest, row count, authenticated collection completeness, and first/next native cursor. The window closer must obtain these cursors and closure from the actual collector/source protocol; counting its own produced rows or setting booleans cannot prove completeness. A missing source, native readback, or applicable observation stays a visibility gap. A signed absence of the gateway architecture can establish inapplicability; collector outage cannot.
Ingress rows use aidefend.trusted-route-ingress.v2 and invocation/requested-model/time. Decision rows come from the ledger's aidefend.route-decision.v3 projection and bind each invocation/attempt/predecessor, exact decision digest, source application/version/gateway and canonical recorder-policy digest, routing-policy file digest, eligibility, eight fields, decision time, and durable_intent_sha256. That field is the exact committed INTENT event digest, or null when no such event exists; never fill it from an eligibility result, gateway claim, record count, or provider observation. Call project_decisions(export, window_id, expected_subject=policy["subject"], expected_recorder_policy_sha256=policy["recorder_policy_sha256"], invocation_ids=receipt["expected_invocation_ids"]) with the independently verified observation policy. A witnessed dispatch with null intent is dispatched_without_durable_intent even when all route fields match. These source identity bindings must exactly match the signed observation policy rather than being re-labeled by the new window receipt. Independent gateway rows bind window/invocation/attempt, outcome, actual eight fields (absent for non-dispatch/unknown), provider request ID, observation time, and decision digest. Provider/network readback rows bind window/invocation/attempt, provider request ID, observation time, and actual provider/account/model/deployment/endpoint/region. Unsupported provider visibility produces a gap; do not fill actual values from the planned decision. The schema and field checks are executable in the shared module, not an assessment engine envelope.
Replay the signed route evidence and interpret the measured effect
# File: detection/verify_route_window.py
from __future__ import annotations
import argparse
from datetime import datetime, timezone
import os
from pathlib import Path
from gateway.route_ledger import canonical, timestamp, verify_window
parser = argparse.ArgumentParser()
parser.add_argument("--input-root", type=Path, required=True)
parser.add_argument("--key-root", type=Path, required=True)
parser.add_argument("--output", type=Path, required=True)
parser.add_argument("--verify-timeout-seconds", type=float, required=True)
parser.add_argument("--snapshot-max-bytes", type=int, required=True)
parser.add_argument("--evaluation-time")
args = parser.parse_args()
clock = datetime.now(timezone.utc)
try:
if args.evaluation_time:
clock = timestamp(args.evaluation_time)
result = verify_window(args.input_root, args.key_root,
args.verify_timeout_seconds, args.snapshot_max_bytes, clock)
except Exception as error:
result = {"window_result": "PROCESSING_ERROR", "error_class": type(error).__name__,
"evaluated_at": clock.isoformat(), "findings": [], "coverage_gaps": []}
raw = canonical(result) + b"\n"
args.output.parent.mkdir(parents=True, exist_ok=True)
# Each result is a new artifact; never overwrite a retained measurement.
descriptor = os.open(args.output, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600)
with os.fdopen(descriptor, "wb") as output:
output.write(raw); output.flush(); os.fsync(output.fileno())
if args.output.read_bytes() != raw:
raise OSError("result readback differs")
# CLI success means a new result was persisted and read back, never a clean window.
# Detection/alert classification MUST inspect result["window_result"].
raise SystemExit(0)
Run the verifier as a separate identity with the deployment's signed deadlines and byte caps. An independent evidence owner reads back the active gate/normalizer/contract and the exact signed snapshots, verifies all bundles, and replays the recorded evaluation time. Reconcile the complete independent ingress set and all attempt/fallback chains, including deny, non-dispatch, unknown dispatch, duplicated IDs, hidden downstream sends, mismatched decision digest, and missing provider readback. Retain measured cases, input hashes, tested software/configuration/profile, results, and readback evidence. The same signed observation can substantiate the enforcement claim here; H-033.001 separately establishes protected provenance custody. D-004.006 earns detection assurance only when adversarial cases produce the required findings/alerts and benign approved substitutions avoid false alerts. Re-running a comparator or a no-drift window gives no additional detector effectiveness credit.
Supply all eight independently authenticated window inputs, including ledger.json and its separately protected recorder-attestation signature. The v3 receipt covers ledger event count/cursors/completeness and exact digest. verify_window rejects reuse of the ledger public key for decisions, receipt, gateway or provider signing. It verifies the complete ledger chain, calls project_decisions(..., invocation_ids=receipt["expected_invocation_ids"]) and compares the canonical projection to decisions.jsonl. A disagreement produces decision_projection_differs_from_protected_ledger, including a fabricated intent hash or a decision hash masquerading as an intent hash. The projection remains v3; ledger events/export remain v2. Missing independent ledger evidence cannot support a clean window.
The window evaluator also checks attested OBSERVED DISPATCHED and FINAL VIOLATION events for the independently enumerated invocation IDs. A dispatch missing from the gateway snapshot, conflicting observed route/provider identity, or retained violation remains a finding even when the decision projection matches. Events for other invocation populations do not taint this window; a later witness for this population still invalidates a clean claim.
Snapshot capacity: this v2 ledger exporter and verifier require the complete protected segment from sequence 1. Paging bounds each frame, not the total snapshot or verification cost. An export exceeding the signed snapshot ceiling produces a processing/capacity fault; never truncate history, raise the ceiling without reviewing resources, or treat that fault as a clean window. Automatic rotation and cross-segment checkpoint verification are not implemented here. Use an externally qualified segmented recorder/verifier with signed continuity anchors for sustained high-volume service, or bound and close this reference segment within the deployment profile. Keep every unresolved invocation and outbox record recoverable across a segment transition.
Reconcile the latest protected-ledger observation for each attempt and latest FINAL for each invocation in the independently enumerated window population. A ledger NOT_DISPATCHED conflicting with an actual gateway dispatch is a finding. Missing ledger observation, latest UNKNOWN, or latest UNRESOLVED FINAL is a visibility gap even when gateway/provider snapshots report dispatch. A later independently retained resolution replaces an earlier UNKNOWN or UNRESOLVED checkpoint; historical dispatched evidence and violations remain findings. Complete agreement is required for a clean local window observation, and confirmed findings survive other visibility gaps.
Open-source tools
- LiteLLM
- Envoy
- Open Policy Agent (OPA)
- OpenTelemetry
- Cosign
Commercial / hosted tools
- Cloudflare AI Gateway
- Prisma AIRS AI Gateway (formerly Portkey; managed gateway integration)
- Azure API Management
Threat mappings
MITRE ATLAS
- AML.T0010 AI Supply Chain Compromise (blocks dispatch when the resolved route is outside the verified signed route contract)
MAESTRO
- Integration Risks (L7) (blocks dispatch when the resolved route is outside the verified signed route contract)
- Data Exfiltration (L2) (blocks dispatch when the resolved route is outside the verified signed route contract)
- Supply Chain Attacks (Cross-Layer) (blocks dispatch when the resolved route is outside the verified signed route contract)
OWASP LLM Top 10 2026
- LLM02:2026 Sensitive Information Disclosure
- LLM04:2026 Supply Chain
OWASP ML Top 10 2023
- ML06:2023 AI Supply Chain Attacks (blocks dispatch when the resolved route is outside the verified signed route contract)
OWASP Top 10 for Agentic Applications 2026
- ASI04:2026 Agentic Supply Chain Vulnerabilities (blocks dispatch when the resolved route is outside the verified signed route contract)
NIST Adversarial Machine Learning 2025
- N/A
Cisco Integrated AI Security and Safety Framework
- AISubtech-14.1.2 Insufficient Access Controls (Enforces the stated application access boundary; hosting infrastructure is a separate scope)
- AITech-8.2 Data Exfiltration / Exposure
- AITech-8.3 Information Disclosure
Google Secure AI Framework 2.0 - Risks
- IIC: Insecure Integrated Component (blocks dispatch when the resolved route is outside the verified signed route contract)
- SDD: Sensitive Data Disclosure (blocks dispatch when the resolved route is outside the verified signed route contract)
Databricks AI Security Framework 3.0
- Model Serving - Inference requests 9.10: Accidental exposure of unauthorized data to models (blocks dispatch when the resolved route is outside the verified signed route contract)
- Operations 11.1: Lack of MLOps - repeatable enforced standards (blocks dispatch when the resolved route is outside the verified signed route contract)