Replicate through corporate firewalls

Connect wallet copies behind bank firewalls and reverse proxies: TX bid/ask rendezvous, an outbound HTTPS keep-alive stream with long-poll fallback, relay node setup, code, costs and value.

On a home network, copies find each other with a UDP beacon. In a bank they can't: routers drop multicast, and reverse proxies only pass HTTPS. So a copy doesn't wait to be found. It asks a relay node for a connection with a TX bid, the node answers with a ticket, and the copy dials out on port 443. Nothing opens an inbound port.

Quick start: two copies through a relay, on your computer

About five minutes. You need git and Deno 2. Nothing is charged.

1 · Start a relay node

git clone https://github.com/CAL-CAPPZ-Attribution-Liberation/graph-ledger-notary cappz && cd cappz deno run --allow-net --allow-read --allow-write --allow-env \ packages/cappz-edge-node/main.ts --relay 41445

Leave it running. It listens on port 41445 and only accepts copies that sign their hello.

2 · Check it answers

Check your relay node

3 · Connect copies through it

Opens the wallet-copies demo with your relay filled in. Press Create Copy twice, then send a sample payment from one copy to the other.

Each copy shows "HTTPS keep-alive stream" when connected. The relay prints every decision to cappz-node-data/relay-txs.jsonl.

How it works

1 · Ask (TX bid/ask)

The copy sends ReplicaConnectRequested with its bid, the bytes it expects to move and a hello signed with its Ed25519 key, which the node verifies. The node replies ReplicaConnectOffered with a short-lived ticket, or ReplicaConnectRejected with a reason. Both are TXs with the same correlation id.

2 · Dial out (fastest first)

The copy tries WebTransport (QUIC over UDP), then WebSocket, then one HTTPS GET that never ends: an HTTP/1.1 keep-alive response with chunked transfer. Every rung carries the same CPZ1 frames with no per-message HTTP overhead.

3 · Step down, never stall

UDP blocked: WebSocket. Upgrade refused: the keep-alive stream. No first byte (a proxy buffers): HTTPS long-poll. If a connection is cut, the copy reconnects from the relay's cursor. Frames carry checksums; copies dedupe by id and hash.

Bank network DMZ AgentCo ┌──────────────┐ HTTPS 443 ┌───────────────┐ keep-alive ┌──────────────┐ │ bank copy │ ──────────▶ │ reverse proxy │ ───────────▶ │ relay node │ ◀── sales / ops / │ (no inbound) │ ◀── stream ─│ (TLS, no buf) │ ◀─────────── │ (edge node) │ treasury copies └──────────────┘ └───────────────┘ └──────────────┘ ReplicaConnectRequested ─▶ node decides ─▶ ReplicaConnectOffered (ticket) ─▶ TunnelOpened

What you need

  • Library or tool
  • What it does
  • Where it runs
  • Cost
  • @cappz/sdk/transports
  • connectThroughFirewall, createHttpsRelay, dialWebTransport / dialWebSocket, generateSigningKey / signHello, declareHelloKey, runBodyExchange, proxiedFetch
  • Every copy and the relay node
  • Free
  • Deno 2 (or Node 18+, Bun)
  • Runs the edge node, or your own relay with createHttpsRelay
  • The relay node
  • Free
  • nginx or Caddy
  • TLS on 443 in front of the relay, keep-alive upstream, no buffering
  • The DMZ / reverse proxy
  • Free
  • A small server or VM
  • Hosts the relay node (1 vCPU, 512 MB is plenty to start)
  • Your cloud or data centre
  • Yours (≈ $5–10/month)
  • Optional: cloudflared
  • Publishes a relay without opening an inbound port at all
  • Anywhere
  • Free tier
npm install @cappz/sdk # or: bun add @cappz/sdk deno --version # Deno 2 runs the edge node

Deploy it at your company

Three steps: a relay node outside the firewall, your reverse proxy in front of it, and copies that dial out. Steps 4 to 6 are optional.

1 · Run the relay node

The relay is part of the CAPPZ edge node. CAPPZ_RELAY_ASK is your price for carrying traffic (0 for your own copies). The node verifies every hello's Ed25519 signature and rejects tampered, stale or wrong-wallet hellos; CAPPZ_RELAY_OPEN=1 also carries copies that send no hello (demos only). With a declared-keys file and CAPPZ_RELAY_REQUIRE_BOUND=1 it carries only keys each wallet declared. Each wallet holds at most 8 open tickets. The node offers WebSocket at /cpz1/ws and, with a TLS certificate and --unstable-net, WebTransport over UDP. Decisions, with the signature check each hello passed, are written to relay-txs.jsonl.

# 1 · Run the relay node (part of the CAPPZ edge node) git clone https://github.com/CAL-CAPPZ-Attribution-Liberation/graph-ledger-notary cappz && cd cappz # the node's Ed25519 key signs its hello, its LAN beacons and its TX log node -e 'crypto.subtle.generateKey({name:"Ed25519"},true,["sign"]).then(async k=>{ console.log("CAPPZ_NODE_KEY="+Buffer.from(await crypto.subtle.exportKey("pkcs8",k.privateKey)).toString("base64")); console.log("CAPPZ_NODE_PUB="+Buffer.from(await crypto.subtle.exportKey("raw",k.publicKey)).toString("hex"))})' > node.env set -a; . ./node.env; set +a CAPPZ_POW=<your node POW address> \ CAPPZ_RELAY_ASK=0 CAPPZ_RELAY_ASK_UNIT=per-MB \ deno run --allow-net --allow-read --allow-write --allow-env \ packages/cappz-edge-node/main.ts --relay 41445 # optional: WebTransport (fastest rung) needs a TLS cert and --unstable-net # CAPPZ_TLS_CERT=cert.pem CAPPZ_TLS_KEY=key.pem CAPPZ_RELAY_WT_URL=https://relay.example.com:41445/cpz1/wt # deno run --unstable-net ... (UDP 41445 open to the node) # optional: carry only keys each wallet declared (copies present a wallet-signed declaration) # CAPPZ_RELAY_REQUIRE_BOUND=1 # check it curl http://localhost:41445/cpz1/health

2 · Put it behind your reverse proxy

The proxy terminates TLS. It must keep the upstream connection alive and must not buffer: buffering is exactly what makes a copy step down to long-poll.

# 2a · nginx: TLS on 443, stream frames as they are written location /cpz1/ { proxy_pass http://127.0.0.1:41445/cpz1/; proxy_http_version 1.1; # keep-alive to the relay proxy_set_header Connection ""; proxy_buffering off; # chunked frames flow through at once proxy_read_timeout 3600s; # a stream may stay open for minutes } location /cpz1/ws { # WebSocket rung proxy_pass http://127.0.0.1:41445/cpz1/ws; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_read_timeout 3600s; } # WebTransport is UDP: open UDP 41445 to the node (nginx does not carry it) # tickets travel in the Authorization header or the first socket frame — never in a URL
# 2b · Caddy: TLS certificates are automatic relay.example.com { reverse_proxy /cpz1/* 127.0.0.1:41445 { flush_interval -1 # never buffer the stream; WebSocket upgrades pass through } } # WebTransport is UDP: open UDP 41445 to the node

3 · Connect a copy from behind the firewall

The copy asks first, then dials out. If the node says no, connectThroughFirewall throws with the node's reason (bid too low, unsigned hello, ticket limit).

// 3 · A copy behind the firewall: ask, then dial out import { connectThroughFirewall, generateSigningKey, declareHelloKey } from '@cappz/sdk/transports'; const signingKey = await generateSigningKey(); // the device key that signs hellos // The wallet vouches for it (secp256k1, wallet key): nodes can then require declared keys. const keyDeclaration = await declareHelloKey(wallet.privateKey, wallet.address, signingKey.publicKeyHex); const { decision, tunnel } = await connectThroughFirewall({ endpoint: 'https://relay.example.com/cpz1', walletAddress: myWallet, // the copy's wallet copyId: 'treasury', channelId: 'agentco', // network channel or sorted pair "A~B" bid: { baseCappz: 0.02, baseUnit: 'per-MB', priceCappz: 0.02, unit: 'per-MB' }, expectedBytes: 50 * 1_048_576, // priced against the node's ask signingKey, // signs a fresh Ed25519 hello; the node verifies it keyDeclaration, // binds the key to the wallet, no lookup needed heads, // head txIds carried in the signed hello onFrame: (frame) => replicate(frame), onRung: (rung, reason) => console.log('stepped down to', rung, reason), }); // tunnel.rung: 'webtransport' | 'wss' | 'https-stream' | 'https-poll' — fastest the network allows // decision.eventType === 'ReplicaConnectOffered' — record it on your ledger await tunnel.send('inv', { heads }); // CPZ1 frames, checksummed console.log(tunnel.stats()); // rung, cursor, HTTP requests, resumes

Going further

4 · Run the relay inside your own server instead of the edge node

5 · Model your business as flow (how AgentCo works)

6 · Test against real proxy behaviour before a bank does

For your security team

A one-page brief you can forward. Every point is enforced in code and covered by tests.

Outbound only; HTTPS 443 is enough

Copies never listen. Plain HTTPS on 443 always works. WebSocket (443) and WebTransport (UDP) are used only where the network allows them, and are never required. No inbound port, no multicast.

Every connection is asked for and recorded

ReplicaConnectRequested, then Offered or Rejected with a reason, then TunnelOpened and TunnelClosed: ledger records with one correlation id.

Signed, verified hellos

Each copy signs its hello with its own Ed25519 key, and the wallet signs a declaration that the key speaks for it. The relay rejects tampered, stale (over 10 minutes) and wrong-wallet hellos, and can carry only keys a wallet declared — checked offline, no registry.

Tickets stay out of logs

The short-lived ticket travels in the Authorization header (HTTPS) or the first frame (WebSocket, WebTransport), never in a URL, so proxy and server access logs never hold it. The ledger keeps only its hash prefix. Open tickets are capped per wallet.

The relay cannot read content

It checks framing and checksums and passes sealed messages along. Seal payloads end to end with the copy keys; the relay keeps a bounded log for an hour, in memory.

Nothing is lost or silently changed

Every message carries a checksum; documents carry a sha256 that the receiving copy recomputes. After a cut the copy resumes from its cursor; duplicates are dropped.

New to this? Six terms in plain words

Wallet copy

Each party's own copy of the shared records. Nobody edits anyone else's copy; documents are copied in and checked.

Relay node

A small server you run outside the firewalls. Copies connect out to it; it passes sealed messages along and cannot read them.

Bid and ticket

A copy asks the relay to carry its traffic and says what it will pay (its bid). The relay answers with a short-lived ticket, or says no and why. Both are recorded.

Signed hello

The first message a copy sends, signed with its own key. The relay checks the signature, so nobody can connect pretending to be someone else.

Connection ladder

A copy tries the fastest connection first (WebTransport, then WebSocket, then a live HTTPS stream) and falls back to polling over plain HTTPS if a network blocks the others. The switch is automatic.

Hash check

Every document carries a fingerprint (sha256). A copy that receives it recomputes the fingerprint and rejects anything that changed on the way.

Costs and value

Free

  • The SDK, the edge node and the relay (your own server).
  • Your own relay's ask: 0 CAPPZ for your own copies.
  • Discovery: no hosted rendezvous service to pay for.

Charged (published price sheets)

  • $0.01 per ledger transaction.
  • Replication: $0.02 per MB ($0.01 enterprise), $1 per replica wallet a month, $10 a month subscription ($40 enterprise).
  • Notarization: from $0.50 per document, halved from 100 a month.
  • Another operator's relay may set its own ask in CAPPZ. You see it in the offer before you connect.

Here is AgentCo for a month. Change the assumptions to match your business.

Assumptions

The price, volume and analyst figures are illustrations, not quotes or benchmarks. Use your own numbers.

What a month costs

  • Item
  • Quantity
  • Source
  • Per month
  • Ledger transactions
  • 18,000 TX
  • base fee 1¢ per TX
  • $180.00
  • Replication transfer
  • 1,373.3 MB
  • replicator-2026-09-28
  • $27.48
  • Replica wallets
  • 5 replica-month
  • replicator-2026-09-28
  • $5.00
  • Replicator subscription
  • 1 month
  • replicator-2026-09-28
  • $10.00
  • Notarized reports
  • 2,000 document
  • notarizer-2026-09-28
  • $500.00
  • Agent compute
  • 2,000 order
  • assumption
  • $60.00
  • Relay node hosting (your own server)
  • 1 month
  • assumption
  • $6.00
  • CAPPZ platform charges
  • $722.48
  • Total running cost
  • $788.48

Cost per order

$0.394

Revenue

$50,000

Gross margin

98.4%

Same work by people

$127,500

The biggest platform charge is notarization: $500.00 a month for a verifiable proof of every report. Replication itself costs $32.48 for 1373 MB across 5 copies. A relay node operator may also set an ask (in CAPPZ); your own node asks 0.

Questions

Why keep HTTP/1.1 keep-alive when there is WebSocket and WebTransport?

What does the relay see?

What if the proxy cuts the connection?

Is the hello signature verified?

What happens to my payment if a matched sync fails?

Can a browser on cappz.ai reach my relay?

Watch a company with no employees run through five firewalls

AgentCo uses exactly this library: five copies, a bank's inspecting proxy, live costs.