Repository navigation
Description
Summary
pkgs/id/src/currency.rs fold_authorisation (landed today via PR #3888, closing #3800) selects the live version with max_by_key(|(_, body)| body.version) (currency.rs:313-320). When two distinct signed bodies from the expected issuer carry the same highest version (a forked/duplicated issuer chain, or a re-issued v2 with a different rate), Iterator::max_by_key returns the last maximal element in slice order — so the folded Live authorisation depends on the order the caller happens to present the objects, not on the objects alone. The module header promises "State is a fold over the objects alone" (currency.rs:20-23), and the revoke side of the same fold was made explicitly deterministic ("ties break to the smallest revoked_version_from, deterministically", currency.rs:296-300) — the version selection has no such tie-break.
Evidence (verified this run, laptop probe)
Probe: ~/git/fleet/probe-2026-11-01-laneB-currency/ on the laptop — verbatim validate + version-selection core of fold_authorisation, against currency.rs at main c3fda1c4 (sha256 8f68982526219dff920586495a076d2c1a33f87fe3b6716a74e561ea821b9493, reference copy in the probe dir).
Two issuer-signed v2 bodies for authorisation 7, rate_num 8000 vs 9000:
order [8000,9000] -> rate_num 9000
order [9000,8000] -> rate_num 8000
test duplicate_version_fold_depends_on_input_order ... ok
Same object set, two presentation orders, two different live rates.
Why it matters
The fold is the library source of truth every later phase consumes: Phase 2 (#3801) folds "highest version" at submission time and Phase 3 (#3802) binds quotes to it. Two nodes (or one node after a re-sync that changes object order) can fold the same signed object set to different live rates and both be "correct" per this code — a consensus-style divergence in a money-adjacent type, created by the issuer merely signing two bodies at one version (which the chain permits on forked chains; nothing in validate or the fold rejects duplicate versions).
Acceptance criteria
- Duplicate highest versions fold deterministically regardless of input order: either a canonical tie-break (e.g. by body hash / canonical bytes) documented in the fold's doc comment, or duplicate versions at the maximum are rejected / fold to no live authorisation with the rule stated.
- Regression test: the same duplicate-version object set in both orders folds to the identical state.
- Existing currency tests (golden rates, hijack, revoke tie-break) still pass.
- The chosen rule is recorded on id: design: RateAuthorisation as a signed ID-graph object — schema, signing, revocation #2290 (parent design) if it changes the design record's fold semantics.
Distinct from: #3801 (gateway live-state checks — it consumes this fold), #3802 (quote binding), #4060/#4063 (app_manifest validation, different module).
Activity
dezren39 commentedon Nov 1, 2026
🤖 Agent note · filed
fold_authorisationin the newpkgs/id/src/currency.rs(PR feat(id): currency.rate_authorisation + revoke types and fold (#3800) #3888, main c3fda1c) picks the live version withmax_by_key(version)and no tie-break, so two issuer-signed bodies at the same highest version fold to different live rates depending on slice order. Verified on the laptop (probe~/git/fleet/probe-2026-11-01-laneB-currency/, sha256-matched currency.rs): order [rate 8000, rate 9000] folds Live rate 9000, reversed order folds 8000.28 remaining items
dezren39 commentedon Nov 2, 2026
🤖 Agent note · handed off
queue/queued+status/needs-triage. Open PR: PR fix(id): deterministic tie-break for duplicate highest currency versions (#4069) #4547 (verify and shepherd it on resume — do not re-implement).dezren39 commentedon Nov 3, 2026
agent-note:v1
event: picked-up
task: 6306 (repo-health-code-pilot, repo-worker-code; lane ec118cad-0fd3-4652-91c4-27432f2f2efd)
state: claimed (resume from awaiting_ci)
verified: Fresh GitHub state 2026-11-03T08:05Z: #4069 OPEN; bound PR #4547 OPEN on branch queue/6306-4069-currency-tiebreak at aee7648 (matches checkpoint); checks basic guard SUCCESS + CodeRabbit SUCCESS. Resuming: verify worktree/tests, then merge per standing criteria.
next: Targeted currency tests in task worktree, re-check mergeability, merge + complete.
Merge pull request #4547 from developing-today/queue/6306-4069-curren…
dezren39 commentedon Nov 3, 2026
agent-note:v1
event: done
task: 6306 (repo-health-code-pilot, repo-worker-code; lane ec118cad-0fd3-4652-91c4-27432f2f2efd)
state: complete fixed_merged
result: PR #4547 merged as 5994eaf on origin/main; issue auto-closed. fold_authorisation now breaks equal-version ties by lexicographically greatest canonical body bytes (documented); order-permutation regression test added. currency:: suite 10/10 pass on main-merged head; PR checks green (production-line-guard SUCCESS, CodeRabbit NEUTRAL). Labels cleared to terminal state.
tests: cargo test --manifest-path pkgs/id/Cargo.toml --lib currency:: — 10 passed, 0 failed