🧠πŸšͺ RAPP Neighborhood β€” Doorman Guide

Turn a fresh Claude on any machine into the doorman to that machine's brainstem: it stands up a tether so authorized peers β€” another browser, another machine, another Claude β€” can reach and operate the brainstem, end-to-end encrypted, as secure as if it were all on one device.

rapp-neighborhood-protocol/1.0AES-256-GCM sealedWebRTC Β· DTLS kited twinszero-dependencyproven E2E

What this is

A RAPP neighborhood is a set of brainstems that meet as uniform peers and talk in one envelope shape (rapp-twin-chat/1.0). A tether is the live link between two of them. This guide shows how to make Claude the doorman: a fresh Claude session reads one file, proves a secure door works on its machine, opens it, and hands you the key.

Another browseror another machine / Claude
β”€β”€πŸ”’ sealed ──▢WebRTC DTLS + AES-256-GCM
Doormanbrainstem_bridge
── localhost ──▢on-device
Local brainstem:7077

Quick start

  1. On the machine you want to reach, open a fresh Claude (Code) session and paste:
    Read https://raw.githubusercontent.com/kody-w/vbrainstem/main/doorman.skill.md and set me up as the doorman to this machine.
  2. That Claude self-tests (hosts the bridge in headless Chrome, drives it from a separate sealed peer), checks prerequisites, then opens the door and gives you a peer-id + token + operator link.
  3. Walk through the door from anywhere β€” open the operator link in a browser, or from a shell:
    bash vbridge.sh <peer-id> <token> ask "who are you and what can you do?"
    Every byte is opaque ciphertext; the doorman refuses anyone without the token.

Uniform peers

Everyone in the neighborhood β€” a person, a local brainstem.py, a browser vBrainstem, or Claude β€” speaks the same envelope, so you can't tell what's on the other end. That's the point: a tether is transparent.

// twin-chat envelope
{ schema:"rapp-twin-chat/1.0", from_rappid, to_rappid, utc, nonce,
  kind:"say"|"console", payload, facets }

Tethers & kited twins

There are two live (Β§5a) transports:

πŸ›° WebRTC tether 5a-tether

Direct browser↔browser P2P. The PeerJS broker does the handshake only (SDP/ICE); data flows DTLS-encrypted peer-to-peer β€” the broker never sees it.

πŸͺ Kite tether 5a-kite

An operator (Claude) holds the string: drives a browser tab's console over the Chrome DevTools Protocol and relays. No broker, no STUN, no CORS β€” the string-holder is the transport.

A kited twin is a tab flown on a kite string. It is tethered when the string also reaches the locally-running brainstem (5a-kite+tether) β€” its turns are answered by that brainstem; with no local brainstem it is just kited (answered by the tab's own in-page brainstem).

kite tabreaches nothing
── CDP ──▢on-device only
Claudethe string
── localhost ──▢the tether
local brainstem
CDP (Chrome's debug port) is unauthenticated β€” keep the kite/CDP hop on the machine. To cross machines, ride the WebRTC tether (encrypted), never raw CDP.

The sealed channel β€” as secure as on-device

A fully on-device neighborhood has no wire to tap. To match that over a network, every envelope can be sealed:

PropertyHow
ConfidentialAES-256-GCM; the wire/broker/TURN see only {schema:"rapp-sealed/1.0", iv, ct}
Tamper-evidentGCM auth tag β€” a flipped byte is rejected (decrypt/auth failed)
AuthenticatedKey = PBKDF2-SHA256 (210k, salt rapp-neighborhood-5a/1) from a secret that rides only the out-of-band pairing link β€” never the broker
At restSecrets & holocards use the same AES-256-GCM vault primitive

Layered over WebRTC's DTLS, the network is fully untrusted and still safe. A wrong-key peer can't even read the rejection. The identical scheme runs in the browser, the bridge, the CLI, and Node β€” one contract on every hop.

Session & handshake

Opening the door is one call: host() mints a peer-id + token (the token is the channel secret). Sharing it out-of-band is the handshake. Closing the tab / killing the host destroys the peer + secret β†’ the session ends, exactly like stopping brainstem.py. Plaintext chat (say) may be open; operating the console (run/eval/chat) only works over the sealed channel, where key-possession is the authorization.

Set up a doorman

Prerequisites (on the machine being opened)

  • Local brainstem running β€” curl -s http://localhost:7077/health returns {"status":"ok",…}.
  • Google Chrome / Chromium (headless WebRTC + CDP). Set CHROME=/path/to/chrome if needed.
  • Node β‰₯ 18 β€” built-in WebSocket/fetch/crypto.subtle.

Prove it, then open it

The skill makes Claude run this first β€” it exits PASS only if a separate sealed peer reached the real brainstem:

# one-command proof this machine can be a sealed doorman
curl -fsSL https://raw.githubusercontent.com/kody-w/vbrainstem/main/doorman_selftest.sh | bash

Open the door (GUI). The brainstem is on http://localhost, so serve the bridge from localhost too β€” an HTTPS page is blocked from fetching http://localhost (mixed-content / private-network) and the call hangs; localhost is still a secure context, so sealing works:

curl -fsSL https://raw.githubusercontent.com/kody-w/vbrainstem/main/brainstem_bridge.html -o brainstem_bridge.html
python3 -m http.server 8123 &
open http://localhost:8123/brainstem_bridge.html   # URL stays http://localhost:7077 β†’ β€œHost bridge”

The three duties

A Β· Open the door β€” front this machine's brainstem

Use the bridge above (GUI), or host it headless and keep Chrome alive. It publishes a peer-id + token; share the operator link with the authorized visitor.

B Β· Visit a door β€” operate another host

bash vbridge.sh <peer> <token> ask    "hello"                # sealed chat
bash vbridge.sh <peer> <token> chat   "summarize my agents"  # β†’ their /chat
bash vbridge.sh <peer> <token> eval   "1+1"                  # console: rapp.eval
bash vbridge.sh <peer> <token> agents                         # list their agents

In any tab's console you have the same API: rapp.neighborhood.host(), .ask(peer,text,secret), .operate(peer,method,args,secret).

C Β· Fly a kited twin tethered to this machine

# launch the kite tab with CDP on a private localhost port
"$CHROME" --headless=new --remote-debugging-port=9350 --user-data-dir=/tmp/kite "file:///path/to/kite.html" &
# hold the string; --brainstem makes the twin TETHERED to this machine
node kited_twin.js --port 9350 --brainstem http://localhost:7077

Connect two machines

Run the doorman skill on both machines. Each gives you its peer-id + token. Now either machine's twin (or you, from any browser/shell) reaches the other's brainstem β€” sealed both ways:

# from machine A, reach machine B's brainstem (end-to-end sealed)
bash vbridge.sh <peerB> <tokenB> ask "who are you and what can you do?"
Machine Abrainstem + doorman
β—€β”€β”€πŸ”’ sealed WebRTC πŸ”’β”€β”€β–Άbroker = handshake only
Machine Bbrainstem + doorman

Security rules the doorman enforces

  • CDP stays on the machine. Never bind/forward Chrome's debug port; cross-machine = WebRTC, not CDP.
  • Token = the key. It authorizes and derives the AES-256-GCM key. Share only via the out-of-band operator link; rotate by re-hosting.
  • Operating requires the sealed channel. Plaintext chat may be open; console ops are key-gated.
  • Closing ends it. Kill the host tab/Chrome β†’ the peer + secret are gone. No lingering access.
  • No plaintext secrets on disk or in logs; at rest uses the same vault primitive.

Tools

FileRole
doorman.skill.mdFeed its raw URL to a fresh Claude β†’ it sets up & guards the sealed door
doorman_selftest.shOne-command proof a machine can be a sealed doorman
brainstem_bridge.htmlFront a local brainstem into the neighborhood (sealed)
vbridge.shCLI peer β€” operate a hosted tab from a shell, sealed
kited_twin.jsThe kite string (CDP); --brainstem β‡’ tethered
index.htmlThe vBrainstem app β€” window.rapp.neighborhood

Troubleshooting

SymptomFix
Self-test fails at brainstem healthThe local brainstem isn't on BRAINSTEM_URL β€” start it (or set the URL).
Chrome not foundexport CHROME=/path/to/chrome and retry.
Two devices on different networks won't pairNAT traversal needs STUN/TURN β€” fine on normal nets; same-machine/LAN needs neither.
Bridge hangs at β€œstarting bridge”, never hostsThe page is HTTPS but the brainstem is http://localhost β€” serve the bridge from localhost (HTTPSβ†’localhost is blocked by mixed-content / private-network).
crypto.subtle undefinedThe bridge is on file:// β€” use the HTTPS page or a localhost server (secure contexts).
Visitor gets timeouts, not errorsThat's a wrong-key peer being shut out (it can't read the sealed rejection) β€” re-check the token.