# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/why-does-an-instance-of-cross-org-agent-federation-fail-to-bootstrap-trust-when-both-parties-hold-valid-verifiable-credentials.md
# Remnant Warrant:    https://corpusfetch.com/c/why-does-an-instance-of-cross-org-agent-federation-fail-to-bootstrap-trust-when-both-parties-hold-valid-verifiable-credentials.warrant.json
# Markdown SHA-256:   9da8d9abed7cb8d03618e52458825329b440781f4e433faa44d652ae1a2b385f
# Code AST SHA-256:   1a43572eab2b04f1a117bd88a6dc530c9bc9aa42358d58aa0f99bbdbed16148d
# Verified Classes:   FederationBootstrapError
# Defensive Guards:   3 fail-closed invariants (zero external deps)

class FederationBootstrapError(RuntimeError):
    """Raised when mutual admission cannot be established despite valid credentials."""


def establish_federation(local_policy, peer_material, peer_policy):
    # Step 1: cryptographic verification (symmetric, cheap, local).
    if not verify_vc(peer_material.vc):
        raise FederationBootstrapError("peer VC failed signature/issuer verification")
    if not verify_signed_policy(peer_policy):
        raise FederationBootstrapError("peer policy failed signature verification")

    peer_org = peer_material.vc.credential_subject["org_did"]

    # Step 2: policy admission (asymmetric, requires explicit grant).
    if peer_org not in local_policy.admitted_org_dids:
        # Verified but not admitted: this is the deadlock boundary.
        # Do NOT retry. Require an out-of-band grant or an inbound
        # admission-assertion from the peer before proceeding.
        raise FederationBootstrapError(
            f"peer org {peer_org} verified but not admitted; "
            f"mutual allow-list gating will deadlock. "
            f"verified=True admitted=False"
        )

    # Step 3: only now may we grant authority and emit our own
    # admission-assertion so the peer can populate its allow-list.
    return grant_authority(peer_org)
