Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,62 @@
# Capability: hash-primitives
## ADDED Requirements
### Package identity
- REQ-HASH-001: Package name is `@suaveplan/hash`, located at `packages/universal/hash`.
- REQ-HASH-002: Runtime deps: `@noble/hashes`, `@suaveplan/error`, `tslib`, `zod`. Zero browser/React/Node-only deps.
- REQ-HASH-003: Ships `"sideEffects": false`. All modules are individually subpath-exported for tree-shaking.
### Hash digests
- REQ-HASH-010: Exports `sha256(data: Uint8Array): Uint8Array` — 32-byte SHA-256 digest.
- REQ-HASH-011: Exports `sha384(data: Uint8Array): Uint8Array` — 48-byte SHA-384 digest.
- REQ-HASH-012: Exports `sha512(data: Uint8Array): Uint8Array` — 64-byte SHA-512 digest.
- REQ-HASH-013: Exports `HashAlgorithm = "SHA-256" | "SHA-384" | "SHA-512"`.
- REQ-HASH-014: Exports `hash(algo: HashAlgorithm, data: Uint8Array): Uint8Array` — algorithm dispatcher.
### HMAC
- REQ-HASH-020: Exports `hmac(algo: HashAlgorithm, key: Uint8Array, data: Uint8Array): Uint8Array`.
- REQ-HASH-021: Empty key is permitted (library-level; policy enforcement is the caller's responsibility).
### HKDF
- REQ-HASH-030: Exports `hkdf(algo: HashAlgorithm, ikm: Uint8Array, options: HkdfOptions): Uint8Array`.
- REQ-HASH-031: `HkdfOptions = { salt: Uint8Array; info: Uint8Array; length: number }`. All fields required.
- REQ-HASH-032: Throws `HashError("HASH.KDF.INVALID_PARAMS")` if `length <= 0` or `length > 255 * hashLen`.
### PBKDF2
- REQ-HASH-040: Exports `pbkdf2(algo: HashAlgorithm, password: Uint8Array, options: Pbkdf2Options): Uint8Array`.
- REQ-HASH-041: `Pbkdf2Options = { salt: Uint8Array; iterations: number; length: number }`.
- REQ-HASH-042: Throws `HashError("HASH.KDF.INVALID_PARAMS")` if `iterations < 600_000` (OWASP 2023 minimum for SHA-256). Same minimum for SHA-384/512 (conservative — these are also interactive-login strength minimums).
- REQ-HASH-043: Exports `PBKDF2_MIN_ITERATIONS = 600_000`.
### Argon2id
- REQ-HASH-050: Exports `argon2id(password: Uint8Array, options: Argon2idOptions): Uint8Array`.
- REQ-HASH-051: `Argon2idOptions = { salt: Uint8Array; timeCost: number; memoryCost: number; parallelism: number; length: number }`.
- REQ-HASH-052: Throws `HashError("HASH.KDF.INVALID_PARAMS")` per-field: `timeCost < 1`, `memoryCost < 8`, `parallelism < 1`, `length <= 0`. Each error's `context` includes `{ field, value, minimum }`.
- REQ-HASH-053: Exports `ARGON2ID_MIN_MEMORY_COST_KIB = 8`, `ARGON2ID_MIN_TIME_COST = 1`, `ARGON2ID_MIN_PARALLELISM = 1`.
### Encoding utilities
- REQ-HASH-060: Exports `toHex(bytes: Uint8Array): string` and `fromHex(hex: string): Uint8Array`.
- REQ-HASH-061: Exports `toBase64(bytes: Uint8Array): string`, `fromBase64(b64: string): Uint8Array`, `toBase64Url(bytes: Uint8Array): string`, `fromBase64Url(b64url: string): Uint8Array`.
- REQ-HASH-062: `fromHex`/`fromBase64`/`fromBase64Url` throw `HashError("HASH.ENCODING.INVALID_INPUT")` on malformed input.
### Error surface
- REQ-HASH-070: Exports `HashError extends SuaveplanError<HashCode>`.
- REQ-HASH-071: Error codes namespace: `HASH.KDF.INVALID_PARAMS`, `HASH.ALGORITHM.UNSUPPORTED`, `HASH.ENCODING.INVALID_INPUT`.
- REQ-HASH-072: No error message or context field contains raw key material or password bytes.
### Quality
- REQ-HASH-080: 100% statement + branch coverage (istanbul).
- REQ-HASH-081: fast-check property tests: determinism (same input → same output), HMAC known-vector (RFC 4231 vectors).
- REQ-HASH-082: mitata benchmarks: sha256/sha384/sha512 at 1 KiB and 1 MiB; argon2id at minimum params.
- REQ-HASH-083: Every `.ts` implementation file has a sibling `.md` (≥200 words).
- REQ-HASH-084: `tests/no-disallowed.test.ts` asserts no `Math.random`, `Date.now`, or `crypto.getRandomValues` in `src/`.