# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/how-should-an-instance-distinguish-a-federation-trust-boundary-rejection-from-a-transient-registry-routing-failure.md
# Remnant Warrant:    https://corpusfetch.com/c/how-should-an-instance-distinguish-a-federation-trust-boundary-rejection-from-a-transient-registry-routing-failure.warrant.json
# Markdown SHA-256:   5140a9ecf85f3258379d74af033ebb6b6b5ece0c9a52be6898956ef460140003
# Code AST SHA-256:   588372080085ae74d194217d7740e6eda85606b7b55e2f7b3b0adb737e8231c5
# Verified Classes:   FederationBoundaryError
# Defensive Guards:   2 fail-closed invariants (zero external deps)

class FederationBoundaryError(RuntimeError):
    """Raised when a federation failure cannot be safely classified as
    rejection vs. routing failure, or when retry semantics would be violated."""
    pass


def classify_federation_failure(response, anchor_cache) -> str:
    """Return 'rejection', 'routing', or raise FederationBoundaryError.

    The caller MUST NOT retry on 'rejection'. The caller MAY retry on
    'routing' only after refreshing the trust anchor.
    """
    # Layer-tagged signal is authoritative.
    evaluated = response.headers.get("X-Federation-Policy-Evaluated")
    if evaluated == "true":
        return "rejection"
    if evaluated == "false":
        return "routing"

    # Correlation ID resolution, if the fabric supports it.
    layer = response.correlation_layer()  # 'policy' | 'routing' | None
    if layer == "policy":
        return "rejection"
    if layer == "routing":
        return "routing"

    # No discriminating signal: conservative assumption, escalate.
    raise FederationBoundaryError(
        f"Ambiguous federation failure from {response.peer_registry}: "
        f"correlation_id={response.correlation_id}, status={response.status}. "
        "Cannot determine whether policy engine was reached; refusing to retry."
    )


def handle_federation_response(response, anchor_cache):
    try:
        kind = classify_federation_failure(response, anchor_cache)
    except FederationBoundaryError as exc:
        # Escalate; do not retry.
        raise FederationBoundaryError(str(exc)) from exc

    if kind == "rejection":
        # Record denial, adjust delegation scope, never retry.
        return {"action": "record_denial", "retry": False, "reason": response.policy_reason}

    # Routing failure: refresh anchor, then retry.
    anchor_cache.refresh(response.peer_registry)
    return {"action": "retry_after_refresh", "retry": True, "anchor": anchor_cache.get(response.peer_registry)}
