# Capability Spec Delta: crypto-core (crypto-core) **Package**: `@suaveplan/crypto-core` **Status**: PROPOSED > Every requirement below carries a `**Verified by:**` line at authoring time. No exceptions. ## MODIFIED Requirements ### Requirement: ByteSource and Rng are distinct contracts `@suaveplan/crypto-core` SHALL declare `ByteSource` as the package's callable byte producer (`type ByteSource = (n: number) => Uint8Array`), exported from `src/primitives/random-bytes/random-bytes.ts`. The package SHALL NOT alias `Rng` to `ByteSource` or to any callable shape — the canonical `Rng` (from `@suaveplan/types`) is an object with `nextUint32` / `nextFloat`, fundamentally different from a callable byte producer. The previous `type Rng = ByteSource` alias and the `defaultRng: ByteSource = defaultByteSource` constant SHALL both be removed. `@suaveplan/crypto-core` MAY re-export the canonical `Rng` from `@suaveplan/types` under the name `Rng` as a back-compat forwarder for one release cycle, with a prose comment naming the canonical import path and the removal change ID (`remove-deprecated-rng-aliases`). The forwarder MUST live at `src/primitives/random-bytes/random-bytes.ts` and be re-surfaced through the three barrels (`src/primitives/random-bytes/index.ts`, `src/primitives/index.ts`, `src/index.ts`). The `defaultRng` re-export SHALL NOT survive in any barrel — consumers use `defaultByteSource` directly. The `RandomBytesOptions` shape SHALL drop the legacy `rng?: ByteSource` field; only `byteSource?: ByteSource` remains. The internal selector simplifies from `options.byteSource ?? options.rng ?? defaultByteSource` to `options.byteSource ?? defaultByteSource`. Repo-internal grep confirms zero callsites pass `{ rng: ... }` to `randomBytes` today. `@suaveplan/crypto-core` SHALL preserve every other `ByteSource`-typed surface verbatim — engine constructors (`AeadEngine`, `SignEngine`, `AgreeEngine`, `SealedBoxEngine`, `AuthBoxEngine`), the `byteSource` injection on `generateKeypair` (ed25519, ecdsaP256, x25519), and the `defaultByteSource` constant. None of these reference `Rng`; they reference `ByteSource` by its real name. **Verified by:** `packages/crypto/crypto-core/src/primitives/random-bytes/random-bytes.ts` (no `type Rng = ByteSource`; no `defaultRng`; presence of `export type { Rng } from "@suaveplan/types"` back-compat re-export) AND `packages/crypto/crypto-core/src/primitives/random-bytes/random-bytes.test.ts::"randomBytes accepts byteSource option"` AND `packages/crypto/crypto-core/src/primitives/random-bytes/random-bytes.test.ts::"randomBytes rejects negative or non-integer n"` AND `bunx turbo typecheck test --filter=@suaveplan/crypto-core` (green with zero assertion edits) AND `bunx turbo test --filter=...@suaveplan/crypto-core` (every consumer green) AND repo-internal grep `grep -rn "defaultRng\b\|\.rng:\|, rng:" packages/crypto/crypto-core/src/ --include="*.ts"` returns zero results outside the documented back-compat re-export comment. #### Scenario: Rng re-export forwards canonical - **WHEN** a consumer writes `import type { Rng } from "@suaveplan/crypto-core"` - **THEN** the imported type is structurally identical to `import type { Rng } from "@suaveplan/types"` (an object, NOT a callable) #### Scenario: ByteSource remains the callable contract - **WHEN** a consumer writes `import type { ByteSource } from "@suaveplan/crypto-core"` - **THEN** the imported type is `(n: number) => Uint8Array` #### Scenario: defaultRng is removed - **WHEN** a consumer writes `import { defaultRng } from "@suaveplan/crypto-core"` - **THEN** `tsc` rejects with "has no exported member `defaultRng`" #### Scenario: RandomBytesOptions.rng field is removed - **WHEN** a consumer calls `randomBytes(32, { rng: customSource })` - **THEN** `tsc` rejects with "Object literal may only specify known properties, and `rng` does not exist in type `RandomBytesOptions`" #### Scenario: engines preserve ByteSource injection - **WHEN** a consumer calls `ed25519.generateKeypair({ byteSource: customSource })` - **THEN** the keypair is generated using `customSource(32)` (behavior unchanged)