tls: one transport of TCP or TLS over TCP, upgradable in the middle #115
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Goal
std/tlsexports oneTransport: TCP or TLS over TCP behind the same four operations (receive, send, finish, remote), upgradable in the middle of a connection. This is what Postgres's TLS request, MySQL's SSL request, SMTP'sSTARTTLSandrediss:need. Today every consumer has a private copy (std/http/src/transport.trb,torb/postgres'sWire).Design point
std/httpreads and writes either through oneTransport"). The interface ofstd/tlsstays; this adds a type besideTlsStream.std/http's privateTransport(plain / encrypted,isEncrypted,receiveBuffer,sendBuffer,finish,remote), plus the middle upgrade.Scope
Public API in
std/tls/src/lib.trb:Transport.plain(stream),Transport.encrypted(stream, session)as instd/httptoday.var fn upgrade(serverName, settings = TlsSettings()): Task<Result<Void, NetworkError>>: TLS client handshake over the plain TCP stream already held. Refused (aNetworkError, nothing sent) where the transport is already encrypted. A failed handshake leaves the transport unusable; the error is the oneTlsStream.connectgives (isCertificateRejected(),isTlsFailure()).var fn upgradeAccepting(identity, protocols = [], clientRoots = []): the server's side with the semantics ofTlsStream.accept.fn tls(): TlsStream?(the session, fornegotiatedProtocol()and the peer's certificate of #116) andfn isEncrypted(): Bool.Reader) must be empty beforeupgrade; a transport itself buffers nothing, so aSTARTTLSresponse-injection cannot hide in it.Acceptance criteria
Transportwith the API above instd/tls, documented with aSTARTTLS-shaped example.tests/conformance/(pattern oftls-loopback.trb): plain exchange,upgrade/upgradeAcceptingover loopback, encrypted exchange afterwards,isEncrypted()flips;upgradeon an encrypted transport fails;upgradefor a wrong name fails withisCertificateRejected(); a plain-only transport never reports a session.std/httpusesstd/tls'sTransport; its privatesrc/transport.trbis deleted; its existing tests pass unchanged.torb/postgresnamed as still to move (outside this repo).sh tools/gates.sh agreen in forge CI; docs change regeneratesskills/.Seed
Does not touch the seed: pure TorbScript in
std/tlsandstd/http, no syntax change, no new native, no driver flag, no name the compiler looks up by string.Size
One PR, two Conventional Commits:
feat(tls): one Transport of TCP or TLS over TCP, upgradable in the middle(type, tests).refactor(http): use std/tls's Transport(delete the private copy, FIRST-PARTY.md gap 17 done, regeneratedskills/).Dependencies
None open. #116 (peer's certificate) and #117/#118 (client certificates, ALPN) are merged. #463 (commit 2 of 2 for #116) also edits
std/tls/src/lib.trb: whichever lands second rebases; no semantic dependency.Moved from the planning lists of the docs; the design record stays the specification.
[loop:torbscript] intake: in scope (author orion, label loop), source FIRST-PARTY.md gap 17, not a duplicate. Depends on TLS work in std. next: waiting (refine queued, ready buffer full) until 2026-10-10T04:00:00Z
[loop:torbscript] claim refine by session:loop-torbscript-20261027 until 2026-10-27T01:37Z
[loop:torbscript] decided by the loop: (1) The type lives in
std/tlsandstd/httpmoves onto it, becausestd/httpalready importsstd/tls, so no new package edge, and the gap namesstd/tls. (2)upgradeis an explicit method on the transport (client) withupgradeAcceptingfor the server, so loopback tests cover both ends. (3) The transport buffers nothing; the caller must drain its ownReaderbefore upgrading, documented. (4) Thetorb/postgresWirecopy is outside this repo and stays until it moves. (5) Size: one PR, two commits, no seed touch. Dependencies #116/#117/#118 are already merged; #463 only overlaps the same file. The issue body now holds goal, criteria, design point, seed impact and size.[loop:torbscript] refine: body rewritten to the definition of ready, label
readyset, next: implement. Worker usage: about 60k tokens (sonnet).[loop:torbscript] claim implement by session:loop-torbscript-20261027 until 2026-10-27T06:00Z
[loop:torbscript] implement: checkpoint, claim 7124 released, no PR yet, next: implement (continue).
Done (commit
9442c1e4onloop/115-tls-transport, pushed):Transportinstd/tls/src/lib.trbwithplain,encrypted,isEncrypted,tls,upgrade,upgradeAccepting,receiveBuffer,sendBuffer,finish,remote; a failed handshake marks the transport unusable (isClosed()),upgradeon an encrypted transport is refused withNetworkError.invalid. Doc comment carries a STARTTLS example and the drain-your-Reader rule.Left, in order:
tests/conformance/tls-transport.{trb,expected,exit,allocations}(pattern oftls-alpn.trb; cert constants copied from it): plain exchange,upgrade/upgradeAccepting, encrypted exchange,isEncrypted()flips, second upgrade refused, wrong name ->isCertificateRejected()thenisClosed(), plain-only never has a session,Transport.encryptedpair..exitis0without newline;.allocationsisunbudgeted: <reason>liketls-alpn.docs/standard-library/tls.mdTransport declaration block (generated format, source order) plus prose, mirrored by hand intoskills/torbscript-networking/references/standard-library/tls.md(only link rewriting differs) unless a torb binary is available.refactor(http): use std/tls's Transport: deletestd/http/src/transport.trb, changeuse Transport from "./transport"tofrom "std/tls"inclient.trb,connection.trb,server.trb; FIRST-PARTY.md row 17 marked done with file and test names,torb/postgresWirenamed as still to move.Closes #115), read tier A with ci-wait.sh, fix red rounds.Unverified risks: nothing compiled or formatted yet (no torb binary in the gateway), so the first CI round may show type or
format --checkfindings;doc --checktype-checks the new doc example (Buffer.frominference).Worktree:
code/wt/torbscript-language-115(orion workspace). Last commit:9442c1e4. Worker usage: about 110k tokens (sonnet).CONTINUE: torbscript/language#115
[loop:torbscript] claim implement (continuation 1/3 after checkpoint 7143) by session:loop-torbscript-20261027 until 2026-10-27T06:00Z
[loop:torbscript] implement: checkpoint, claim 7144 released, PR #522 is open, forge CI tier A running (ci-wait started, no result read yet), next: implement (continue).
Done (4 commits on
loop/115-tls-transport, pushed, last9cc7e9da):Transportinstd/tls(9442c1e4); conformancetests/conformance/tls-transport.{trb,expected,exit,allocations}(plain, STARTTLS-style upgrade on both ends with ALPN, second upgrade refused, wrong name -> certificate rejected then closed,Transport.encrypted); docs indocs/standard-library/tls.mdand the skill mirror,http.mdsource lists, FIRST-PARTY.md row 17 done;std/httpnow importsTransportfromstd/tlsandstd/http/src/transport.trbis deleted.Left, in order: read tier A of PR 522 with ci-wait.sh (
-C code/wt/torbscript-language-115), fix red rounds on the same branch (nothing was compiled or formatted before CI, so expect type orformat --checkfindings and a possibly different server-side outcome in the "wrong name" line oftls-transport.expected), then write the finalnext: reviewcomment.Unverified risks:
tls-transport.expectedwas derived by hand; the doc fragment intls.mdisfragment(lexed only), the doc comment example instd/tls/src/lib.trbis type-checked bydoc --check.Worktree:
code/wt/torbscript-language-115. Worker usage so far: about 190k tokens (sonnet).CONTINUE: torbscript/language#115
[loop:torbscript] claim implement (fix round, red CI on PR #522) by session:loop-torbscript-20261027 until 2026-10-27T07:19Z
[loop:torbscript] release implement: worker died on a session limit (profile locked), fresh worker follows on the next profile
[loop:torbscript] claim implement (fix round, red CI on PR #522, respawn on anthropic:tkoehn) by session:loop-torbscript-20261027 until 2026-10-27T08:00Z
[loop:torbscript] implement: checkpoint, no new commit this round. HEAD
d630bd8e(var session field fix) is pushed and forge CI on PR 522 is running (commit messages, change scope, pdisc green so far); a fresh worker on anthropic:tkoehn is waiting on ci-wait for tier A, next: implement (fix any red job, then write the final comment). Worker usage so far: about 25k tokens (sonnet).[loop:torbscript] release implement: the fix-round worker (anthropic:tkoehn) was killed before its result; HEAD
d630bd8eis pushed and forge CI on PR #522 is running. next: waiting (CI on PR #522) until 2026-10-27T05:00:00Z[loop:torbscript] claim implement (fix round, red tier A on PR #522 head
d630bd8e, pinned on anthropic:notahumanmate) by session:loop-torbscript-20261027 until 2026-10-27T11:15Z[loop:torbscript] implement: root cause of red tier A on
d630bd8ewasformat --checkonly (tests/conformance/tls-transport.trb: twoTransport.encrypted(stream, session)calls in command position must be commands); every other gate lane in that run was green (check, docs, repl/lsp/debug, native + VM std tests, language, packages, vendor, lock). Fixed with the formatter itself (nightlytorb format, 2 lines) and pushedff60cab1style(tls): format the Transport conformance testto loop/115-tls-transport. Forge CI onff60cab1has not started: all jobs of runs 1969/1970 are still queued (waiting for a runner, ~55 min at 06:10 CET), so tier A is undecided. next: waiting (CI on PR #522). Worker usage about 100k tokens (sonnet).[loop:torbscript] claim implement (fix round, red 'commit messages' check on PR #522 head
ff60cab1, pinned on anthropic:notahumanmate) by session:loop-torbscript-20261027-0718 until 2026-10-27T12:43Z[loop:torbscript] implement: fix round,
ci / commit messagesfailed becausestyle(tls): format the Transport conformance testused the typestyle, which tools/check-commits.sh does not allow (feat fix perf refactor docs test build ci chore revert); also folded thefix(tls)repair of the PR's own earlier commit, squashed both fixups into their origin commits (4 commits left, check-commits.sh clean locally), rebased onto current main, changeset identical (diff vs old head equal), new head2beb1bb5; CI queued, next: waiting (CI on PR #522). Worker tokens: ~45k. Claim 7406 released.