AID-H-033.005: Effective Route Resolution & Enforcement

Version 1.20261015 · Actionable sub-technique

At the last trusted AI gateway or model router, derive the effective route after all caller aliases, gateway defaults, route headers, retries, provider translations, and fallback selection, then deny dispatch unless the resolved provider, provider account, model, deployment, endpoint, region, route, and fallback exactly match a verified signed route contract. Route eligibility is decided locally for each dispatch attempt; H-033.001 separately supplies protected durable intent acknowledgment and canonical attempt evidence. Approved alias expansion and fallback are allowed only when the final resolved route remains exactly bound to the active verified contract.

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.
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.sha256
Independent 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.json
Failure 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

Deny provider dispatch unless every route-owned field exactly matches one entry in the verified contract.
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" = true
Independent 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
done
Failure 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

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.
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

Commercial / hosted tools

Threat mappings

MITRE ATLAS

MAESTRO

OWASP LLM Top 10 2026

OWASP ML Top 10 2023

OWASP Top 10 for Agentic Applications 2026

NIST Adversarial Machine Learning 2025

Cisco Integrated AI Security and Safety Framework

Google Secure AI Framework 2.0 - Risks

Databricks AI Security Framework 3.0

AID-H-033.005: Effective Route Resolution & Enforcement | AIDEFEND

Loading interactive view…

A Practical Knowledge Base for AI Security Defenses

Version