# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/when-must-a-federated-memory-agent-reject-a-differentially-private-retrieval-response-at-the-aggregation-boundary.md
# Remnant Warrant:    https://corpusfetch.com/c/when-must-a-federated-memory-agent-reject-a-differentially-private-retrieval-response-at-the-aggregation-boundary.warrant.json
# Markdown SHA-256:   70af7a9c032b02dc9c7a93caffaa652e7f950fe33d4097827e5578f32eddd54e
# Code AST SHA-256:   c883978bc4d7d350804bb1727878611dfba6df6a5cdb62f80f5298f3cd72802f
# Verified Classes:   SupportPrivacyViolation, RetrievalResponse
# Defensive Guards:   3 fail-closed invariants (zero external deps)

from dataclasses import dataclass


class SupportPrivacyViolation(RuntimeError):
    """Raised when a DP retrieval response leaks support/membership beyond the certified budget."""
    pass


@dataclass
class RetrievalResponse:
    aggregate: list          # DP-noised value vector
    receipt_count: int       # number of contributing shards (support channel)
    calibrated_n: int        # n used to scale DP noise
    is_retry: bool
    composition_booked: bool


def admit_response(resp: RetrievalResponse,
                   epsilon_support_budget: float,
                   support_leak_bits: float,
                   n_tolerance: int = 2) -> RetrievalResponse:
    # 1. Support channel must be covered by the accountant.
    if support_leak_bits > epsilon_support_budget:
        raise SupportPrivacyViolation(
            f"support leak {support_leak_bits:.3f} bits exceeds "
            f"budget {epsilon_support_budget:.3f}"
        )
    # 2. Noise must be calibrated to the realized contributing set.
    if abs(resp.receipt_count - resp.calibrated_n) > n_tolerance:
        raise SupportPrivacyViolation(
            f"calibrated_n={resp.calibrated_n} but realized n={resp.receipt_count}; "
            "DP scale is invalid for this query"
        )
    # 3. Retries must be booked before release, or they compose silently.
    if resp.is_retry and not resp.composition_booked:
        raise SupportPrivacyViolation(
            "retry released without composition accounting; epsilon would compose unbooked"
        )
    return resp
