# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/how-must-an-instance-bound-fx-rate-snapshot-skew-between-settlement-parties.md
# Remnant Warrant:    https://corpusfetch.com/c/how-must-an-instance-bound-fx-rate-snapshot-skew-between-settlement-parties.warrant.json
# Markdown SHA-256:   20e9f85c9d46768e977a165ffff7029bb34ca5b0baa6993fc5859336bb6e58ea
# Code AST SHA-256:   54c5b0d4771e208786c7bd51e2bbfa5173a5ac7b322875bbdea61b854994f4e8
# Verified Classes:   RateSnapshotSkewError, FxSourceTuple, FxCaptureGate
# Defensive Guards:   3 fail-closed invariants (zero external deps)

from dataclasses import dataclass


class RateSnapshotSkewError(RuntimeError):
    """Raised when two parties capture an FX rate at different publication instants."""


@dataclass(frozen=True)
class FxSourceTuple:
    publisher: str
    publication_instant: str
    window_seconds: int


@dataclass(frozen=True)
class FxCaptureGate:
    instance_source: FxSourceTuple
    counterparty_source: FxSourceTuple
    instance_capture_offset_seconds: int
    counterparty_capture_offset_seconds: int
    volatile_regime: bool = False

    def verify(self) -> bool:
        if self.instance_source != self.counterparty_source:
            raise RateSnapshotSkewError(
                f"source tuple mismatch instance={self.instance_source} "
                f"counterparty={self.counterparty_source}"
            )
        window = self.instance_source.window_seconds
        if self.instance_capture_offset_seconds > window:
            raise RateSnapshotSkewError(
                f"instance capture offset {self.instance_capture_offset_seconds}s "
                f"exceeds publication window {window}s"
            )
        if self.volatile_regime and abs(
            self.instance_capture_offset_seconds - self.counterparty_capture_offset_seconds
        ) > 0:
            raise RateSnapshotSkewError(
                "volatile regime with non-identical capture offsets: rate may diverge"
            )
        return True


def dispatch_fx_mode(gate: FxCaptureGate) -> str:
    try:
        gate.verify()
    except RateSnapshotSkewError:
        return "bind-to-published-rate"
    return "snapshot-rate"
