# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/what-structural-signals-indicate-a-did-resolution-dependency-has-silently-degraded-into-a-trust-laundering-path-in-cross-org-agent-federation.md
# Remnant Warrant:    https://corpusfetch.com/c/what-structural-signals-indicate-a-did-resolution-dependency-has-silently-degraded-into-a-trust-laundering-path-in-cross-org-agent-federation.warrant.json
# Markdown SHA-256:   4f619a0c3171d0c84b8513c7039eef87b00ef4c37620dba9358d67e3b1cd1406
# Code AST SHA-256:   a69103b42179c9e4f359c49bca3063d70d2ad04e2e7c4047439f4cb49e156b60
# Verified Classes:   TrustLaunderingError, ResolvedDocument
# Defensive Guards:   3 fail-closed invariants (zero external deps)

import hashlib
from dataclasses import dataclass
from typing import Optional


class TrustLaunderingError(RuntimeError):
    """Raised when a resolved DID document does not identity-match the requested DID.

    This is a hard failure: a signature-valid credential issued under a
    substituted document must never be fed to policy evaluation keyed on the
    requested DID.
    """


@dataclass(frozen=True)
class ResolvedDocument:
    requested_did: str
    resolved_id: str
    controller: str
    key_thumbprints: frozenset[str]
    served_by_host: str
    method_expected_host: Optional[str]


def canonicalize_did(did: str) -> str:
    # did:web example; lowercase host, strip trailing slash, preserve method+id
    method, _, rest = did.partition(":")
    rest = rest.rstrip("/").lower()
    return f"{method}:{rest}"


def assert_identity_preserving(doc: ResolvedDocument) -> None:
    req = canonicalize_did(doc.requested_did)
    got = canonicalize_did(doc.resolved_id)
    if req != got:
        raise TrustLaunderingError(
            f"resolved document id {doc.resolved_id!r} does not match "
            f"requested did {doc.requested_did!r} after canonicalization"
        )
    if doc.method_expected_host is not None:
        if doc.served_by_host.lower() != doc.method_expected_host.lower():
            raise TrustLaunderingError(
                f"document for {doc.requested_did!r} served by host "
                f"{doc.served_by_host!r}, expected {doc.method_expected_host!r}"
            )


def evaluate_admission(
    requested_did: str,
    doc: ResolvedDocument,
    policy_tier_by_did: dict[str, str],
) -> str:
    assert_identity_preserving(doc)
    tier = policy_tier_by_did.get(canonicalize_did(requested_did))
    if tier is None:
        raise TrustLaunderingError(
            f"no policy tier for {requested_did!r}; refusing admission"
        )
    return tier
