feat(rustd): the approval gate decides, and the order it decides in is a type
The gate's pure core: which rule fires for an action, what that rule decides, and how a recorded gate and the current policy compose. `evaluateGate` walks the rules and answers a decision; `matchRule` walks them again and answers the rule, because the decision discards which rule produced it and the approval card needs that rule's workspace-authored copy. The second carries a comment insisting it uses "the same traversal and same first-match-wins order … so the two can never disagree about which rule applied." An invariant a comment has to insist on is one the code is not holding. There is one walk here — `match_rule` — and the decision is a pure function OF its result. They cannot disagree about which rule applied because only one of them looks. `route` ports faithfully, tests included: a recorded gate outranks every policy outcome, including both that would otherwise pass. Those two rows are what a mid-flight config PATCH produces, and under the other ordering both released a parked event while its approval card still sat unanswered. `RefState` stays three arms rather than an `Option` because collapsing "no gate" and "cannot tell" is unsafe in both directions. Condition evaluation is a chain of `and_then` ending in `is_none_or`, so all five ways a context cannot answer a condition — absent, not an object, missing field, non-string field, unparseable expression — resolve through one expression rather than five `return true`s a reader has to find. `every_undecidable_context_fires_the_gate` walks all five, because a fail-safe that is safe for four of five inputs is not one. The grammar lands in `afd_fleet_runtime` beside the field it interprets rather than beside its one caller, because the Zig's header explains why that sharing is load-bearing: a condition that parsed at write time and not at eval time silently fires the gate on every matching action. The write-time half is not ported here, and this is where it goes. `GatePolicy::from_parts` is behind `test-util`: the production door is the validating `TryFrom`, and a second way to build a policy is a way to build an invalid one. Not in this commit: parking, cards, anomaly counters, recorded-gate reads. Every one is Redis or Postgres and every one is downstream of a decision made here. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
K
Kishore Kumar committed
e0055ffa5be7c42ad57e92cc28c31eaec49973b5
Parent: 23d546c