# sueta
Multi-user **p2p, end-to-end encrypted** chat PWA at **https://chat.ardegazu.ro** —
no third-party services, no origin server, no storage.
Public mirror (served from IPFS via git's dumb-HTTP protocol — no git server):
```sh
git clone https://git-chat.ardegazu.ro/sueta.git
```
MIT licensed — fork it and build your own p2p apps on the stack
(start at [client/src/lib/README.md](client/src/lib/README.md)).
```
you ⇄ friends WebRTC full-mesh datachannels (DTLS + app-layer AES-GCM)
room secret lives only in the URL fragment (#…) — never sent anywhere
signaling wss://signal.ardegazu.ro — self-hosted blind relay
(sees only ciphertext; cannot read SDP, names, or messages)
NAT traversal stun/turn @ stun.ardegazu.ro (coturn, ephemeral HMAC creds)
hosting IPFS — served through an ird tunnel that is never connected,
so its "offline page" (the pinned build) IS the site
```
Features: room lobby (your rooms live only on your device; the link IS the
room), threads, emoji reactions, image sharing (attach / paste / drop —
client-side re-encode strips EXIF+GPS and converts iPhone HEIC), persistent
Ed25519 identities with emoji fingerprints, TOFU + key-change warnings, and a
password-manager-friendly identity key (save it once, keep the same identity
on any device), installable PWA, mobile-first dark UI. History is peer-held:
members replay it to newcomers over the encrypted channels, and each device
persists its rooms locally (IndexedDB) — no server ever stores a byte.
## Layout
| Path | What |
|---|---|
| `docs/PROTOCOL.md` | crypto + wire protocol spec (the contract) |
| `docs/SIGNAL-SERVER.md` | reusable relay: ops runbook + how to attach new apps/domains |
| `client/` | Vite + vanilla TS PWA; `src/lib/` is the reusable p2p core (see its README) |
| `server/` | Go: blind WS relay + TURN credential minter, autocert TLS, one binary |
| `deploy/` | turnserver.conf, systemd unit, deploy script |
## Dev
```sh
# terminal 1 — signaling relay (plain HTTP)
cd server && go run . --dev
# terminal 2 — app on :5173 (proxies /ws + /turn-credentials to :8080)
cd client && npm install && npm run dev
# tests
cd server && go test ./...
cd client && node e2e/mesh.e2e.mjs # real-Chromium mesh e2e (needs both dev servers)
cd client && node e2e/call.e2e.mjs # audio/video call e2e (fake media devices)
```
## Deploy
```sh
deploy/deploy-server.sh # relay + coturn → root@78.47.93.79
cd client && npm run release # bumps version.json + builds
# then: tunnel_set_offline path=client/dist (ird)
```
Every release also republishes the anonymous open-source mirror:
commit (repo-local git identity is `sueta <sueta@noreply.local>`) →
`deploy/publish-repo.sh` (hard-fails unless the mirror has a single anonymous
author, zero identity bytes in any object, and no nested site build) →
`tunnel_set_offline tunnel=git-chat.ardegazu.ro path=deploy/.site`.
Versioning: integer builds (v1, v2, …) from `client/version.json`, bumped by
`npm run release`. Running apps poll for updates (5 min + on focus) and show a
one-tap "version N is ready" banner — no more double-refresh to pick up a deploy.
Rooms are capped at 16 peers by the relay; the full mesh is comfortable up to
~12. Bigger would need an SFU, which would no longer be this project.