Files
skills/docs/foundation/data/packer-browser/src/runtime/runtime.md
2026-05-29 08:20:56 +01:00

2.9 KiB

runtime

(no submodules)

Purpose

runtime.ts centralises the three injectable platform primitives (Clock, MonotonicClock, Rng) that every production path in @suaveplan/packer-browser reads time and randomness through. Direct Date.now(), Math.random(), and performance.now() calls are banned outside this file so seeded-deterministic tests can pin every observable behaviour. The shape mirrors @suaveplan/packer/runtime, so adopters that already inject runtime into the packer get the same contract here.

Features

  • defaultClock / defaultMonotonicClock / defaultRng — wall-clock and CSPRNG defaults wired to the platform globals.
  • resolveRuntime(opts?) — merges caller-supplied RuntimeOptions against the platform defaults to produce a fully-populated PackerBrowserRuntime bundle.
  • elapsedMs(monotonicClock, startNanos) — convenience for the histogram observation sites that previously did performance.now() - start directly.
  • Adapter that upgrades a seeded Rng lacking nextBytes into the runtime-shape RNG by deriving bytes from nextUint32, so tests can inject @suaveplan/testing's seededRng() unchanged.

Usage: Basic

import { resolveRuntime } from "@suaveplan/packer-browser";

const runtime = resolveRuntime();
const now = runtime.clock(); // ms since epoch
const seed = runtime.rng.nextBytes(16); // CSPRNG bytes

Usage: Advanced

import { FakeClock, seededRng } from "@suaveplan/testing";
import { resolveRuntime } from "@suaveplan/packer-browser";

const clock = new FakeClock({ now: 1_700_000_000_000 });
const runtime = resolveRuntime({
    clock: () => clock.now(),
    rng: seededRng(42),
});
// runtime.clock() returns 1_700_000_000_000 until FakeClock is advanced

API Reference

  • defaultClock: Clock — () => Date.now().
  • defaultMonotonicClock: MonotonicClock — wraps performance.now(), returns nanoseconds as bigint.
  • defaultRng: Required<Pick<Rng, "nextBytes">> & Rng — CSPRNG bound to globalThis.crypto.
  • resolveRuntime(opts?: RuntimeOptions): PackerBrowserRuntime — fills in defaults for absent fields.
  • elapsedMs(monotonicClock, startNanos: bigint): number — returns elapsed milliseconds as a float.
  • RuntimeOptions / PackerBrowserRuntime — option / resolved bundles.

Implementation Notes

Monotonic time is exposed as bigint nanoseconds even though most consumers ultimately reduce to millisecond floats. The bigint discipline prevents accidental rounding when sampling the clock at nanosecond precision; the elapsedMs helper exists so call sites that need the float form never reach for performance.now() directly. nextBytes is part of the resolved RNG shape because the upcoming Cluster B encrypted-archive keyring needs CSPRNG bytes and the manager will forward the resolved RNG to it.