Bridge service architecture
Supervision
Bridge.Application starts one supervision tree containing:
Bridge.PubSub;Bridge.HttpProxyTaskSupervisorfor non-blocking legacy response waiters;Bridge.HttpTransferSupervisorfor temporary v2 coordinators;Bridge.ClusterSupervisor;- server, pairing, persistent-pairing, and session managers;
Bridge.Endpoint.
Bridge.HttpRouter runs before Plug.Parsers, allowing proxy and transfer
routes to consume raw request bytes. Bridge.Router owns /health.
WebSocket channels
Bridge.Socket accepts type=server and type=app.
Bridge.ServerChannel owns the active server control connection. It registers
the server PID, relays pairing notices and request metadata to the Python
server, receives legacy responses, and publishes v2 response initialization.
It unregisters its server on termination.
Bridge.AppChannel owns the compatibility frontend path. It discovers
servers, drives pairing, creates/resumes ephemeral sessions, validates those
sessions on requests, and starts supervised response waiters. Response waiting
does not block the channel mailbox, so later requests can progress.
State managers
Bridge.ServerRegistry stores a per-node ETS view and replicates changes over
the servers:registry PubSub topic. The owning node monitors the active server
channel. Duplicate IDs either take over or are rejected according to
BRIDGE_SERVER_ID_CONFLICT_POLICY.
Bridge.PairingManager stores pending six-digit codes in ETS on the owner
node. Codes have expiry and attempt limits.
Bridge.PersistentPairingManager is a compatibility façade over stateless
Bridge.PairingToken credentials. It does not persist sessions or token
records.
Bridge.SessionManager stores node-local ephemeral sessions used only by the
legacy app channel. Session IDs are recreated from a verified pairing token
and expire after inactivity.
Legacy request coordination
For each full or completed chunked request, AppChannel starts a task that:
- subscribes to
tunnel:request:<request_id>; - sends the request to the active server PID;
- waits for full or chunked response events;
- replies/pushes to the original app channel;
- times out and cleans up independently.
This ordering prevents a fast response from racing ahead of the subscription.
HTTP transfer coordination
Bridge.HttpRouter verifies the frontend pairing token, resolves the server,
issues request/response transfer credentials, starts Bridge.HttpTransfer,
and sends http_request_v2.
The coordinator subscribes to http_transfer:<request_id> and monitors:
- frontend proxy handler;
- registered server PID;
- request-body download handler;
- response-body upload handler.
Handlers on any connected bridge node publish attach messages through PubSub. The coordinator enforces claim identity, one attachment per direction, byte counts, an overall timeout, and demand/acknowledgement backpressure.
On failure it notifies peers and emits http_request_v2_cancel. On final
frontend acknowledgement it tells the uploader to complete and stops
normally.
Bridge.HttpTransferSupervisor configures max_children from the active
transfer limit. DynamicSupervisor admission is atomic, and
Bridge.HttpTransfer.start/1 translates saturation to the router's stable
too_many_transfers result.
Header and compression ownership
The HTTP router removes bridge authentication, host, framing, and hop-by-hop
request headers. The Python server removes Accept-Encoding and requests
identity from its local application.
The Python server removes stale response length/encoding and hop-by-hop headers. The bridge then creates a streamed viewer response; Cowboy or the public edge owns compression.
Cluster model
The cluster may use gossip, DNS polling, or no topology. PubSub distributes registry and transfer messages. HTTP pairing handles carry the finite existing owner-node name so confirmation can call the node that stores the pending code.
The system does not require load-balancer affinity for HTTP pairing or transfer legs. Loss of the owner node invalidates its pending pairing/transfer work but does not invalidate stateless pairing credentials when surviving nodes share the signing configuration.
Connected implementation owners
- Frontend transport implementation:
packages/frontend-sdk/src/transport/ - Registered Python server:
application/python/agent_terminal_app/bridge_client.py - Mobile lifecycle:
mobile/crystal-lattice-control-rn/App.tsx - Deployment:
docker-compose*.yml,haproxy*.cfg, anddeploy/aws-*