Skip to content

Byzantine-Resilient Consensus

director_ai.core.scoring.consensus.ByzantineFaultTolerantConsensus

ByzantineFaultTolerantConsensus(*, fault_tolerance: int)

PBFT-style quorum over independent verifier votes.

For fault tolerance f, at least 3f + 1 independent votes are required and a decision requires a 2f + 1 quorum for the same verdict.

decide

decide(votes: Sequence[BFTConsensusVote], *, policy_id: str) -> BFTConsensusResult

Return a PBFT-style quorum decision for verifier votes.

director_ai.core.scoring.consensus.BFTConsensusVote dataclass

BFTConsensusVote(verifier: str, verdict: str, risk_score: float, evidence_ref: str = '')

One independent verifier vote for BFT consensus.

director_ai.core.scoring.consensus.BFTConsensusResult dataclass

BFTConsensusResult(decision: str, reason: str, policy_id: str, fault_tolerance: int, required_replicas: int, quorum_size: int, byzantine_resilient: bool, participating_verifiers: tuple[str, ...] = (), evidence_refs: tuple[str, ...] = (), risk_score: float = 0.0)

PBFT-style quorum result for verifier votes.

to_dict

to_dict() -> dict[str, object]

Serialise the quorum result with tenant-safe evidence references.

Fault Model

ByzantineFaultTolerantConsensus implements a PBFT-style quorum over independent verifier votes. For a configured fault tolerance f:

  • at least 3f + 1 independent verifier votes are required
  • a decision requires 2f + 1 votes for the same verdict
  • duplicate verifier names are rejected
  • missing quorum returns warn, not allow
from director_ai.core import BFTConsensusVote, ByzantineFaultTolerantConsensus

consensus = ByzantineFaultTolerantConsensus(fault_tolerance=1)
result = consensus.decide(
    (
        BFTConsensusVote("nli-a", "allow", 0.1, "claim://1"),
        BFTConsensusVote("nli-b", "allow", 0.2, "claim://2"),
        BFTConsensusVote("symbolic", "allow", 0.0, "proof://1"),
        BFTConsensusVote("adversarial", "halt", 0.9, "claim://x"),
    ),
    policy_id="policy.bft",
)

This is a verifier-vote quorum layer. It does not prove that verifiers are actually independent or uncompromised; deployment policy must justify that assumption before claiming Byzantine tolerance.