writeonce/docs/stories/runtime-v2/09-in-process-tls.md
shoney.arickathil cc1c82b2ef docs: jarvis track, runtime-v2 7/8/9, lang-41 fix design, fiber scope-gap
- jarvis (00-story): 6th track, 2nd software built with writeonce — an AI
  assistant; direct-HTTPS design; blockers named (net.connect + TLS)
- runtime-v2 7 observability + 8 symmetric cipher: moved from the language
  track (were 30/43); 9 in-process TLS: created from the gap jarvis surfaces,
  RETIRES the "TLS is the proxy's job" doctrine (both directions)
- language 41 (arena hang): fix design to ready — marshal cross-shard
  messages (root), align the shard_id % nshards route/compare + assert bound;
  poison-on-free + minimal fixture as follow-ups
- fiber scope-gap analysis (plan/exploration/fiber/01): porch vs fiber, what
  porch lacks, would developers prefer porch
- board + dependency-graph synced (porch 2-8 ready; rv2 table; §5/§5a graphs)

(cherry picked from commit 203470ceb2a151fe3584931cd4237af3f96a9f29)
2026-09-15 01:15:31 +02:00

117 lines
6 KiB
Markdown

---
track: runtime-v2
iteration: "9"
status: pending
readiness: refine
---
# runtime-v2 9 — in-process TLS: retiring the proxy-termination doctrine
> Created 2026-09-07 from the gap [`jarvis`](../jarvis/00-story.md) surfaces — an
> assistant must dial an LLM over HTTPS, and the runtime has no outbound TLS. The
> developer chose the **full overturn**: the runtime gains TLS **both
> directions**, and the standing "TLS is the proxy's job" doctrine is retired.
> **`readiness: refine`** — the gap, its consumers and its forks are named here;
> the implementation is deliberately left as this story's load-bearing fork, not
> settled.
## Why this exists — and what it overturns
Three documents record the same standing decision, and this story reverses it:
- *"TLS — permanently the proxy's job (framework doctrine)"* —
[language 34](../language-runtime-database/34-crypto-builtins.md) (crypto
builtins, line ~83).
- *"TLS — proxy-terminated, by doctrine, unchanged… the story says so out loud
rather than implying HTTPS clients"* —
[language 38](../language-runtime-database/38-content-platform-capabilities.md)
(which adds `net.connect` as **plaintext** outbound TCP and explicitly refuses
HTTPS).
- *"TLS, HTTP/2 | nobody — proxy-terminated by doctrine"* —
[porch](../porch/00-story.md)'s "what this track does NOT own".
The doctrine was reasonable while nothing in-tree needed to *dial* anything: a
front proxy terminates inbound TLS, and there were no outbound callers. jarvis
breaks that — its whole job is to reach a remote API — and the developer's
direct-HTTPS choice for it means the runtime, not a companion, owns the
connection. Rather than carve out a one-directional exception, the decision is to
give the runtime TLS in **both** directions: outbound so a `.wo` program can dial
HTTPS, and inbound so porch can terminate TLS itself instead of mandating a
proxy in front of every deployment.
This is **not a builtin-sized seam** like the rest of this track. TLS 1.3 plus
X.509 certificate validation is a large, security-critical subsystem — the one
place the runtime's hand-roll-everything habit (the sha256 precedent) should not
be assumed to extend. That tension is the load-bearing fork below.
## What it should deliver (scope to be refined)
- **Outbound TLS client** — a `.wo` program dials an HTTPS endpoint: a TLS
handshake over the TCP socket `net.connect` (language 38) provides, with server
certificate validation against a trust store. jarvis's direct path, and
language 38's deliberately-excluded HTTPS half.
- **Inbound TLS server** — porch terminates TLS on its own listener (cert + key
loaded at startup), retiring the "put a proxy in front" requirement for a
single-binary deployment.
- **Certificate validation and a trust store** — X.509 chain verification,
hostname/SNI checks outbound; certificate + private-key loading inbound. This
is where most of the risk and most of the code live.
## Forks the brainstorm must settle
1. **Implementation source — the load-bearing fork (left open by direction).**
Vendor a small, audited TLS library (mbedTLS or BearSSL) compiled into the
single static binary — correct and maintainable, but a build-time external
dependency, an explicit exception to the no-external-deps doctrine the runtime
otherwise holds — versus hand-rolling a TLS 1.3 subset plus X.509 in C, which
matches the sha256 precedent but is thousands of security-critical lines and a
hand-rolled certificate validator is a CVE factory (strongly discouraged). The
honest lean is vendor-a-lib; TLS is exactly the thing not to hand-roll. This
fork decides whether the whole "single static binary, no external deps" story
gains a footnote.
2. **Phasing.** Outbound first (jarvis's actual need) with inbound to follow, or
both together since the handshake machinery and the vendored library are
shared and only the client-vs-server role and validation direction differ.
3. **Trust store and cert provisioning.** Where the outbound trust anchors come
from (the system CA bundle, and its path across distros), and how the inbound
side is handed its certificate and key (files, env, a reload story).
4. **TLS version and cipher policy.** TLS 1.3 only (simplest, modern, smallest
attack surface) versus 1.2+1.3 (broader reach). Leaning 1.3-only.
## Consumers
Named, so this is not a capability shipped as decoration:
- **[jarvis 1](../jarvis/00-story.md)** — outbound HTTPS to the LLM API (the
reason this story exists).
- **porch** — inbound TLS termination, retiring the mandatory front proxy for a
single-binary deployment.
- **language 38** — the outbound HTTPS half it excluded by doctrine; this story
is where that exclusion is lifted.
## Dependencies
- **[language 38](../language-runtime-database/38-content-platform-capabilities.md)**
— `net.connect` (outbound TCP) is the socket the outbound handshake runs over;
the client half of this story sits directly on it.
## Out of scope
- **HTTP/2.** A separate protocol concern, parked behind language iteration 23
regardless; TLS is its prerequisite, not its owner.
- **Mutual TLS / client certificates.** A later slice if a consumer asks; the
first cut authenticates the server, not the client.
- **Updating the doctrine documents.** Retiring "TLS is the proxy's job" means
correcting [language 34](../language-runtime-database/34-crypto-builtins.md),
[language 38](../language-runtime-database/38-content-platform-capabilities.md)
and [porch](../porch/00-story.md) when this lands — a follow-up bookkeeping
pass, named here so it is not forgotten, not part of the runtime work.
## Info
This is the heaviest iteration in the runtime-v2 track and the only one that
forces a doctrine reversal and, most likely, an external-dependency exception —
both flagged above rather than buried. It is pure I/O-plane work (a handshake
layer over the existing socket verbs); no actors, so it is not exposed to the
lang-41 hang. It gates jarvis entirely: until it lands, jarvis cannot reach a
model at all.