# Capability: random-utilities ## ADDED Requirements ### Package identity - REQ-RAND-001: Package name `@suaveplan/random`, `packages/universal/random`. - REQ-RAND-002: Runtime deps: `@suaveplan/types`, `@suaveplan/error`, `tslib`, `zod`. Zero crypto-specific deps. - REQ-RAND-003: `"sideEffects": false`. Subpath exports per feature module. ### CSPRNG source - REQ-RAND-010: Exports `cryptoRng(): Rng` — factory returning a WebCrypto-backed `Rng` object: `{ nextUint32, nextFloat }`. `crypto.getRandomValues` is the **only** callsite in this package, located exclusively in `src/source/crypto-rng.ts`. - REQ-RAND-011: Exports `getDefaultRng(): Rng` and `setDefaultRng(rng: Rng): void`. Default is `cryptoRng()` at module init. - REQ-RAND-012: `setDefaultRng` is documented as a test hook. Tests must restore the previous value in `afterEach`. ### Bytes and numbers - REQ-RAND-020: Exports `randomBytes(n: number, rng?: Rng): Uint8Array` — fills via `nextUint32()` calls. - REQ-RAND-021: Exports `randomInt(min: number, max: number, rng?: Rng): number` — uniform integer in `[min, max]` inclusive. Throws if `min > max`. - REQ-RAND-022: Exports `randomFloat(rng?: Rng): number` — uniform float in `[0, 1)`. ### String generation - REQ-RAND-030: Exports `randomString(length: number, opts?: { type?: StringType; characters?: string; rng?: Rng }): string`. - REQ-RAND-031: `StringType = "hex" | "base64" | "base64url" | "url-safe" | "numeric" | "alphanumeric" | "distinguishable" | "ascii-printable"`. - REQ-RAND-032: `distinguishable` charset: `CDEHKMPRTUWXY012458` (no visually ambiguous characters). - REQ-RAND-033: `type` and `characters` are mutually exclusive; providing both throws `RandomError("RANDOM.STRING.INVALID_OPTIONS")`. ### ID generation - REQ-RAND-040: Exports `randomUUID(rng?: Rng): string` — RFC 4122 v4 UUID. - REQ-RAND-041: Exports `randomUUIDv7(rng?: Rng): string` — time-ordered UUID v7: 48-bit ms timestamp + 74 random bits. Monotonically increasing within the same millisecond via sequence counter. - REQ-RAND-042: Exports `randomULID(rng?: Rng): string` — Crockford Base32 encoded ULID. - REQ-RAND-043: Exports `randomNanoid(size?: number, rng?: Rng): string` — URL-safe, default 21 characters. ### Collection operations - REQ-RAND-050: Exports `shuffle(array: T[], rng?: Rng): T[]` — Fisher-Yates, immutable. - REQ-RAND-051: Exports `sample(array: T[], n: number, rng?: Rng): T[]` — n distinct elements. - REQ-RAND-052: Exports `choice(array: T[], rng?: Rng): T` — single random element. - REQ-RAND-053: Exports `weightedChoice(items: T[], weights: number[], rng?: Rng): T`. - REQ-RAND-054: Exports `weightedSample(items: T[], weights: number[], n: number, rng?: Rng): T[]` — weighted sampling without replacement. - REQ-RAND-055: All collection functions throw `RandomError("RANDOM.COLLECTION.EMPTY")` on empty input. ### Object/Record operations - REQ-RAND-060: Exports `randomKey(obj: T, rng?: Rng): keyof T`. - REQ-RAND-061: Exports `randomValue(obj: T, rng?: Rng): T[keyof T]`. - REQ-RAND-062: Exports `randomEntry(obj: T, rng?: Rng): [keyof T, T[keyof T]]`. - REQ-RAND-063: Exports `randomSubset(obj: T, n: number, rng?: Rng): Partial`. - REQ-RAND-064: All object functions throw `RandomError("RANDOM.OBJECT.EMPTY")` on empty object. ### Game primitives - REQ-RAND-070: Exports `coin(p?: number, rng?: Rng): boolean` — Bernoulli trial. Default `p = 0.5`. Throws if `p` outside `[0, 1]`. - REQ-RAND-071: Exports `dice(sides: number, rng?: Rng): number` — uniform integer in `[1, sides]`. - REQ-RAND-072: Exports `roll(count: number, sides: number, rng?: Rng): number` — sum of `count` dice. ### Error surface - REQ-RAND-080: Exports `RandomError extends SuaveplanError`. - REQ-RAND-081: Codes: `RANDOM.STRING.INVALID_OPTIONS`, `RANDOM.COLLECTION.EMPTY`, `RANDOM.COLLECTION.INSUFFICIENT`, `RANDOM.OBJECT.EMPTY`, `RANDOM.GAME.INVALID_SIDES`, `RANDOM.GAME.INVALID_PROBABILITY`. ### Quality - REQ-RAND-090: 100% statement + branch coverage. - REQ-RAND-091: `tests/no-disallowed.test.ts`: no `Math.random`, `Date.now`, `crypto.getRandomValues` outside `src/source/crypto-rng.ts`. - REQ-RAND-092: fast-check: all collection operations preserve input length constraints; UUID/ULID format invariants.