mirror of
https://github.com/J3vb/OwnCord.git
synced 2026-09-03 03:50:00 +03:00
Add docs/architecture/ — a curated blueprint set with 10 Mermaid diagrams covering system context, deployment topology, server package map, REST request lifecycle, WebSocket auth/replay/dispatch, the full data model (migrations 001-015), voice/E2EE flow, and the client module map. Add docs/audit-2026-07-19.md — successor to audit-2026-04-07.md: re-verifies carried-over findings, catalogues spec-vs-code drift in api.md/protocol.md/schema.md (incl. the announcement channel-type contradiction and the undocumented voice-E2EE protocol surface), records server/client/CI findings with file:line evidence, and closes with a 12-item prioritized improvement backlog. Link both from the README docs index. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UA17KPvqGBX3XbXYnMf1rA
100 lines
4.2 KiB
Markdown
100 lines
4.2 KiB
Markdown
# System Overview
|
|
|
|
**Verified against:** commit `ddc49f0`, 2026-07-19
|
|
|
|
OwnCord is a self-hosted chat stack: one Go server binary per community, a Tauri
|
|
desktop client that can hold profiles for many servers (one active connection at
|
|
a time), LiveKit for voice/video media, and an embedded web admin panel.
|
|
|
|
## D1 — System context and trust boundaries
|
|
|
|
```mermaid
|
|
flowchart LR
|
|
subgraph desktop ["Desktop client (Tauri v2)"]
|
|
WV["Webview (TS)<br/>UI, stores, dispatcher"]
|
|
subgraph sidecars ["Rust commands"]
|
|
WSP["ws_proxy<br/>TOFU-pinned WSS"]
|
|
LKP["livekit_proxy<br/>TOFU-pinned TLS tunnel"]
|
|
CRD["credentials<br/>OS keychain"]
|
|
UPD["updater<br/>pinned TLS + minisign"]
|
|
end
|
|
WV --- sidecars
|
|
end
|
|
|
|
subgraph server ["Self-hosted Go server (single binary)"]
|
|
RTR["api router<br/>REST /api/v1"]
|
|
HUB["ws Hub<br/>real-time"]
|
|
ADM["admin SPA + REST<br/>(IP-gated)"]
|
|
PLG["plugin runtime<br/>(wazero, opt-in)"]
|
|
DBF[("SQLite file<br/>WAL, single writer")]
|
|
UPS["file storage<br/>uploads/"]
|
|
end
|
|
|
|
LK["LiveKit server<br/>(managed subprocess<br/>or external)"]
|
|
REL["OwnCord-releases<br/>(GitHub, minisign-signed)"]
|
|
|
|
WV -->|"HTTPS REST<br/>⚠ accepts any cert<br/>(no pinning)"| RTR
|
|
WSP -->|"WSS, fingerprint-pinned"| HUB
|
|
LKP -->|"TLS, fingerprint-pinned"| LK
|
|
WV -->|"admin panel (browser)"| ADM
|
|
HUB <-->|"webhooks + server SDK"| LK
|
|
RTR --> DBF
|
|
HUB --> DBF
|
|
RTR --> UPS
|
|
PLG -.->|"allowlisted HTTP only"| NET["external hosts"]
|
|
UPD -->|"via connected server URL"| REL
|
|
server -->|"self-update check"| REL
|
|
```
|
|
|
|
**What this shows.** Three transport paths leave the client and only two are
|
|
certificate-pinned: the app WebSocket and the LiveKit tunnel go through Rust
|
|
proxies that pin a trust-on-first-use SHA-256 fingerprint per host; the HTTP
|
|
REST path currently accepts any certificate (an acknowledged gap tracked in the
|
|
audit). The admin panel is served by the same binary but gated to configured
|
|
CIDRs (private ranges by default), with bearer admin auth on top for the plugin
|
|
endpoints. Plugins run in a WASM sandbox whose HTTP capability is allowlisted
|
|
per manifest. Both the server self-updater and the client updater verify
|
|
minisign signatures against pinned embedded public keys.
|
|
|
|
## D8 — Deployment topology
|
|
|
|
```mermaid
|
|
flowchart TB
|
|
subgraph hostbox ["Operator host (or Docker)"]
|
|
BIN["owncord server binary"]
|
|
BIN --> CFGF["config.yaml<br/>(koanf: defaults → YAML → OWNCORD_* env)"]
|
|
BIN --> DATA["data dir<br/>SQLite DB + uploads + TLS certs"]
|
|
BIN --> LKPROC["livekit-server<br/>(optional managed subprocess)"]
|
|
BIN --> P1[":8443 HTTPS + WSS<br/>API, WS, admin, uploads"]
|
|
BIN -.-> P80[":80 ACME HTTP-01<br/>(when TLS mode acme)"]
|
|
LKPROC --> P2["LiveKit ports<br/>(WS + UDP media range)"]
|
|
end
|
|
|
|
C1["Tauri clients"] --> P1
|
|
C1 --> P2
|
|
ADMB["Admin browser<br/>(allowed CIDRs only)"] --> P1
|
|
|
|
subgraph constraints ["Single-instance constraints (scale-out blockers)"]
|
|
R1["in-memory rate-limiter windows<br/>(lockouts persisted, windows not)"]
|
|
R2["in-memory pub/sub + replay ring buffer"]
|
|
R3["process-local TOTP replay store"]
|
|
R4["SQLite single-writer (MaxOpenConns=1)"]
|
|
end
|
|
BIN --- constraints
|
|
```
|
|
|
|
**What this shows.** The deployment unit is one process per community —
|
|
TLS (self-signed, custom, or ACME), the DB, uploads, the admin panel, and
|
|
optionally LiveKit are all owned by that process. The design is explicitly
|
|
single-instance: rate-limit windows, pub/sub, the replay ring buffer, and the
|
|
TOTP replay store are process-local, and SQLite runs with a single writer.
|
|
Horizontal scaling is out of scope today; the constraint boxes name exactly
|
|
what would have to move to shared infrastructure if that ever changes. A
|
|
15-minute maintenance goroutine (expired sessions, orphaned attachments, with a
|
|
circuit breaker) and graceful drain on SIGINT/SIGTERM round out the process
|
|
lifecycle.
|
|
|
|
**Source of truth:** `Server/main.go`, `Server/config/config.go`,
|
|
`Server/docker-compose.yml`, `docs/deployment.md`, `docs/server-configuration.md`,
|
|
`Client/tauri-client/src-tauri/src/lib.rs`.
|