Files
2026-05-27 23:29:53 +01:00

170 lines
13 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Tasks: complete-rng-unification
## 0. Pre-flight (non-negotiable)
- [ ] 0.1 Confirm clean working tree (`git status` reports nothing) and no in-flight worktrees with uncommitted work (`git worktree list` then `git status` in 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.md` matches `find packages -maxdepth 3 -name package.json` count. 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/types` green at HEAD (baseline).
- [ ] 0.2 Confirm `bunx turbo typecheck test --filter=@suaveplan/testing` green at HEAD (baseline).
- [ ] 0.3 Confirm `bunx turbo typecheck test --filter=@suaveplan/crypto-core` green at HEAD (baseline).
- [ ] 0.4 Confirm `bunx turbo typecheck test --filter=@suaveplan/crypto` green at HEAD (baseline).
- [ ] 0.5 Confirm `bunx turbo typecheck test --filter=@suaveplan/mime` green 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.md` to add a "Single source of truth" section noting that `@suaveplan/types` is the only canonical home for `Rng` across 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.ts` line 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` / `seededRng` may omit.
- [ ] 2.3 Add `"@suaveplan/types": "workspace:^"` to `packages/testing/testing/package.json` `dependencies` (rule 8 exception: testing-infra may depend on `@suaveplan/types` for types-only — confirm byte-size guard still passes).
- [ ] 2.4 Replace `export interface Rng { ... }` with:
```ts
// 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 = { ... }` and `seededRng(seed): Rng` still typecheck against the canonical (they provide only the required members).
- [ ] 2.6 Update sibling `context.md` API reference: note `Rng` is now a re-export of canonical; cross-link to `@suaveplan/types`.
- [ ] 2.7 No barrel edits needed — `src/index.ts:61` `export 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 the `rng` field.
- line 62: `const source = options.byteSource ?? options.rng ?? defaultByteSource;` — simplify to `options.byteSource ?? defaultByteSource`.
- [ ] 3.2 Add back-compat re-export at the bottom of `random-bytes.ts`:
```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/types` is in `packages/crypto/crypto-core/package.json` `dependencies` (it already is per `MANIFEST.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`.
- [ ] 3.5 Update barrel `packages/crypto/crypto-core/src/primitives/index.ts` — same: drop `defaultRng`, keep `Rng` forwarding canonical.
- [ ] 3.6 Update barrel `packages/crypto/crypto-core/src/index.ts` — same: drop `defaultRng`, keep `Rng` forwarding canonical.
- [ ] 3.7 Update sibling `random-bytes.md`: drop `Rng` and `defaultRng` from local API reference; add "Implementation Notes" section explaining the type-class distinction (canonical `Rng` is an object; `ByteSource` is a callable; the local `Rng` is now a back-compat re-export of the canonical, not the legacy callable alias).
- [ ] 3.8 Repo-internal callsite check — confirm no `crypto-core` test or impl file uses `defaultRng` or `RandomBytesOptions.rng`:
```bash
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 `Rng` and `defaultRng` re-exports in `packages/crypto/crypto/src/index.ts` (currently re-exported from `@suaveplan/crypto-core` block).
- [ ] 4.2 Keep the `Rng` re-export (it now forwards canonical via `crypto-core`'s back-compat re-export).
- [ ] 4.3 Drop the `defaultRng` re-export.
- [ ] 4.4 Repo-internal callsite check — confirm no `crypto` test or impl file uses `defaultRng`:
```bash
grep -rn "defaultRng\b" packages/crypto/crypto/src/ --include="*.ts"
```
- [ ] 4.5 If any `.md` in `packages/crypto/crypto/src/` mentions `Rng` or `defaultRng`, update to reference `@suaveplan/types` (canonical) and `defaultByteSource` (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.ts` line 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 is `type`, not `export type`) — name collision is internal only, but renaming eliminates future confusion.
- [ ] 5.4 Update sibling `from-stream.md` if it mentions `ByteSource`.
- [ ] 5.5 Confirm `from-stream-reader.ts` (which uses `ReadableStream<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.md` delta with `## MODIFIED Requirements` block on the canonical-Rng requirement, adding the single-source-of-truth clause.
- [ ] 6.2 Author `specs/testing/spec.md` delta with `## MODIFIED Requirements` block documenting `Rng` is now a back-compat re-export.
- [ ] 6.3 Author `specs/crypto-core/spec.md` delta with `## MODIFIED Requirements` documenting: `Rng` is canonical re-export; `defaultRng` is removed; `RandomBytesOptions.rng` field is removed; `ByteSource` is preserved under its real name (callable byte producer, distinct from `Rng`).
- [ ] 6.4 Author `specs/crypto/spec.md` delta with `## MODIFIED Requirements` documenting the forwarder barrel update.
- [ ] 6.5 Author `specs/mime/spec.md` delta with `## MODIFIED Requirements` documenting the `ByteSource` → `StreamByteSource` rename.
- [ ] 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:
```bash
grep -rln "interface Rng\b\|type Rng\s*=\|class Rng\b\|RngLike\b\|RandomSource\b" \
packages/ --include="*.ts" --exclude-dir=dist --exclude-dir=node_modules
```
Allowed hits:
- `packages/core/types/src/rng.ts` (canonical declaration)
- `packages/random/pseudo-random/src/types/seeded-rng.types.ts` (legitimate `SeededRng extends Rng`)
- back-compat `export type { Rng } from "@suaveplan/types"` forwarder lines in `crypto-core/random-bytes`, `crypto-core/primitives/index`, `crypto-core/primitives/random-bytes/index`, `crypto-core/index`, `crypto/index`, `testing/context`
- [ ] 7.2 Repo-wide `ByteSource` grep — confirm zero unintended renames; only the `mime` file-scope occurrence has changed.
- [ ] 7.3 Repo-wide `defaultRng` grep returns zero hits in genesis source (it remains in `@suaveplan/crypto-rsa/src/encrypt/default-rng.ts` as a `function 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 `.ts` edited has its sibling `.md` updated 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 `## Migration` note is authored in `proposal.md` (already done) — verify the search command works and produces the expected callsites.
- [ ] 8.3 Update root `MIGRATION.md` with the per-package migration note (canonical `Rng` import path, `defaultRng` → `defaultByteSource`, `RandomBytesOptions.rng` → `byteSource`).
- [ ] 8.4 Repo-wide consumer scan:
```bash
grep -rln "from ['\"]@suaveplan/\(crypto-core\|crypto\|testing\)['\"]" packages/ \
| xargs grep -l "Rng\b" 2>/dev/null
```
Every 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.md` dep graph gains one edge (`@suaveplan/testing → @suaveplan/types`). Run `bun scripts/folder-reorg/generate-manifest.ts`.
- [ ] 9.2 `STATUS.md` unchanged (no new pending → completed transitions).
- [ ] 9.3 `SUMMARY.md` — update `@suaveplan/types`, `@suaveplan/testing`, `@suaveplan/crypto-core`, `@suaveplan/crypto` paragraphs to mention the canonical `Rng` clause 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.md` delta into `openspec/specs/types/spec.md`.
- [ ] 10.2 Fold `specs/testing/spec.md` delta into `openspec/specs/testing/spec.md`.
- [ ] 10.3 Fold `specs/crypto-core/spec.md` delta into `openspec/specs/crypto-core/spec.md`.
- [ ] 10.4 Fold `specs/crypto/spec.md` delta into `openspec/specs/crypto/spec.md`.
- [ ] 10.5 Fold `specs/mime/spec.md` delta into `openspec/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-aliases` change to track removal of the back-compat re-export forwarders after one release cycle.