# Defaults — Clock and RNG factories _(no submodules)_ ## Purpose `@suaveplan/bitpacker-network` enforces the determinism rule (no module-scope `Date.now()` or `Math.random()` calls in implementation files). To do that without infecting every consumer with mandatory `clock` / `rng` parameters, this package allow-lists ONE factory per source: `defaultClock` and `defaultRng()`. Every other module reads time and randomness only through the injected primitives passed at construction time, defaulting to these factories. This is the same pattern `@suaveplan/events` uses (`events/clock/default-clock.ts`) and is the single explicit boundary between deterministic, replayable code paths and the host environment's wall clock / CSPRNG. ## Features - `defaultClock` — `Clock = () => Date.now()`. Produces ms-since-epoch reads from the host wall clock. - `defaultRng()` — factory that wraps `@suaveplan/random::cryptoRng()`. Returns a fresh CSPRNG-backed `Rng` per call. Throws if the host has no `crypto.getRandomValues`. ## Usage: Basic Example ```typescript import { NetworkSimulator } from "@suaveplan/bitpacker-network"; // Without overrides: NetworkSimulator wires defaultClock and defaultRng() internally. const sim = new NetworkSimulator(); ``` ## Usage: Advanced Example ```typescript import { NetworkSimulator } from "@suaveplan/bitpacker-network"; import { Mulberry32Rng } from "@suaveplan/pseudo-random"; // Tests: inject a seeded RNG for reproducible packet-loss patterns. const seededRng = new Mulberry32Rng(0xDEADBEEF); const fakeClock = (): number => 0; // every call returns t=0 const sim = new NetworkSimulator({ rng: seededRng, clock: fakeClock, }); // Two simulators with the same seed produce byte-identical loss sequences. ``` ## API Reference ### `defaultClock: Clock` Constant. `() => number` returning the current millisecond timestamp via `Date.now()`. Suitable for the simulator's `startTime`, `lastBandwidthCheck`, packet `timestamp`, and `uptime` calculations. NOT monotonic — consumers needing strict monotonicity should inject a different `Clock`. ### `defaultRng(): Rng` Factory function. Returns a fresh `Rng` backed by `globalThis.crypto.getRandomValues`. Throws `RandomError` (code `RANDOM.SOURCE.UNAVAILABLE`) if the host environment lacks the API. The simulator's constructor calls this lazily — if the consumer always provides their own `rng` option, the factory is never invoked, so older / non-browser hosts that lack `crypto.getRandomValues` can still use the simulator with a seeded `Rng`. ## Implementation Notes The package's `src/simulator/simulator.spec-conformance.test.ts` includes a grep guard that scans implementation files for `Date.now()` / `Math.random()` and fails the build if either appears outside `defaults/default-clock.ts` and `defaults/default-rng.ts`. Those two files are explicitly allow-listed in the grep — that's the integrity boundary that keeps the rest of the package deterministic given identical injected primitives. If a future addition needs another determinism-violating API (e.g. `performance.now()`, `process.hrtime()`), the convention is: add a new file under `defaults/` and extend the spec-conformance allow-list to include it. Spreading the violations across implementation files is what the rule prevents.