Repository navigation
Description
Summary
RateAuthorisation::validate in the new pkgs/id/src/currency.rs (PR #3888, main c3fda1c4) checks exactly two things — issuer == event author and rate_den != 0 (currency.rs:170-180). Every other internally inconsistent body folds as Live: the fold's only validity gate is this function (currency.rs:313-320), so a signed authorisation that can never legitimately convert — or that misprices every conversion — is indistinguishable from a good one for every consumer of the fold.
Evidence (verified this run, laptop probe)
Probe: ~/git/fleet/probe-2026-11-01-laneB-currency/ on the laptop — verbatim validate from currency.rs (reference copy sha256 8f68982526219dff920586495a076d2c1a33f87fe3b6716a74e561ea821b9493 @ c3fda1c4). All of these return Ok(()):
validate(min>max) -> Ok(()) min_amount 10000, max_amount 1
validate(expires_at==not_before (empty window)) -> Ok(()) 2000 / 2000
validate(expires_at<not_before) -> Ok(()) 2000 / 3000
validate(fee_bps 99999 (>100%)) -> Ok(()) fee is 999.99%
validate(empty ledgers) -> Ok(()) source_ledger "" and dest_ledger ""
validate(source==dest ledger) -> Ok(()) ABC -> ABC
validate(rate_num 0 (zero rate)) -> Ok(()) every conversion yields 0
validate(total_cap 0) -> Ok(()) cap permits nothing
validate(empty allowlist (allows nobody)) -> Ok(()) AuthorisedCallers::Allowlist([])
test validate_accepts_internally_inconsistent_bodies ... ok
(Sanity: the two documented checks do fire — rate_den = 0 returns ZeroRateDenominator.)
Why it matters
validate is the library-level contract the fold, and later the Phase 2 gateway checks (#3801: window, min/max, remaining volume at submission), rely on. A body with min_amount > max_amount, an empty/inverted validity window, or fee_bps > 10000 can never be caught downstream as "invalid" — the gateway's live-state checks would evaluate a nonsense window and nonsense bounds as if they were policy, and different consumers can disagree about shapes like a zero rate or a same-ledger "conversion". The field docs in this same file state the invariants in prose ("Rate denominator; non-zero in a valid authorisation", "Mandatory expiry", "Optional fee in basis points") — rate_den is the only one enforced.
Acceptance criteria
-
validaterejects, with namedValidateErrorvariants:min_amount > max_amount;expires_at <= not_before;fee_bps > Some(10000); emptysource_ledgerordest_ledger;source_ledger == dest_ledger. - Shapes that are arguably legitimate-but-dead (zero
rate_num, zerototal_cap, empty allowlist) are either rejected with named variants or explicitly documented as valid in the field docs — one stated rule, tested either way. - Tests cover each rejected shape; existing currency tests still pass; the fold ignores the newly invalid bodies (covered by the existing fold-filter test pattern).
Distinct from: #3801 (gateway submission-time checks against accounts/tiers — it assumes a valid folded object), #4069 (duplicate-version fold tie-break, same file, different defect), #4063 (app_manifest parser validation, different module).
Activity
dezren39 commentedon Nov 1, 2026
🤖 Agent note · filed
RateAuthorisation::validatein the newpkgs/id/src/currency.rs(PR feat(id): currency.rate_authorisation + revoke types and fold (#3800) #3888, main c3fda1c) checks only issuer andrate_den != 0(currency.rs:170-180), so bodies with min>max, expires_at<=not_before, fee_bps 99999, empty ledgers, source==dest, zero rate, zero cap, or an empty allowlist all fold as Live. Verified on the laptop (probe~/git/fleet/probe-2026-11-01-laneB-currency/, sha256-matched currency.rs): all nine shapes return Ok(()); the rate_den=0 control is rejected.82 remaining items
dezren39 commentedon Nov 4, 2026
agent: repo-worker-code
state: parked
queue: repo-health-code-pilot
task: 8834
lane: aea12c82-c5af-4e5a-9b66-f8e360f87177
at: 2026-11-04T21:47:22Z
Parked task 8834 for 30 minutes after fresh revalidation. Issue #4071 is OPEN and assigned to dezren39; PR #5181 is OPEN, fixes #4071, and is authored by dezren39 on the task branch queue/8834-4071-rateauthorisation-validation. This is Drew-owned work: no PR, branch, worktree, files, or tests were touched. Resume only after PR #5181 merges/closes or Drew explicitly releases ownership; then revalidate fresh. Labels now reflect parked state: queue/parked + status/parked + work/assigned.
dezren39 commentedon Nov 4, 2026
🤖 Agent note · picked up
dezren39 commentedon Nov 4, 2026
🤖 Agent note · parked
dezren39 commentedon Nov 5, 2026
🤖 Agent note · handed off