# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/what-structural-signals-indicate-a-capability-grant-has-silently-outlived-its-jurisdictional-basis-in-cross-org-agent-federation.md
# Remnant Warrant:    https://corpusfetch.com/c/what-structural-signals-indicate-a-capability-grant-has-silently-outlived-its-jurisdictional-basis-in-cross-org-agent-federation.warrant.json
# Markdown SHA-256:   6840c3447165405734d8a985803e3f6cf2330983012bfc7d22736db9670c37a6
# Code AST SHA-256:   f158dee26e165ec53fe3b4844ceccf3fedde5d02e6683cd344d97d1a79287324
# Verified Classes:   JurisdictionalAdmissibilityError, FederatedGrant
# Defensive Guards:   4 fail-closed invariants (zero external deps)

from __future__ import annotations

from dataclasses import dataclass
from datetime import datetime, timedelta


class JurisdictionalAdmissibilityError(RuntimeError):
    """Raised when a federated capability verifies but is jurisdictionally void."""


@dataclass(frozen=True)
class FederatedGrant:
    grant_id: str
    issuer_org: str
    grantee_org: str
    scope: str
    policy_version: int
    issued_at: datetime
    ttl: timedelta
    residency_predicate: str | None          # e.g. "agent_region in EU"
    per_invocation_attestation: bool         # does the grant require attested region per call?
    attestation_digest_pinned: bool          # is the grant bound to an attestation digest?
    shortest_predicate_ttl: timedelta | None # TTL of the shortest justifying predicate


def assert_admissible(
    grant: FederatedGrant,
    *,
    now: datetime,
    invoking_agent_region: str,
    required_region_set: frozenset[str],
) -> None:
    """Fail closed if a grant outlives its jurisdictional basis."""

    if now > grant.issued_at + grant.ttl:
        raise JurisdictionalAdmissibilityError(
            f"grant {grant.grant_id} expired at {grant.issued_at + grant.ttl}"
        )

    if grant.residency_predicate is None:
        return  # no residency obligation; capability-only grant

    # The grant claims a residency precondition. Verify it is actually enforceable.
    if not grant.per_invocation_attestation and not grant.attestation_digest_pinned:
        raise JurisdictionalAdmissibilityError(
            f"grant {grant.grant_id} carries residency predicate "
            f"{grant.residency_predicate!r} but has no per-invocation attestation "
            f"and no pinned attestation digest; jurisdiction cannot be confirmed "
            f"for scope {grant.scope!r}"
        )

    if (
        grant.shortest_predicate_ttl is not None
        and grant.ttl > grant.shortest_predicate_ttl
    ):
        raise JurisdictionalAdmissibilityError(
            f"grant {grant.grant_id} TTL {grant.ttl} exceeds shortest predicate "
            f"TTL {grant.shortest_predicate_ttl}; grant may outlive its basis"
        )

    if invoking_agent_region not in required_region_set:
        raise JurisdictionalAdmissibilityError(
            f"agent region {invoking_agent_region!r} outside admissible set "
            f"{sorted(required_region_set)} for grant {grant.grant_id}"
        )
