AID-H-033.002: Policy-Preserving Failover & No Silent Safety Downgrade

Version 1.20261015 · Actionable sub-technique

Ensure failover does not silently weaken safety posture. A model or provider may only serve as fallback if it preserves the same required moderation, tool-use, approval, logging, retention, and allowed-capability constraints as the original route.

Pillars: app, infra

Lifecycle: building, operation

Scope boundary

Owns application-layer substitutability rules for fallback models and providers, ensuring required moderation, capability, approval, logging, retention, and compliance properties are preserved. It does not control network reachability.

AID-I-002.002: AID-H-033.002 decides whether an alternate reachable model or provider preserves the original safety envelope; AID-I-002.002 enforces which external destinations can be reached. Network approval does not make two providers policy-equivalent.

AID-H-033.005: AID-H-033.002 determines which fallback substitutions are eligible; AID-H-033.005 resolves the final route and blocks dispatch unless it matches the signed contract. Eligibility policy and last-mile enforcement are separately evidenced.

Implementation guidance

AID-H-033.002-G001

Define an explicit failover eligibility matrix, evaluate candidates through a deterministic route-profile checker, and fail closed if no fallback preserves the original route's safety and compliance envelope.
Concept:

Fallback is not a generic availability feature. Each primary route needs an explicit policy bundle that declares which fallback routes are eligible and which moderation, tool, logging, retention, and approval constraints must still hold. The gateway should emit one structured failover decision and block silent substitution when no candidate preserves that envelope.

Step 1: Define one failover policy bundle
{
  "routes": {
    "gpt-4.1-primary": {
      "eligible_fallbacks": ["gpt-4.1-backup-us", "gpt-4.1-backup-eu"],
      "required_constraints": {
        "moderation_profile": "strict",
        "tool_profile": "no_direct_shell",
        "log_profile": "forensic",
        "retention_class": "customer-default"
      },
      "override_mode": "explicit_operator_only"
    }
  },
  "route_profiles": {
    "gpt-4.1-backup-us": {
      "moderation_profile": "strict",
      "tool_profile": "no_direct_shell",
      "log_profile": "forensic",
      "retention_class": "customer-default"
    }
  }
}
Step 2: Evaluate candidates through a deterministic checker
# File: routing/failover_policy.py
from __future__ import annotations

import json
from dataclasses import dataclass
from pathlib import Path
from typing import Literal


BUNDLE = json.loads(Path("routing/failover_bundle.json").read_text(encoding="utf-8"))


@dataclass(frozen=True)
class FailoverDecision:
    decision: Literal["allow", "deny", "require_override"]
    chosen_route: str | None
    reason: str


def evaluate_failover(primary_route: str, candidate_routes: list[str]) -> FailoverDecision:
    policy = BUNDLE["routes"][primary_route]
    required = policy["required_constraints"]
    profiles = BUNDLE["route_profiles"]

    for candidate in candidate_routes:
        if candidate not in policy["eligible_fallbacks"]:
            continue
        profile = profiles.get(candidate, {})
        if all(profile.get(key) == value for key, value in required.items()):
            return FailoverDecision(
                decision="allow",
                chosen_route=candidate,
                reason="matched_policy_preserving_fallback",
            )

    if policy.get("override_mode") == "explicit_operator_only":
        return FailoverDecision(
            decision="require_override",
            chosen_route=None,
            reason="no_policy_preserving_fallback",
        )

    return FailoverDecision(
        decision="deny",
        chosen_route=None,
        reason="no_policy_preserving_fallback",
    )
Step 3: Enforce and log at the gateway
# File: routing/gateway_failover.py
from __future__ import annotations

import json
import logging

from routing.failover_policy import evaluate_failover

audit_logger = logging.getLogger("failover")


def select_route(primary_route: str, candidate_routes: list[str]) -> str:
    decision = evaluate_failover(primary_route, candidate_routes)
    audit_logger.warning(
        json.dumps(
            {
                "event_type": "failover_decision",
                "primary_route": primary_route,
                "candidate_routes": candidate_routes,
                "decision": decision.decision,
                "chosen_route": decision.chosen_route,
                "reason": decision.reason,
            }
        )
    )
    if decision.decision != "allow" or not decision.chosen_route:
        raise PermissionError(decision.reason)
    return decision.chosen_route
Operational notes

Action: Make every failover decision pass through a deterministic route-profile checker. Availability may degrade, but the gateway must not silently downgrade moderation, tool, logging, or retention guarantees.

Keep the action safely bounded

Reconcile the complete population of every fallback candidate and every retry or failover attempt for each eligible request; reject expired, revoked, or stale policy and asset bindings under the policy-defined freshness window.

Verify safely

A separately credentialed verifier independently replays candidate-profile comparison and effective route with missing field, weaker moderation, expanded tools, changed retention/region, stale health, chained fallback, and no-candidate fixtures, reads back effective state from the enforcement system, exercises positive, negative, boundary, stale-evidence, and dependency-failure fixtures, and reconciles every eligible item.

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.002: Policy-Preserving Failover & No Silent Safety Downgrade | AIDEFEND

Loading interactive view…

A Practical Knowledge Base for AI Security Defenses

Version