86 lines
3.6 KiB
Markdown
86 lines
3.6 KiB
Markdown
# unibus playground
|
|
|
|
An all-in-one, web-based sandbox for the **unibus** message bus. One command
|
|
brings up the entire stack embedded — no NATS to install, no services to wire —
|
|
and a browser UI lets you exercise the bus visually: create peers, create and
|
|
join rooms (cleartext or end-to-end encrypted), invite, publish, watch messages
|
|
arrive live, and kick members (forward secrecy).
|
|
|
|
This is a **playground** (see `.claude/rules/playgrounds.md`): it lives inside
|
|
the `unibus` app, reuses the parent Go module (no separate `go.mod`), is not
|
|
indexed, and keeps all runtime state under `playground/local_files/` (ephemeral,
|
|
safe to delete).
|
|
|
|
## Run
|
|
|
|
From the `unibus` app directory:
|
|
|
|
```bash
|
|
cd /home/enmanuel/fn_registry/projects/message_bus/apps/unibus
|
|
go run ./playground
|
|
```
|
|
|
|
Then open **http://localhost:7700** in your browser.
|
|
|
|
Stop with `Ctrl-C` — the server tears down the web UI, every bus client, the
|
|
control plane, and the embedded NATS cleanly (no orphaned processes).
|
|
|
|
## Architecture
|
|
|
|
The browser never speaks NATS. The Go server is the actual bus peer:
|
|
|
|
```
|
|
browser ──fetch/SSE──▶ playground server (:7700)
|
|
│ holds one unibus client per named peer
|
|
├──HTTP──▶ membership control plane (127.0.0.1:8480)
|
|
└──NATS──▶ embedded NATS + JetStream (:4260)
|
|
```
|
|
|
|
- **:7700** — web UI (the only browser-facing port).
|
|
- **127.0.0.1:8480** — membership control plane (rooms, members, sealed keys,
|
|
rekey, blobs). Internal only.
|
|
- **:4260** — embedded NATS + JetStream (the data plane). Internal only.
|
|
|
|
Each named peer gets its own long-term identity, persisted to
|
|
`playground/local_files/<name>.id`, so a peer keeps the same endpoint across
|
|
restarts. When a peer creates or joins a room, the server subscribes on its
|
|
behalf and streams every received frame to that peer's open browser tabs over
|
|
Server-Sent Events.
|
|
|
|
The playground only orchestrates the public unibus client API
|
|
(`CreateRoom`, `Join`, `Subscribe`, `Publish`, `Invite`, `Kick`); it never
|
|
reimplements bus or crypto logic.
|
|
|
|
## Try it: 2 peers + encryption + kick
|
|
|
|
1. Open **two browser tabs** on http://localhost:7700.
|
|
2. Tab A: type `alice`, click **Connect**.
|
|
3. Tab B: type `bob`, click **Connect**.
|
|
4. Tab A (alice): type a subject like `room.general`, tick **🔒 encrypted
|
|
(E2E)**, click **Create room**. Copy the resulting `room_id`.
|
|
5. Tab A (alice): in the Action panel, pick `bob` as the target peer (use the
|
|
↻ button to refresh the peer list if needed) and click **Invite to this
|
|
room**.
|
|
6. Tab B (bob): paste the `room_id` into the join field and click **Join**.
|
|
7. Type messages in **both** tabs and hit Send — each message appears live in
|
|
both tabs, tagged with subject, sender, time, and 🔒 (encrypted) or `clear`.
|
|
8. Tab A (alice): click **Kick from this room** with `bob` selected. The room
|
|
key rotates to a new epoch. New messages alice sends are no longer visible to
|
|
bob — **forward secrecy**: bob no longer holds the current key.
|
|
|
|
Cleartext rooms (leave the checkbox unticked) behave like plain NATS fan-out:
|
|
fast, ephemeral, unsigned. Encrypted rooms are the Matrix-like mode: E2E
|
|
encrypted, persisted, and per-message signed.
|
|
|
|
## State / cleanup
|
|
|
|
All writable state lives under `playground/local_files/`:
|
|
|
|
- `<name>.id` — per-peer identity (private keys; treat like an SSH key).
|
|
- `play.db` — membership store (rooms, members, sealed keys).
|
|
- `blobs/` — media blob store.
|
|
- `js/` — embedded JetStream store.
|
|
|
|
Delete the whole `playground/local_files/` directory to reset to a clean slate.
|
|
It is gitignored and never distributed.
|