From 38457973c3d7b8df85264e540acf03c7a8bc9d3a Mon Sep 17 00:00:00 2001 From: "shoney.arickathil" Date: Sat, 22 Aug 2026 17:34:27 +0200 Subject: [PATCH] =?UTF-8?q?docs:=20story=2034=20=E2=80=94=20crypto=20built?= =?UTF-8?q?ins=20(digests=20+=20HMAC)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - SHA-1 (WS-handshake hard req, RFC 6455 worked example as acceptance), SHA-256, HMAC-SHA256 over Bytes; hand-rolled C per doctrine, FIPS/RFC vector fixtures; four forks recorded (namespace, shape, source, file) - gates chain item 24; digest floor for held 21 + ETag row; 24's dependency note repointed; board + table rows (held seqs bumped) Co-Authored-By: Claude Fable 5 --- docs/stories/00-status.md | 1 + .../language-runtime-database/00-story.md | 17 +-- .../refine/34-crypto-builtins.md | 101 ++++++++++++++++++ 3 files changed, 111 insertions(+), 8 deletions(-) create mode 100644 docs/stories/language-runtime-database/refine/34-crypto-builtins.md diff --git a/docs/stories/00-status.md b/docs/stories/00-status.md index 4e7e192..2dc68a9 100644 --- a/docs/stories/00-status.md +++ b/docs/stories/00-status.md @@ -243,6 +243,7 @@ that sequences its tasks. Read one, approve, then the next starts. | 23 | [io_uring group-commit](language-runtime-database/refine/23-io-uring-commit.md) | ⬜ fifth in chain, after stage 3 + 22 | | 32 | [WAL checkpoint](language-runtime-database/refine/32-wal-checkpoint.md) | ⬜ last in chain, after 23 — disk reclamation + bounded replay (story written 2026-08-21) | | 33 | [Single-file store](language-runtime-database/refine/33-single-file-db.md) | ⬜ off-chain, small — `WO_DATA=.db` file form; driver-only (story written 2026-08-22) | +| 34 | [Crypto builtins](language-runtime-database/refine/34-crypto-builtins.md) | ⬜ off-chain but GATES 24 (WS handshake needs SHA-1) — digests + HMAC as vector-verified C builtins (story written 2026-08-22) | | 20 | [Cross-program tables](language-runtime-database/hold/20-cross-program-tables.md) | ⏸ hold (2026-08-21); channel done (branch ipc-attach keeps its manifest) | | 21 | [Keypair attach auth](language-runtime-database/hold/21-keypair-attach-auth.md) | ⏸ hold (2026-08-21); crypto+handshake done (branch keypair-auth keeps its manifest) | | 25 | [HTTP service layer](../superpowers/plans/2026-08-01-http-service-layer.md) | ⏸ hold (2026-08-21) — story file removed; the plan doc remains | diff --git a/docs/stories/language-runtime-database/00-story.md b/docs/stories/language-runtime-database/00-story.md index 594fdaa..0c5de50 100644 --- a/docs/stories/language-runtime-database/00-story.md +++ b/docs/stories/language-runtime-database/00-story.md @@ -108,14 +108,15 @@ still pending IS the runtime-concurrency chain; order: | 19 | 23 | [io_uring group-commit](refine/23-io-uring-commit.md) | WAL WRITE+FSYNC chains on the arc's per-shard rings; fsync fallback kept (after 22 + the arc). *(was 9f)* | | 20 | 32 | [WAL checkpoint](refine/32-wal-checkpoint.md) | **NEW 2026-08-21** (stage-3 guarantee refinement found the hole) — the WAL is append-only forever: snapshot + truncate reclaims disk and bounds replay time; every durability guarantee byte-identical; crash mid-checkpoint recovers from the previous snapshot + full tail. After 23 (composes with group-commit); RAM slot-reuse already contracted in `04-db-binding.md`. | | 21 | 33 | [Single-file store](refine/33-single-file-db.md) | **NEW 2026-08-22** — `WO_DATA=.db`: a file path IS the wal (the store already lives in exactly one file; this makes the surface say so). Driver-only, independent of the chain; composes with 32's rename-swap. | -| 22 | 25 | [HTTP service layer](../../superpowers/plans/2026-08-01-http-service-layer.md) | `service` blocks lower onto the framework (after 9b + 20 by their own precedence notes). **HELD 2026-08-21** — story file removed; the plan doc remains. *(was 10)* | -| 23 | 18 | [framework v2: memory-rich features](hold/18-memory-db-features.md) | spec+plan approved: TTL cache, @table flags, durable job queue, `transaction { }` over the WAL's staged batch. **Demoted from seq 14**: more surface on a framework with one consumer, and the cache still stores `Text` because there are no generics | -| 24 | 27 | [Query grammar corpus](hold/27-query-grammar-corpus.md) | grow the query grammar from real corpora; likely collapses to "confirm `len(query)` + add `exists`"; precedes 28. *(was 9g)* | -| 25 | 26 | [Blue-green deploy](hold/26-blue-green-deploy.md) | two VM slots, in-runtime compile, atomic switch, resident rollback (plan authored after 9 + 25). *(was 12)* | -| 26 | 20 | [Cross-program tables](hold/20-cross-program-tables.md) | attach to a running program's database over local IPC; owner stays the single writer (channel half-built). **Demoted from seq 16**: new distribution surface while there is no TLS, no crypto, and the multi-shard DB still traps. *(was 9c)* | -| 27 | 21 | [Keypair attach auth](hold/21-keypair-attach-auth.md) | program identity is a keypair; mutual challenge–response at attach (crypto half-built; plan folds into 20's). **Demoted with 20** — and it needs crypto primitives that do not exist. *(was 9d)* | -| 28 | 28 | [skillhost host workload](hold/28-skillhost-host-workload.md) | host-shaped driving workload naming runtime gaps — demoted with the framework goal. *(was 14)* | -| 29 | 29 | [Compile-time metaprogramming](hold/29-compile-time-metaprogramming.md) | `@derive(...)` from class-table metadata; held with the parked drain by the 2026-08-08 scope directive. *(was 13)* | +| 22 | 34 | [Crypto builtins](refine/34-crypto-builtins.md) | **NEW 2026-08-22** — SHA-1/SHA-256/HMAC-SHA256 as C builtins over Bytes (no bitwise ops in the language, hand-rolled per doctrine, vector-verified). GATES 24's WS handshake; digest floor for held 21 and the ETag row. | +| 23 | 25 | [HTTP service layer](../../superpowers/plans/2026-08-01-http-service-layer.md) | `service` blocks lower onto the framework (after 9b + 20 by their own precedence notes). **HELD 2026-08-21** — story file removed; the plan doc remains. *(was 10)* | +| 24 | 18 | [framework v2: memory-rich features](hold/18-memory-db-features.md) | spec+plan approved: TTL cache, @table flags, durable job queue, `transaction { }` over the WAL's staged batch. **Demoted from seq 14**: more surface on a framework with one consumer, and the cache still stores `Text` because there are no generics | +| 25 | 27 | [Query grammar corpus](hold/27-query-grammar-corpus.md) | grow the query grammar from real corpora; likely collapses to "confirm `len(query)` + add `exists`"; precedes 28. *(was 9g)* | +| 26 | 26 | [Blue-green deploy](hold/26-blue-green-deploy.md) | two VM slots, in-runtime compile, atomic switch, resident rollback (plan authored after 9 + 25). *(was 12)* | +| 27 | 20 | [Cross-program tables](hold/20-cross-program-tables.md) | attach to a running program's database over local IPC; owner stays the single writer (channel half-built). **Demoted from seq 16**: new distribution surface while there is no TLS, no crypto, and the multi-shard DB still traps. *(was 9c)* | +| 28 | 21 | [Keypair attach auth](hold/21-keypair-attach-auth.md) | program identity is a keypair; mutual challenge–response at attach (crypto half-built; plan folds into 20's). **Demoted with 20** — and it needs crypto primitives that do not exist. *(was 9d)* | +| 29 | 28 | [skillhost host workload](hold/28-skillhost-host-workload.md) | host-shaped driving workload naming runtime gaps — demoted with the framework goal. *(was 14)* | +| 30 | 29 | [Compile-time metaprogramming](hold/29-compile-time-metaprogramming.md) | `@derive(...)` from class-table metadata; held with the parked drain by the 2026-08-08 scope directive. *(was 13)* | | ✅ | 17 | [library projects + `internal/`](done/17-library-projects-internal.md) | **LANDED 2026-08-20** — `kind = "library"` + entry-less check mode (retires the `--emit` workaround) and Go's `internal/` rule as WO-E108 at the consumer's `use`; driver-only, VM/GC untouched. `just web-app` 26/0 | diff --git a/docs/stories/language-runtime-database/refine/34-crypto-builtins.md b/docs/stories/language-runtime-database/refine/34-crypto-builtins.md new file mode 100644 index 0000000..4b060ab --- /dev/null +++ b/docs/stories/language-runtime-database/refine/34-crypto-builtins.md @@ -0,0 +1,101 @@ +--- +iteration: "34" +status: refine +--- + +# Iteration 34 — crypto builtins: digests and HMAC in the runtime + +> Format: `product/story-iteration-template`. Part of +> [Story — one language, one runtime, one database, one binary](../00-story.md). +> +> **Inserted 2026-08-22** — the framework ledger's oldest unowned gap +> gets an owner. The language has NO bitwise operators (a settled +> surface decision), so digests cannot be written in `.wo`; the +> ledger's recorded resolution stands: hand-rolled C builtins in the +> runtime — the libc-only doctrine permits hand-rolled crypto, and the +> code is bounded and well-specified. Off the concurrency chain but +> **gates chain position 4**: iteration 24's WebSocket handshake needs +> SHA-1 before chat can land. + +## Why this iteration exists + +Four consumers already wait on it, none able to proceed: +[iteration 24](24-chat-websocket-workload.md)'s upgrade handshake +(`Sec-WebSocket-Accept` = base64(SHA-1(key + GUID)) — SHA-1 +specifically, not a choice); the framework's ETag/conditional-request +row (wants a content hash); HMAC-signed tokens the auth core can grow; +and held [iteration 21](../hold/21-keypair-attach-auth.md), whose +challenge–response needs primitives that "do not exist" (its demotion +note). Bytes and base64 landed with iteration 19 — the carriers exist, +only the digests are missing. + +## Goals + +- **Digest builtins over Bytes**: SHA-1 (the WS handshake's hard + requirement), SHA-256 (the modern default for ETag/HMAC), each + `Bytes -> Bytes`, streaming not required (whole-value, like every + existing builtin). +- **HMAC-SHA256** (`key: Bytes, msg: Bytes -> Bytes`) — the one + composition real services need (signed tokens, webhook signatures); + writing HMAC in `.wo` is impossible for the same no-bitwise reason. +- **Test vectors are the acceptance**: FIPS 180 / RFC 2202 / RFC 4231 + vectors in a corpus fixture — a digest that "looks right" is worth + nothing. +- **The contract doc row**: names, arities, Bytes-in/Bytes-out, and the + explicit note that SHA-1 exists for protocol compatibility (WS), not + for new designs. + +## Acceptance Criteria (draft — the spec refines) + +- **Given** the published test vectors for SHA-1, SHA-256, and + HMAC-SHA256, **when** the corpus fixture runs them through the + builtins, **then** every output matches byte-for-byte (via the + existing base64/Bytes surface). +- **Given** the WS handshake's worked example from RFC 6455 + (`dGhlIHNhbXBsZSBub25jZQ==` → `s3pPLMBiTxaQ9kYGzzhZRbK+xOo=`), + **when** composed in pure `.wo` from `sha1` + `base64_encode`, + **then** the exact accept token comes out — iteration 24's handshake + is provably one expression away. +- **Given** the full battery, **when** it runs, **then** nothing + regresses — new builtin ids only, no opcode, no `.wob` version bump + (the iteration-19/`time.ticks` precedent). + +## Out Of Scope + +- Asymmetric crypto (ed25519 signatures/keypairs) — held iteration 21's + spec decides what it needs when it unholds; this iteration lays the + digest floor it will stand on. +- TLS — permanently the proxy's job (framework doctrine). +- CRC32 — the ledger lists it, but no consumer is blocked on it; it + joins only if 24's spec finds a real need (rejecting speculative + surface). +- A password-hashing story (bcrypt/argon2) — no workload asks yet. +- Bitwise operators in the language — a separate, bigger surface + decision this iteration deliberately routes around. + +## Info + +Forks the spec must settle: + +1. **The namespace.** The reserved stdlib namespaces are exactly + `fs`/`proc`/`net`/`time`/`json`/`env` (compiler-enforced list) — a + new `crypto` namespace touches that list plus the typechecker + table, or the functions ride an existing namespace. Leaning: a real + `crypto` namespace (the list exists to be grown deliberately; this + is deliberate). +2. **Surface shape**: `crypto.sha1(b: Bytes) -> Bytes`, + `crypto.sha256(b: Bytes) -> Bytes`, + `crypto.hmac_sha256(key: Bytes, msg: Bytes) -> Bytes` — Text + convenience overloads rejected (the caller has `bytes_of_text`). +3. **Implementation source**: hand-rolled C from the FIPS pseudocode + (~200 lines for both digests; well-trodden, vector-verified) — the + doctrine's shape. No linking against OpenSSL, ever. +4. **Where the code lives**: `runtime/src/crypto.c` beside sysio, or + inside builtin.c — file layout, the executor decides. + +## Proposed Solution + +Brainstorm → (small) spec settling the four forks → implement with the +`time.ticks` slice's shape (ids, one table row per compiler surface, +contract-doc rows, vector fixtures). Lands any time before iteration +24's spec; independent of 31/22/23.