Combinators and the rule catalog
impl<A: Rule<P>, B: Rule<P>, P> Rule<P> for All<(A, B)> { ... } // verdicts and-ed
impl<A, B, P> Rule<P> for Either<(A, B)> { ... } // verdicts or-ed
pub struct OnlyIf<C, R>; // predicate-gated (implies)Composition is at source level (one circuit), never by recursion. Because
rules return Verdicts rather than asserting, Either is a plain boolean
or and both branches are always evaluated, as Noir requires. Either
emits Attest::select(a_holds, att_a, att_b); if both hold, A's
attestation wins. Regions are opened once per phase and shared by every
rule in the composition.
The standard catalog (framework/rules) ships: AmountCap,
DailyVelocity, TravelRuleThreshold, CountryAllow, CountryDeny,
AssetAllow, PurposeCode, MinAge (from DOB leaf, age never revealed),
OfficerApproval (Schnorr co-signature over context_root),
RequireAttestation, CounterpartyAllow (by pool-welded
counterparty_fi_index). Each ships with its assert ids, gate count, and
generated negatives.