Skip to content

fix(directory): byte-order determinism-receipt sort, not locale collation (§10.5.3(2))#22

Open
cX3po wants to merge 1 commit into
mainfrom
cx3po/dacs-reputation-byteorder
Open

fix(directory): byte-order determinism-receipt sort, not locale collation (§10.5.3(2))#22
cX3po wants to merge 1 commit into
mainfrom
cx3po/dacs-reputation-byteorder

Conversation

@cX3po

@cX3po cX3po commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Problem

reputation.ts sorted the DACS-5 determinism receipt (bundleRefs) and the per-currency volume / tx-count arrays with String.localeCompare. §10.5.3(2) specifies byte-order lexicographic ordering on contentHash. localeCompare is ICU/locale-collation dependent and is not guaranteed byte-stable across runtimes or default locales — so two conforming implementations could emit different determinism-receipt bytes, which defeats the receipt's purpose.

Fix (validator/derivation-only)

A byteOrder(a, b) = Buffer.compare(Buffer.from(a, "utf8"), Buffer.from(b, "utf8")) comparator, applied to all three sorts. Buffer.compare is unsigned byte-wise lexicographic, and UTF-8 byte order equals code-point order — so it implements the specified ordering exactly (and avoids the UTF-16-code-unit trap of a naive a < b).

No behavior change on well-formed data: for lowercase-hex hashes and same-case currency codes, ICU collation and byte order already agree. The comparators diverge only on mixed-case / non-ASCII input — exactly the cross-implementation cases where receipt determinism matters.

Test

A vector on an input where the two comparators disagree: 'Z' (0x5A) sorts before 'a' (0x61) in byte order but after it under ICU collation. The test asserts byte order and provably fails against the old localeCompare comparator.

Receipts: suite 35/35, tsc --noEmit --incremental false clean. Reviewed pre-PR (Codex binding: APPROVED; second reviewer: APPROVED-with-notes).

…tion (§10.5.3(2))

reputation.ts sorted bundleRefs + observed-volume/tx-count by `String.localeCompare`,
which is ICU/locale-collation dependent and not guaranteed byte-stable across
runtimes/locales. §10.5.3(2) specifies byte-order lexicographic ordering — so two
conforming implementations under different default locales could emit different
determinism-receipt bytes, defeating the receipt's purpose.

Fix: a `byteOrder(a,b) = Buffer.compare(utf8(a), utf8(b))` comparator, applied to all
three sorts. Vector added: an input where byte-order ('Z'=0x5A before 'a'=0x61) and
ICU collation disagree — provably fails against the old comparator. Suite 35/35,
typecheck clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@mj-deving mj-deving left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed against origin/main at ce0718329a1475db99bfa925d7e5535b809a2415.

Validation I ran in a disposable checkout:

  • git diff --check origin/main...HEAD -> pass
  • built pinned vendor/dacs-sdk rev 44d8ff2a07df8c951b94619d20b957b4bb5ce140 with Bun
  • sequential test files -> 35/35 pass
  • bun run typecheck -> pass
  • bun run build -> pass
  • autoreview --mode branch --base origin/main -> clean, no accepted/actionable findings

The change is narrow and matches the §10.5.3(2) requirement: Buffer.compare(Buffer.from(..., "utf8")) gives byte-order lexicographic ordering for the deterministic receipt fields, and the new Z/a regression distinguishes it from locale collation. No findings from me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants