Files
skills/docs/foundation/flow/cbor/src/deterministic/deterministic.md
2026-05-29 08:20:56 +01:00

2.4 KiB

deterministic

(no submodules)

Purpose

Convenience entry point for RFC 8949 §4.2 deterministic encoding. The underlying encode accepts a deterministic: true option; this module exposes a tiny encodeDeterministic(value, options?) wrapper that pins the flag at true and forbids the caller from overriding it. Use this when the encoded bytes must be byte-stable across runs — content-addressable storage, hash digests, signature payloads, COSE structures, and CWT claim sets are the canonical consumers.

Features

  • Sorted map keys — lexicographic byte order over the canonical CBOR-encoded key bytes, NOT the JavaScript Map iteration order.
  • Shortest-form integers — always-on regardless of mode.
  • No indefinite-length items — caller cannot opt in.
  • Half-float disabled in deterministic mode; floats serialise as the shortest exact width among {float32, float64}.
  • Rejects undefined with CborError(NON_DETERMINISTIC) — undefined has no canonical CBOR representation, so it cannot be deterministically encoded.

Usage: Basic Example

import { encodeDeterministic } from "@suaveplan/cbor/deterministic";

const m = new Map<string, number>([["b", 2], ["a", 1]]);
const bytes = encodeDeterministic(m);
// bytes are sorted by canonical key order

Usage: Advanced Example

import { encodeDeterministic } from "@suaveplan/cbor/deterministic";

const a = encodeDeterministic({ z: 1, a: 2 });
const b = encodeDeterministic({ a: 2, z: 1 });
// a and b are byte-identical because key order is canonical, not insertion-order.

import { sha256 } from "@suaveplan/crypto-hash/sha256";
const digest = await sha256(a);

API Reference

  • encodeDeterministic(value: unknown, options?: Omit<EncoderOptions, "deterministic">): Uint8Array

The omitted deterministic field guarantees the flag stays pinned. Other options (maxDepth, maxItems, preferFloat16) are honoured but preferFloat16 has no effect when deterministic is on.

Implementation Notes

This module exists primarily for ergonomics — direct encode(v, { deterministic: true }) is identical at runtime. The wrapper guards against accidental deterministic: false overrides and gives downstream readers a clear signal about intent at the call site. Consumers who need to assert byte-stability across runs should pair this with property tests over arbitrary JsonValue-like inputs.