# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/in-what-scenarios-must-an-instance-refuse-to-treat-a-did-document-s-alsoknownas-as-a-transitive-trust-bridge-during-cross-org-agent-federation.md
# Remnant Warrant:    https://corpusfetch.com/c/in-what-scenarios-must-an-instance-refuse-to-treat-a-did-document-s-alsoknownas-as-a-transitive-trust-bridge-during-cross-org-agent-federation.warrant.json
# Markdown SHA-256:   c9c13d5a7e014b5e968a4e51fe7dec399fb6040240b6724fac12a91641c87548
# Code AST SHA-256:   f4f67d7c15b578900c412b3243f684ccb688307515271ef15ccd088cc6f65b45
# Verified Classes:   AliasTrustViolation, ResolvedDid
# Defensive Guards:   5 fail-closed invariants (zero external deps)

from dataclasses import dataclass
from typing import Optional


class AliasTrustViolation(RuntimeError):
    """Raised when alias traversal is used to satisfy an authorization binding."""
    pass


@dataclass(frozen=True)
class ResolvedDid:
    did: str
    also_known_as: tuple[str, ...]
    controller: Optional[str]
    anchor: str  # trust anchor that vouches for this document


def authorize_credential_subject(
    presented_did: str,
    vc_subject_id: str,
    resolved: ResolvedDid,
    verifier_trusted_anchors: frozenset[str],
    alias_is_bidirectional: bool = False,
    alias_is_fresh: bool = True,
) -> None:
    """
    Enforce exact-match binding between the presented DID and the VC subject.

    Alias traversal (alsoKnownAs / controller) is permitted ONLY for correlation,
    never to satisfy an authorization binding across org boundaries.
    """
    if presented_did == vc_subject_id:
        if resolved.anchor not in verifier_trusted_anchors:
            raise AliasTrustViolation(
                f"anchor {resolved.anchor!r} not in verifier trust set; "
                f"cannot honor VC for {presented_did!r}"
            )
        return

    # Presented DID differs from VC subject: any path here is alias traversal.
    traversed = (
        vc_subject_id in resolved.also_known_as
        or resolved.controller == vc_subject_id
    )
    if not traversed:
        raise AliasTrustViolation(
            f"VC subject {vc_subject_id!r} does not match presented DID "
            f"{presented_did!r} and is not reachable via declared alias"
        )

    # Even with a declared alias, refuse unless every validity condition holds.
    if not alias_is_bidirectional:
        raise AliasTrustViolation(
            f"unidirectional alias {presented_did!r} -> {vc_subject_id!r} "
            f"is a reverse-alias attack surface; refusing authorization"
        )
    if not alias_is_fresh:
        raise AliasTrustViolation(
            f"stale alias resolution between {presented_did!r} and "
            f"{vc_subject_id!r}; refusing until DID Document re-resolved"
        )
    raise AliasTrustViolation(
        f"alias traversal {presented_did!r} -> {vc_subject_id!r} cannot "
        f"satisfy authorization; require issuer-signed sameAs claim or "
        f"re-issued VC bound to {presented_did!r}"
    )
