sueta / README.md
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# 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.