← board

Networking runtime

Summary

Add a target-neutral networking API (net.pas) with platform-specific backends. Use the Synapse library as both a compiler compatibility target and correctness test suite.

Design Reference

Full design lives in devdocs/developer/plan-networking.md. Key decisions:

Analysis: Work Required

1. Compiler prerequisites (may already be in progress)

Blocker Notes
Conditional/directive parsing POSIX-profile Synapse hits missing {$IF DECLARED(...)} support
Unit resolution from source paths Dotted units such as Posix.SysSocket truncate to posix
RTL unit availability SysUtils, Classes stubs or equivalents needed
Platform-branch selection {$IFDEF LINUX} / {$IFDEF FPC} handling

2. Runtime implementation order

  1. Syscall constants + sockaddr_in struct layout for Linux x86-64.
  2. Byte-order helpers (htons, ntohs, htonl, ntohl).
  3. Thin syscall wrappers: socket, bind, listen, accept, connect, read/write, sendto/recvfrom, close, setsockopt.
  4. Public net.pas API wrapping the above.
  5. Loopback tests: TCP echo client/server, UDP send/recv.

3. Synapse compatibility milestones

Unit Current state Likely fix category
synautil default: missing libc; POSIX profile: missing posix branch selection + dotted units
synaip default: missing libc; POSIX profile: missing posix branch selection + dotted units
synsock default: missing system; POSIX profile: {$IF DECLARED(...)} parse fail branch selection + directive support
blcksock default: missing system; POSIX profile: missing system dotted units / later RTL availability

First pass: classify failures. Second pass: fix compiler blockers. Third pass: compile units successfully.

4. Test strategy

First Milestone

Linux syscall-only IPv4:

DNS deferred to feature-dns-resolver-library.

Log

Log

Umbrella status (2026-07-20, Track B sweep)

This is a strategy umbrella spanning years of milestones (own syscall socket layer, PAL backends, Synapse compatibility via the Posix.* path, cross/ESP targets), not a unit of work that can be finished in one pass. Its named milestones are done — net.pas, asyncnet, the PAL, and per the 2026-07-19 sweep note the Synapse milestone is "effectively achieved".

Its concrete open remainder is now [[feature-ipv6-complete-surface]] (accept peer address, UDP v6, asyncnet v6, AAAA, dual-stack, scopeId). Prio dropped to 20 to reflect that: rank the children, not the umbrella, so it stops presenting as available work while its actual tasks live elsewhere.

2026-07-31 — the IPv6 child is closed

[[feature-ipv6-complete-surface]] is resolved: v6 accept returns a real peer (address, port and scope id), UDP branches on family through both the PAL and net.pas, and asyncnet gained TcpListen6 / TcpConnect6 / TcpConnectAddr6. Gated by lib_net6 (extended) and the new lib_asyncnet6, both SKIP-clean on a host without AF_INET6.

Two items came back out of it as a Track U question rather than plumbing — IPV6_V6ONLY on a :: listener, and A-vs-AAAA ordering — filed as [[decide-ipv6-dualstack-and-aaaa-ordering]]. Both are choices this umbrella's design section never made, and both change observable behaviour, so they wait for a human.

2026-08-02 (Track B) — the decided items landed; this umbrella has no open children

[[decide-ipv6-dualstack-and-aaaa-ordering]] was resolved 2026-08-01, but the ticket that owned its implementation ([[feature-ipv6-complete-surface]]) was already in done/, so the decided work sat in nobody's queue for a day. Both halves are now in:

Two defects fell out of that work, both fixed with regressions: [[bug-b-dns-wire-ipv4-literal-returns-nxdomain]] (the default resolver answered NXDOMAIN for 127.0.0.1, so the facade's answer changed with the backend), and NetTcpConnectTimeout silently ignoring addr.Family (a v6 address connected to 0.0.0.0).

State of this umbrella: no open children. Its named milestones are done, its IPv6 child is closed, and its decision is implemented. The only networking tickets left in the tree are [[feature-dns-esp-backend]] (ESP-only, and not startable without an ESP runner) and [[feature-dns-libc-backend]] (done).

It is still ranked 20 and still appears in the ready queue despite its own instruction to "rank the children, not the umbrella". Whether a years-spanning strategy umbrella with zero open children should be closed, or kept open to collect future ones, is a judgment call about how this project wants its board read — flagged here rather than decided by an agent.

Closed 2026-08-28 (Track B, frankB) — delivered; split-or-demote call made

The call this ticket had been waiting for: split one child, then close. It is an umbrella whose milestone is met and whose every named residue already has its own ticket — and all of those tickets are done.

The First Milestone is met

lib/rtl/net.pas provides TNetSocket/TNetAddress, TCP NetTcpListen/NetTcpAccept/NetTcpConnect/NetSend/NetRecv, UDP NetUdpBind/NetUdpSendTo/NetUdpRecvFrom, and NetGetSockName/NetGetSockError/NetShutdown/NetClose, over the PAL substrate with no platform conditionals of its own. asyncnet.pas is the coroutine face over the same primitives; sockets.pas and baseunix.pas exist. lib-test carries 66 net-related rows and exercises async DNS, IPv6, TLS and cross-target net PAL under qemu.

Every residue is closed, and that is what makes this a demote rather than a park

residue this ticket named where it went state
DNS resolver policy [[feature-dns-resolver-library]] done
PAL datagram / poll / errno [[feature-pal-network-datagram-poll-errno]] done
dotted unit names (Posix.*) [[feature-dotted-unit-names]] done
{$IF DECLARED(Qualified.Symbol)} [[feature-conditional-declared-directive]] done
Synapse compat milestone [[feature-synapse-compile-check]] done
IPv6 landed in net.pas done — 19 API points, gated by lib_ipv6

One item was stale, and one was superseded

Split out

[[feature-b-posix-and-fpc-named-socket-facades]] (Track B, prio 25) — the Posix.* / FPC-named compat facades with a selectable syscall-or-libc backend. The only piece designed in detail here and never built, and the only one with no ticket of its own; closing this umbrella without it would have deleted the design. Filed at low prio because nothing is blocked on it — Synapse already compiles via --mimic-fpc — and ranked the way CLAUDE.md ranks a compat item: by how much real code needs the form, which today is none in tree.

Why closing beats parking

An umbrella nobody can start is a planning defect, not a backlog entry. This one read as p40 of available Track B work while containing none: a dispatcher sees a slug and a prio, not a body, so a ticket whose contents are entirely elsewhere costs a real dispatch every time it surfaces. That happened tonight to two tickets in this lane.


Coordinator ratification, 2026-08-28 — the one judgement call in this closure

frankB surfaced the single call rather than burying it, so it is recorded here with the sentence to disagree with named.

The residual "async/blocking facade unification" was treated as superseded, not outstanding. Verified: devdocs/developer/plan-networking.md:117 reads "shaped compat surfaces — they coexist with the async transport, they do not merge". The line carrying unification forward is a backlog sweep note, which postdates the design decision but is a weaker source than it: a mechanical carry-forward is not a decision to revisit.

Ratified. A design document beats a sweep note, and the remedy if this is wrong is one reopened ticket — cheap enough that it does not warrant a Track U decision. If the intent genuinely was to revisit coexist, plan-networking.md:117 is the sentence to disagree with, and reopening is one ticket.

Note on the verification itself: the first check looked in devdocs/dev/ and returned nothing. The file is in devdocs/developer/. A search in the wrong directory returns silence that reads exactly like a refuted claim — the mirror image of face fourteen, filed the same hour under feature-a-a-refusal-is-a-claim-with-a-date-on-it.