From 526a83710229930ca1d903100e9999d266b5cc58 Mon Sep 17 00:00:00 2001 From: "shoney.arickathil" Date: Sat, 22 Aug 2026 17:37:12 +0200 Subject: [PATCH] =?UTF-8?q?docs:=20story=2035=20=E2=80=94=20net=20runtime?= =?UTF-8?q?=20seams=20(deadlines,=20unix=20sockets,=20peer=20addr)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - owns the framework ledger's three seam rows; deadlines compose with the arc's park plane (POLL_ADD+TIMEOUT fork recorded); framework knobs explicitly out of scope; stalled-client soak in acceptance - board + table rows (held seqs bumped); pairs naturally with 24 Co-Authored-By: Claude Fable 5 --- docs/stories/00-status.md | 1 + .../language-runtime-database/00-story.md | 17 +-- .../refine/35-net-runtime-seams.md | 107 ++++++++++++++++++ 3 files changed, 117 insertions(+), 8 deletions(-) create mode 100644 docs/stories/language-runtime-database/refine/35-net-runtime-seams.md diff --git a/docs/stories/00-status.md b/docs/stories/00-status.md index 2dc68a9..76a1779 100644 --- a/docs/stories/00-status.md +++ b/docs/stories/00-status.md @@ -244,6 +244,7 @@ that sequences its tasks. Read one, approve, then the next starts. | 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) | +| 35 | [net runtime seams](language-runtime-database/refine/35-net-runtime-seams.md) | ⬜ off-chain — fd deadlines on the park plane, Unix sockets, peer address; owns the ledger's three 🔧 rows (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 0c5de50..d7b515e 100644 --- a/docs/stories/language-runtime-database/00-story.md +++ b/docs/stories/language-runtime-database/00-story.md @@ -109,14 +109,15 @@ still pending IS the runtime-concurrency chain; order: | 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 | 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)* | +| 23 | 35 | [net runtime seams](refine/35-net-runtime-seams.md) | **NEW 2026-08-22** — the ledger's three 🔧 rows owned: fd deadlines composing with the park plane, Unix-socket listeners, peer address (trusted-proxy check). Framework knobs stay framework slices; pairs naturally with 24 (dead-client eviction). | +| 24 | 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)* | +| 25 | 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 | +| 26 | 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)* | +| 27 | 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)* | +| 28 | 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)* | +| 29 | 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)* | +| 30 | 28 | [skillhost host workload](hold/28-skillhost-host-workload.md) | host-shaped driving workload naming runtime gaps — demoted with the framework goal. *(was 14)* | +| 31 | 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/35-net-runtime-seams.md b/docs/stories/language-runtime-database/refine/35-net-runtime-seams.md new file mode 100644 index 0000000..69bb229 --- /dev/null +++ b/docs/stories/language-runtime-database/refine/35-net-runtime-seams.md @@ -0,0 +1,107 @@ +--- +iteration: "35" +status: refine +--- + +# Iteration 35 — `net` runtime seams: timeouts, Unix sockets, peer address + +> 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 three 🔧 rows get one +> owner: "Read/write/idle timeouts — `net` has no timeout surface", +> "Unix socket binding — `net.listen` is TCP-only", and "Trusted-proxy +> client IP — needs a peer-address runtime seam". Each is a small +> builtin-surface addition; the framework knobs built ON them stay +> framework slices. Off the concurrency chain; no chain item depends on +> it, but a production-shaped deployment (proxy in front, sockets not +> ports, slow-client defense) needs all three. + +## Why this iteration exists + +The framework cannot defend against a slow client (no read deadline — +one stalled socket parks a fiber forever), cannot sit behind a +same-host proxy the idiomatic way (Unix socket beats a loopback port), +and cannot TRUST `X-Forwarded-For` (parsing is expressible in `.wo` +today, but verifying the peer actually IS the proxy needs the peer's +address, which no builtin exposes). All three are runtime seams by +nature: the information or mechanism lives at the fd level. + +## Goals + +- **Deadlines on parked net I/O.** A read/accept/write that would park + can carry a deadline; expiry resumes the fiber with a distinguishable + timeout result (nil-or-trap decided by the spec, consistent with the + stdlib's nil-vs-trap contracts). On serving shards this composes with + the existing plane — a park is ALREADY a POLL_ADD or TIMEOUT + submission (arc T4); the seam arms both and takes whichever fires. + Program mode gets the same surface over blocking syscalls. +- **Unix-domain listeners and connections** beside the TCP ones — same + accept/read/write/close builtins afterward (an fd is an fd; only the + bind/connect shape differs). +- **The peer's address, readable** — for an accepted connection, enough + to answer "is this my trusted proxy?" (address + family; port where + meaningful). The framework's trusted-proxy middleware then becomes a + pure-`.wo` candidate slice. +- **The framework knobs are explicitly NOT here** — timeout defaults, + proxy allowlists, socket-path config all live in framework slices + that consume these seams. + +## Acceptance Criteria (draft — the spec refines) + +- **Given** a fiber reading a socket whose peer sends nothing, **when** + the declared deadline expires, **then** the fiber resumes with the + timeout result (never a hang), other fibers having run throughout + (TID-verified), and the fd is still usable or cleanly closed per the + spec's stated semantics. +- **Given** a listener on a Unix socket path, **when** a client + connects and exchanges bytes, **then** the whole existing net surface + works unchanged over it, and the log-watcher/web-app gates stay + byte-identical on TCP. +- **Given** an accepted connection, **when** the handler asks for the + peer address, **then** loopback TCP and Unix-socket peers are both + identifiable, and the answer round-trips into the trusted-proxy + check's comparison. +- **Given** the full battery plus a soak with deliberately stalled + clients, **when** it runs, **then** zero leaked fds and flat RSS — + timeouts must CLEAN UP, not merely return. + +## Out Of Scope + +- Framework policy (default timeout values, proxy allowlist shape, + keep-alive idle policy) — framework slices on top. +- TLS, h2c — unchanged owners (proxy; parked behind 23). +- Connect-side timeouts for outbound clients beyond what the deadline + seam gives free — no workload asks yet. +- Cancellation as a general mechanism — iteration 31's + request/response + timers own actor-level cancellation; this is + strictly fd-level deadlines. + +## Info + +Forks the spec must settle: + +1. **Timeout result shape**: nil result vs a distinguishable trap — + must follow the stdlib's existing nil-vs-trap doctrine + (`07`-series contracts; a timeout is an EXPECTED outcome, which + argues nil). +2. **Deadline plumbing on the plane**: one park may need BOTH a + POLL_ADD and a TIMEOUT in flight (io_uring linked ops vs two + submissions + first-wins cancel; epoll fallback = the existing + deadline scan). The park protocol contract + ([`03-concurrency-coroutines.md`](../../../plan/oop-vm/03-concurrency-coroutines.md)) + gains the rule. +3. **Surface shape**: per-call deadline argument vs per-fd setting + (`net.set_deadline(fd, ms)`); leaning per-call — no hidden fd state, + matches the no-coloring doctrine. +4. **Unix-socket path semantics**: unlink-before-bind? stale-socket + handling on restart (the never-stopping-runtime doctrine says a + restart must not need manual cleanup). + +## Proposed Solution + +Brainstorm → small spec settling the four forks → implement in the +`time.ticks`/34 shape (builtin ids + park.c deadline arming + contract +rows + fixtures incl. a stalled-client corpus case). Independent of the +chain; natural pairing is right before or with iteration 24 (chat wants +read deadlines for dead-client eviction even before lifecycle timers).