Skip to content

docs: architecture page, diagrams across the guide, and stale-fact fixes - #6

Merged
Alex-Dolid merged 2 commits into
mainfrom
docs/architecture-diagrams
Oct 7, 2026
Merged

Alex-Dolid merged 2 commits into
mainfrom
docs/architecture-diagrams

Conversation

@Alex-Dolid

Copy link
Copy Markdown
Contributor

Summary

Adds architecture diagrams that show how wRPC's pieces work together: a new Architecture page, plus mermaid diagrams on the guide and reference pages that only described their mechanics in prose (32 new diagrams in total). I checked every diagram against src/ before drawing it, and the check turned up a few statements in the docs and in CLAUDE.md that no longer match the code. Those are fixed here too.

New page: guide/architecture.md

Under Introduction, after "Why wRPC?", and listed in llms.txt:

  • The layers: the client and server stacks and what each layer owns
  • Life of a call: one call through every layer
  • Four ways in: every host reaches RpcServer through attachSocket, handleHttpCall, attach or attachPort
  • One connection on the server: class diagram of RpcServer, Client, ServerTransport and Context, plus what is injected
  • Receive and send paths: how an inbound frame is decoded, "encode once", and the order of compression and encryption per carrier
  • The client: WrpcClient outbound and inbound
  • Plugging in: where each subpath plugs into the client and server
  • Across instances: backplane channels, shared session store, what stays local

Diagrams added to existing pages

Page Diagram
server how an HTTP request is routed
reference/protocol revision negotiation (ws, http, worker port, wt); overview of all packet types
encryption which layer covers which hop; Noise handshake; sealed HPKE request
compression each direction picks its own codec from the preference lists
brokers capability model (backplane, log, queue, direct)
brokers/consumers one delivery's life, from arrival to ack, retry, release or dead letter
brokers/rpc stateless requests vs sessions
wt anatomy of a WebTransport session; path from the HTTP/3 host into the core
webrtc how WrpcPeer, PeerLink, RtcLink, PeerHost and Mesh fit together
metadata which handshake carrier is used, and the server's read order
typed-client where client.api comes from (load(), use(), .d.ts)
browser worker proxy serving several tabs
production deployment topology (load balancer, WebTransport over UDP, sticky routing for SSE only)
rate-limiting what a framework limiter sees vs what onRequest sees
telemetry trace propagation client → server → broker → consumer
adapters/express, adapters/fastify how each adapter wires into the core

Corrections

  • client.md: reconnect state diagram redrawn to match #scheduleReconnect and #openOrClose. The first connect never waits. The fallback and restore-failed transitions were missing. failed is not final: the online event or open() restarts the cycle.
  • client.md: transport fallback now says that with the default retries: Infinity the next candidate is never reached once a connection has been up.
  • brokers/rpc.md no longer claims NATS answers 503 when nobody listens on the address. NATS core publish cannot know. The in-process broker, Redis and RabbitMQ do answer 503.
  • CLAUDE.md now matches the code on four points:
    • the publisher writes traceparent/tracestate in message headers, not tp/ts
    • the envelope receiver cache evicts the least recently used sender past maxSenders, not the oldest
    • the key of a sealed SSE stream also mixes in a per-stream server nonce (n=)
    • the broker binding does name the codec on each frame (wrpc-enc)

Verification

  • Rendered every diagram in the dev server, in light and dark themes and at mobile width; no mermaid parse errors in the console
  • Kept each diagram's natural width under ~1100px so the text stays legible in the content column
  • pnpm docs:build passes (dead links)
  • Every new #anchor link resolves to an existing heading in the built HTML
  • node --test tests/package/consistency.test.js passes (26/26)

Notes for reviewers

  • No runtime code changes.
  • Two mermaid pitfalls found while verifying, for whoever edits these next: a ; inside a sequence-diagram message or note ends the statement and breaks the diagram, and a subgraph with direction TB inside an LR flowchart can explode into a single very wide row.

🤖 Generated with Claude Code

Alex-Dolid and others added 2 commits October 8, 2026 00:05
Add guide/architecture.md (Introduction group, listed in llms.txt): the
layers a call crosses, the life of one call, the four entry points into
RpcServer, one connection's object model, the receive and send paths with
the per-carrier order of compression and encryption, the client's
internals, the extension seams, and the topology across instances.

Add mermaid diagrams where the mechanics were prose only: HTTP routing
(server), revision negotiation and the packet exchange (protocol), where
each encryption layer applies, the Noise handshake and a sealed HPKE
request (encryption), per-direction codec choice (compression), the
broker capability model, a queue delivery's settlement, stateless vs
session broker RPC, the WebTransport session and hosting path, the
WebRTC peer composition, the ws metadata carrier, where client.api comes
from (typed client), the worker proxy, the deployment topology, the two
rate-limiting layers, trace propagation through a broker, and the
express/fastify wiring.

Every diagram was checked against src/, rendered in both themes and at
mobile width, and kept under ~1100px natural width so it stays legible.

Two corrections found on the way: the client's reconnect state diagram
now matches #scheduleReconnect/#openOrClose (the first connect never
waits, fallback and restore-failed transitions, failed is not final), and
broker RPC no longer claims NATS answers 503 for an address nobody
listens on — the in-process broker, Redis and RabbitMQ do.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Each checked against the source:

- createPublisher writes the trace context under the W3C header names
  traceparent/tracestate (renamed from the packet fields tp/ts the
  injector writes); consumers.js reads traceparent, falling back to tp.
- The envelope receiver's per-(kid, suite ‖ salt) cache evicts the least
  recently used entry past maxSenders (1024 by default), not the oldest;
  the sealer skips its own last 16 salts, not one.
- A sealed SSE stream's key also mixes in a per-stream server nonce,
  carried as n= in the Content-Type (streamKey in src/encryption/http.js).
- "No frame names its codec" holds for WebTransport and WebRTC; a broker
  binding frame names it in wrpc-enc.
- client.md › Transport fallback: reconnect.retries defaults to Infinity,
  so after the first connection the next candidate is never reached unless
  the budget is finite — only the first connect walks the list on its own.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vercel

vercel Bot commented Oct 7, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
wrpc Ready Ready Preview Oct 7, 2026 9:28pm UTC

@Alex-Dolid
Alex-Dolid merged commit 96c0b84 into main Oct 7, 2026
10 checks passed
@Alex-Dolid
Alex-Dolid deleted the docs/architecture-diagrams branch October 7, 2026 21:35

This branch was successfully deployed

1 active deployment
Preview — c0ab2f6e Deployed Oct 7, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant