Persistent application streams

Evidence level: Implemented capability. Layer Minus provides the encrypted forwarding and exclusive attachment primitives used by persistent application streams. web3:// defines the portable application contract. Linux implements that contract with conet-l0d.

This page explains the boundary between those layers. It does not define a new SI command family.

Layer boundary

Layer Responsibility
Layer Minus / SI Route encrypted control data and attach one opaque writer to one waiting receive line
web3:// application protocol Exact target and logical-port selection, authenticated offer/accept, frame ordering, close, and errors
Runtime Map a local socket to one application session and enforce queue, timeout, and reconnect bounds
Origin service Read and write its native TCP byte protocol without knowing the L0 route

The implemented SI attachment primitives are l0_listen and l0_connect. An application may also use the compatibility form command: "mining" with listenKind: "l0". These are L0 transport controls, not browser-facing web3:// methods.

SI does not implement duplex_offer, duplex_accept, duplex_reject, or application frame objects. Those objects remain encrypted application data. Do not add p2p_stream_*, listenKind: "duplex", or listenKind: "l1p2p" as SI commands.

Stream lifecycle

local client socket
  → parse exact web3:// target and logical port
  → create a fresh application session
  → sign and encrypt an offer to the target user PGP
  → submit through entry A
  → target host validates the offer and configured port
  → target opens its configured local origin
  → both endpoints attach opaque L0 lines through entries C/D
  → authenticated accept
  → ordered encrypted bytes in both directions
  → explicit close, timeout, or bounded reconnect

Each accepted local socket is a separate session. A runtime must not reuse identity, queue, upstream-socket, close state, or attachment handles merely because two sockets use the same wallet and port.

An incoming offer is attach-only. The host must first match:

  • the exact destination wallet or exact tag result;
  • a configured logical port;
  • an expected, fresh session; and
  • local origin policy.

An unmatched, replayed, stale, or ambiguous offer must not allocate a line or open an arbitrary local socket.

When the same process is also a client of another wallet's identical logical port, inbound and outbound lines stay separate. Only an offer addressed to this host's billing wallet plus that port may open the --proxyDuplex origin. An outbound web3://<other>:8400 session keeps the same port number as remote metadata and must not drain the local origin. See URI grammar.

Why two attached lines

An SSE receive line is server-to-listener. Full duplex therefore uses two independently attached directions:

endpoint A receive line  ←  endpoint B writer
endpoint B receive line  ←  endpoint A writer

Each endpoint owns its receive identity. A client must not create a receive line under another application's wallet or attach directly to mailbox B. Control and receive traffic follow the same entry-to-mailbox routing boundary as other conforming L0 applications. POST entry A/C is always a random qualified SI (A ≠ B, C ≠ B). Production picks mailbox B at random from the SI pool. conet-l0d start --debugSI [SI] pins mailbox B only.

Duplex handshake (temporary SSE)

One local TCP is one incarnation. SI never parses duplex_* JSON.

1. Initiator: l0_listen (command) on mailbox B for a temporary wallet.
   Command includes userPgpKeyId. POST via random entry C ≠ B.
2. duplex_offer: encrypt to the destination's **registered** user PGP;
   mailbox-work wrap to that destination's **registered** mailbox.
   JSON announces the initiator temp line (listenWallet, listenUserPgp,
   listenRoutePgp, listenMailboxWallet).
3. Responder: own temp l0_listen, then duplex_accept encrypted to initiator
   listenUserPgp, mailbox-work wrap to initiator listenRoutePgp.
   POST via random entry A ≠ initiator B.
4. Mailbox B of the initiator: unwrap work → match idle l0_listen by inner
   user PGP (not getRoute) → SSE gossip. Initiator decrypts, writes
   responseChunk, then l0_connect to the responder temp mailbox.
5. Only after the initiator occupies the responder listen may the responder
   reverse-occupy the initiator mailbox. Occupying the initiator SSE first
   turns it into a pipe and **drops** the Chat accept.

A --proxy / proxy_duplex hub does not retry a failed temporary line. It posts one duplex_reject (retryable=true) to the initiator request listen (same wrap as accept). The client L0d closes that TCP; the application must open a new connection (new temporary wallet and offer). Do not occupy the initiator SSE only to deliver reject.

l0_connect is a signed command to the peer's mailbox route PGP (targetWallet = that peer's temp listen wallet). It must not share a race with mailbox-work duplex_accept on the same idle SSE.

SI attachment behavior

Event Required behavior
Idle receive line Keep the SSE usable without application data
First valid l0_connect Attach the writer and keep the HTTP connection open
Successful attachment Return HTTP 200 transport readiness; continue carrying opaque bytes
Second writer for the same live line Return 409 Conflict
Receive line disappeared before attachment Return a non-success transport result such as 410 Gone
Attached line closes or becomes stale Release only that line and its local resources
Replacement after the old line is dead Accept a fresh line instead of preserving a zombie occupancy

Chat, mining, presence, acknowledgements, and UDP use separate pools. Occupying an application stream must not return 409 for unrelated Chat or mining traffic.

Once attached, SI treats application bytes as opaque. It must not:

  • decrypt the endpoint-to-endpoint stream key;
  • parse the origin application's byte protocol;
  • save active stream frames as offline Chat messages;
  • send Chat push notifications for stream frames; or
  • move a failed stream onto another application transport and report success.

Identity and encryption

Material Visible to Purpose
Long-lived target EOA Client and host Stable application identity
Target user PGP Client and host Encrypt the application offer
Mailbox route PGP L0 routing controls Reach the target mailbox
Temporary session identity The two endpoints and required route registration Isolate one stream incarnation
End-to-end stream key The two endpoints only Protect accept, reject, control, and data frames
Hop-local attachment handle One local attachment path Release the correct line without cross-hop correlation

The end-to-end stream key must never appear in a command encrypted to mailbox B's route key. Business negotiation is encrypted to the target user PGP; mailbox controls are encrypted to the route PGP.

Fresh session identities and random opaque attachment handles prevent one socket incarnation from being confused with another. Do not derive a handle from public wallets, ports, IP addresses, or route keys.

Socket bootstrap

For --clientDuplex, the accepted local TCP socket is the session boundary. The client may include the first local bytes in the authenticated offer. A --proxyDuplex host opens only the upstream configured for that logical port, forwards the initial bytes, and may return the first upstream bytes with the accept.

Only after authentication and acceptance may either paused application socket resume. This ordering prevents:

  • bytes reaching the wrong session;
  • an unmatched offer opening an origin socket;
  • a response racing ahead of accept; and
  • pre-accept data being attached to a dead line.

Readiness and failure semantics

The following signals are not interchangeable:

Signal Meaning
Entry HTTP 2xx for an encrypted offer An entry accepted transport work
Receive SSE handshake A receive path exists
l0_connect HTTP 200 One opaque writer is attached
Authenticated application accept The remote runtime accepted this exact session
Origin response bytes The configured local service processed stream data

A runtime must report the stream ready only after the authenticated application accept. An HTTP 404, 409, timeout, EOF, or missing accept is a failed stream, not an empty successful response.

Reconnect must be bounded and generation-aware:

  1. clear the dead writer and old attachment state;
  2. create a fresh session incarnation where required;
  3. wait for a valid replacement receive line;
  4. retry with bounded backoff; and
  5. stop when policy, expiry, or retry limits are reached.

Old bytes and handles must never be written into the replacement session.

Backpressure and limits

Every implementation must bound:

  • concurrent sessions per wallet and per logical port;
  • queued bytes and frame count per direction;
  • initial-offer and response-chunk size;
  • idle and total handshake time;
  • reconnect attempts and retry age; and
  • local-origin connect and read timeouts.

socket.write() === false or its runtime equivalent means backpressure, not successful delivery and not necessarily a closed socket. Pause reads, retain only a bounded queue, resume on drain, and close on overflow or drain timeout.

A receive-only SSE can remain healthy after its request body has ended. readableEnded alone is therefore not proof that the line is stale. Use write failure, close/error events, and bounded liveness policy.

Platform implementations

Platform Persistent-stream implementation
Linux server conet-l0d --proxyDuplex <host:port>
Linux client conet-l0d --clientDuplex web3://<wallet-or-exact-tag>:<port>
Windows / macOS Browser extension, browser client, or native runtime implementing the same web3:// contract
Android / iOS Web or native client implementing the same contract
Browser Client-side target resolution, signing, encryption, response verification, and stream adaptation

The application protocol is portable. conet-l0d is the Linux runtime, not a requirement for every client platform.

Security boundary

When endpoint keys remain secure and routing follows the entry/mailbox model:

  • intermediary nodes carry ciphertext rather than origin plaintext;
  • mailbox B does not receive the endpoint stream key;
  • the local origin accepts connections only from its trusted host adapter; and
  • application identity remains the verified wallet rather than a public origin address.

This does not hide a client IP from its selected entry, defeat a global timing observer, provide padding, or make a compromised endpoint safe. See Security limits and threat grades.

Implementation anchors

results matching ""

    No results matching ""