13 KiB
Tasks: complete-rng-unification
0. Pre-flight (non-negotiable)
- 0.1 Confirm clean working tree (
git statusreports nothing) and no in-flight worktrees with uncommitted work (git worktree listthengit statusin each) - 0.2 If any worktrees exist under
.claude/worktrees/, account for each one: still-active agent, work-pending-merge, or stale-and-prune. Stale worktrees MUST be removed (git worktree remove) before opening a new one — code that has been lost twice on main is the failure mode this guards against. - 0.3 Confirm the package set in
MANIFEST.mdmatchesfind packages -maxdepth 3 -name package.jsoncount. Drift here means a prior change archived without regenerating the manifest.
0. Pre-flight (mandatory before any edit)
- 0.1 Confirm
bunx turbo typecheck test --filter=@suaveplan/typesgreen at HEAD (baseline). - 0.2 Confirm
bunx turbo typecheck test --filter=@suaveplan/testinggreen at HEAD (baseline). - 0.3 Confirm
bunx turbo typecheck test --filter=@suaveplan/crypto-coregreen at HEAD (baseline). - 0.4 Confirm
bunx turbo typecheck test --filter=@suaveplan/cryptogreen at HEAD (baseline). - 0.5 Confirm
bunx turbo typecheck test --filter=@suaveplan/mimegreen at HEAD (baseline). - 0.6 Re-run the exhaustive grep documented in
proposal.md§ Audit and confirm zero NEW matches have appeared since this proposal was drafted.
1. @suaveplan/types — spec-only tightening
- 1.1 Update
packages/core/types/src/rng.mdto add a "Single source of truth" section noting that@suaveplan/typesis the only canonical home forRngacross the monorepo and the permitted forms of downstream redeclaration (consume-direct, extend, or distinct-concept-under-distinct-name). - 1.2 No code change to
packages/core/types/src/rng.ts(shape is already correct). - 1.3
bunx turbo typecheck test --filter=@suaveplan/types— green. - 1.4
bunx turbo test --filter=...@suaveplan/types— foundation dependent sweep green (mandatory per §13 step 10).
2. @suaveplan/testing — migrate Rng interface to re-export
-
2.1 Locate local declaration:
packages/testing/testing/src/context/context.tsline 45 (export interface Rng { nextUint32(): number; nextFloat(): number }). -
2.2 Confirm structural compatibility — required members are an exact subset of canonical; canonical adds two OPTIONAL members which existing
cryptoRng/seededRngmay omit. -
2.3 Add
"@suaveplan/types": "workspace:^"topackages/testing/testing/package.jsondependencies(rule 8 exception: testing-infra may depend on@suaveplan/typesfor types-only — confirm byte-size guard still passes). -
2.4 Replace
export interface Rng { ... }with:// Back-compat re-export of @suaveplan/types' canonical Rng. Prefer importing // Rng from @suaveplan/types directly; this forwarder will be removed in the // follow-up `remove-deprecated-rng-aliases` change. export type { Rng } from "@suaveplan/types"; -
2.5 Confirm
cryptoRng: Rng = { ... }andseededRng(seed): Rngstill typecheck against the canonical (they provide only the required members). -
2.6 Update sibling
context.mdAPI reference: noteRngis now a re-export of canonical; cross-link to@suaveplan/types. -
2.7 No barrel edits needed —
src/index.ts:61export type { Clock, Rng } from "./context/context.js"continues to forward correctly. -
2.8
bunx turbo typecheck --filter=@suaveplan/testing— green. -
2.9
bunx turbo test --filter=@suaveplan/testing— green, zero assertion edits. -
2.10
bunx turbo test:coverage --filter=@suaveplan/testing— 100/100/100/100 preserved. -
2.11 Dependent sweep:
bunx turbo test --filter=...@suaveplan/testing— every test in the monorepo flows through@suaveplan/testing, must be green.
3. @suaveplan/crypto-core — drop misleading Rng alias + defaultRng
-
3.1 Locate local declarations in
packages/crypto/crypto-core/src/primitives/random-bytes/random-bytes.ts:- line 9:
export type ByteSource = (n: number) => Uint8Array;— KEEP. - line 12:
export type Rng = ByteSource;— REMOVE. - line 19:
export const defaultByteSource: ByteSource = ...— KEEP. - line 36:
export const defaultRng: ByteSource = defaultByteSource;— REMOVE. - line 38–41:
RandomBytesOptions { byteSource?: ByteSource; rng?: ByteSource }— drop therngfield. - line 62:
const source = options.byteSource ?? options.rng ?? defaultByteSource;— simplify tooptions.byteSource ?? defaultByteSource.
- line 9:
-
3.2 Add back-compat re-export at the bottom of
random-bytes.ts:// Back-compat re-export of @suaveplan/types' canonical Rng. Prefer importing // Rng from @suaveplan/types directly. This forwarder exists for one release // cycle — the legacy local `type Rng = ByteSource` alias was structurally // incompatible with canonical (callable vs object) and has been removed. // The follow-up `remove-deprecated-rng-aliases` change will delete this line. export type { Rng } from "@suaveplan/types"; -
3.3 Confirm
@suaveplan/typesis inpackages/crypto/crypto-core/package.jsondependencies(it already is perMANIFEST.md). -
3.4 Update barrel
packages/crypto/crypto-core/src/primitives/random-bytes/index.ts:- keep
type ByteSource,defaultByteSource,type RandomBytesOptions,randomBytes. - keep
type Rng(now forwards canonical via the back-compat re-export). - drop
defaultRng.
- keep
-
3.5 Update barrel
packages/crypto/crypto-core/src/primitives/index.ts— same: dropdefaultRng, keepRngforwarding canonical. -
3.6 Update barrel
packages/crypto/crypto-core/src/index.ts— same: dropdefaultRng, keepRngforwarding canonical. -
3.7 Update sibling
random-bytes.md: dropRnganddefaultRngfrom local API reference; add "Implementation Notes" section explaining the type-class distinction (canonicalRngis an object;ByteSourceis a callable; the localRngis now a back-compat re-export of the canonical, not the legacy callable alias). -
3.8 Repo-internal callsite check — confirm no
crypto-coretest or impl file usesdefaultRngorRandomBytesOptions.rng:grep -rn "defaultRng\b\|\.rng:\|, rng:" packages/crypto/crypto-core/src/ --include="*.ts" -
3.9
bunx turbo typecheck --filter=@suaveplan/crypto-core— green. -
3.10
bunx turbo test --filter=@suaveplan/crypto-core— green, zero assertion edits. -
3.11
bunx turbo test:coverage --filter=@suaveplan/crypto-core— 100/100/100/100 preserved. -
3.12 Dependent sweep:
bunx turbo test --filter=...@suaveplan/crypto-core— every consumer (crypto,crypto-rsa,crypto-vault,crypto-keys,vault,vault-sync,webauthn,crypto-cli,crypto-bin,crypto-sodium,crypto-browser) green.
4. @suaveplan/crypto — update forwarder barrel
-
4.1 Locate
RnganddefaultRngre-exports inpackages/crypto/crypto/src/index.ts(currently re-exported from@suaveplan/crypto-coreblock). -
4.2 Keep the
Rngre-export (it now forwards canonical viacrypto-core's back-compat re-export). -
4.3 Drop the
defaultRngre-export. -
4.4 Repo-internal callsite check — confirm no
cryptotest or impl file usesdefaultRng:grep -rn "defaultRng\b" packages/crypto/crypto/src/ --include="*.ts" -
4.5 If any
.mdinpackages/crypto/crypto/src/mentionsRngordefaultRng, update to reference@suaveplan/types(canonical) anddefaultByteSource(correct name for the dropped alias). -
4.6
bunx turbo typecheck --filter=@suaveplan/crypto— green. -
4.7
bunx turbo test --filter=@suaveplan/crypto— green. -
4.8
bunx turbo test:coverage --filter=@suaveplan/crypto— 100/100/100/100 preserved.
5. @suaveplan/mime — rename file-scope ByteSource
- 5.1 Locate
packages/data/mime/src/detection/from-stream.tsline 19:type ByteSource = ReadableStream<Uint8Array> | AsyncIterable<Uint8Array>. - 5.2 Rename to
StreamByteSource; update the single reference at line 30 (source: StreamByteSource). - 5.3 Confirm the type is NOT exported from
from-stream.ts(it istype, notexport type) — name collision is internal only, but renaming eliminates future confusion. - 5.4 Update sibling
from-stream.mdif it mentionsByteSource. - 5.5 Confirm
from-stream-reader.ts(which usesReadableStream<Uint8Array> | AsyncIterable<Uint8Array>inline) is unaffected. - 5.6
bunx turbo typecheck --filter=@suaveplan/mime— green. - 5.7
bunx turbo test --filter=@suaveplan/mime— green. - 5.8
bunx turbo test:coverage --filter=@suaveplan/mime— 100/100/100/100 preserved.
6. Spec deltas
- 6.1 Author
specs/types/spec.mddelta with## MODIFIED Requirementsblock on the canonical-Rng requirement, adding the single-source-of-truth clause. - 6.2 Author
specs/testing/spec.mddelta with## MODIFIED Requirementsblock documentingRngis now a back-compat re-export. - 6.3 Author
specs/crypto-core/spec.mddelta with## MODIFIED Requirementsdocumenting:Rngis canonical re-export;defaultRngis removed;RandomBytesOptions.rngfield is removed;ByteSourceis preserved under its real name (callable byte producer, distinct fromRng). - 6.4 Author
specs/crypto/spec.mddelta with## MODIFIED Requirementsdocumenting the forwarder barrel update. - 6.5 Author
specs/mime/spec.mddelta with## MODIFIED Requirementsdocumenting theByteSource→StreamByteSourcerename. - 6.6 Every requirement carries
**Verified by:**line at authoring time.
7. Repo-wide verification gate
-
7.1 Repo-wide grep returns exactly the documented set:
grep -rln "interface Rng\b\|type Rng\s*=\|class Rng\b\|RngLike\b\|RandomSource\b" \ packages/ --include="*.ts" --exclude-dir=dist --exclude-dir=node_modulesAllowed hits:
packages/core/types/src/rng.ts(canonical declaration)packages/random/pseudo-random/src/types/seeded-rng.types.ts(legitimateSeededRng extends Rng)- back-compat
export type { Rng } from "@suaveplan/types"forwarder lines incrypto-core/random-bytes,crypto-core/primitives/index,crypto-core/primitives/random-bytes/index,crypto-core/index,crypto/index,testing/context
-
7.2 Repo-wide
ByteSourcegrep — confirm zero unintended renames; only themimefile-scope occurrence has changed. -
7.3 Repo-wide
defaultRnggrep returns zero hits in genesis source (it remains in@suaveplan/crypto-rsa/src/encrypt/default-rng.tsas afunction defaultRng(): Rng— that is correct usage, not the dropped alias). -
7.4
bunx turbo lint typecheck --filter=...(full repo) — green.
8. Doc-drift + behaviour-change propagation
-
8.1 Per CLAUDE.md §4a: every
.tsedited has its sibling.mdupdated in the same change set (covered by tasks 1.1, 2.6, 3.7, 4.5, 5.4). -
8.2 Per CLAUDE.md §13a: the
## Migrationnote is authored inproposal.md(already done) — verify the search command works and produces the expected callsites. -
8.3 Update root
MIGRATION.mdwith the per-package migration note (canonicalRngimport path,defaultRng→defaultByteSource,RandomBytesOptions.rng→byteSource). -
8.4 Repo-wide consumer scan:
grep -rln "from ['\"]@suaveplan/\(crypto-core\|crypto\|testing\)['\"]" packages/ \ | xargs grep -l "Rng\b" 2>/dev/nullEvery hit either continues to compile via the back-compat forwarder OR is updated to canonical import in this change set.
9. Root-doc refresh + markdownlint
- 9.1 No package add/remove;
MANIFEST.mddep graph gains one edge (@suaveplan/testing → @suaveplan/types). Runbun scripts/folder-reorg/generate-manifest.ts. - 9.2
STATUS.mdunchanged (no new pending → completed transitions). - 9.3
SUMMARY.md— update@suaveplan/types,@suaveplan/testing,@suaveplan/crypto-core,@suaveplan/cryptoparagraphs to mention the canonicalRngclause and the back-compat forwarder. - 9.4
MIGRATION.md— updated per task 8.3. - 9.5
bunx markdownlint-cli2 --fix— green.
10. Fold + archive
- 10.1 Fold
specs/types/spec.mddelta intoopenspec/specs/types/spec.md. - 10.2 Fold
specs/testing/spec.mddelta intoopenspec/specs/testing/spec.md. - 10.3 Fold
specs/crypto-core/spec.mddelta intoopenspec/specs/crypto-core/spec.md. - 10.4 Fold
specs/crypto/spec.mddelta intoopenspec/specs/crypto/spec.md. - 10.5 Fold
specs/mime/spec.mddelta intoopenspec/specs/mime/spec.md. - 10.6 Move
openspec/changes/complete-rng-unification/→openspec/archive/<yyyy-mm-dd>-complete-rng-unification/. - 10.7 Open the follow-up
remove-deprecated-rng-aliaseschange to track removal of the back-compat re-export forwarders after one release cycle.