J3vbandClaude Opus 5 7f87be6306 chore(lint): set complexity budgets to targets (intentionally red — backlog visible) (#1384)
* chore(lint): add ratcheted complexity budgets

Enables funlen, cyclop, nestif and dupl. Each threshold sits just above today's
worst offender, so the tree is green now and the budgets only block regression
past the current extreme:

  funlen    320 lines / 135 statements  (worst: main.go run, 311/131)
  cyclop    60                          (worst: ws handleVoiceJoin, 59)
  nestif    18                          (worst: 17)
  dupl      250 tokens                  (green boundary; 150 flags 3 real pairs)

Measured over 1446 production functions with tests excluded. Verified tight
rather than slack: 320/135 is green and 310/130 is not.

The budgets apply to production code only. Table-driven tests are legitimately
long, and duplicated setup between cases is clearer than a helper that hides
what each case does.

These are a ratchet, not a standard. 94 functions exceed 60 lines and 22 exceed
120; none of them are touched. The settings block records what each budget is
waiting on, including the three duplicate pairs that must be collapsed before
dupl can drop to the conventional 150.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* chore(lint): set complexity budgets to targets, not to what passes

Replaces the ratchet (thresholds parked just above today's worst) with real
targets. Existing offenders are left failing rather than excluded: an exclusion
list goes stale and quietly becomes permanent, whereas a failing check is a
backlog you can see and work off.

  funlen    100 lines / 50 statements   (was 320/135)
  cyclop    20                          (was 60)
  nestif    8                           (was 18)
  dupl      150 tokens                  (was 250)

These are not the tool defaults (60/40, 10, 4). Those descend from 1976-era
cyclomatic-complexity work predating Go's explicit error handling, where every
`if err != nil` costs a branch and idiomatic code scores high for no real
complexity — which is why golangci-lint's other cyclomatic linter, gocyclo,
defaults to 30 rather than 10. The values above are chosen for a Go server.

Also disables three output limits that hide work. uniq-by-line is the sharp one:
it keeps one issue per line, and because cyclop and funlen both anchor at the
function declaration, enabling cyclop silently swallowed 16 of funlen's 21
findings. The visible backlog was 46; the real one is 62.

This leaves the lint gate RED by design. No other linter regressed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-16 17:30:12 +02:00
2026-08-15 21:37:20 +02:00
2026-08-15 21:37:20 +02:00

CI Release Status Go Tauri Platforms License: AGPL-3.0

OwnCord

A self-hosted chat app I build for me and my friends — text channels, voice and video, and a server you actually own.

Alpha, and a hobby project. This is something I build for fun and run for a small group of friends. It isn't a product, there's no support, and it isn't production-ready. Expect rough edges, rapid changes, and the occasional breaking change.

Don't use it for anything sensitive.

It's a Go server plus a Tauri desktop client: real-time messaging, voice/video via LiveKit, file sharing, and a web admin panel. Run the server on a spare box or a VPS, hand your friends an invite code, and that's the whole thing.

OwnCord Client

Login Page Admin Panel

How it's built

Most of the implementation is generated with AI tooling, with quality held up by automated checks — CI, tests, linting — and by me and my friends actually using it. That keeps iteration fast, and it also means behaviour can change quickly between releases.

What works right now

Area Status
Core chat flow Working in alpha
Voice/video Working in alpha
Admin panel Working in alpha
Security hardening Ongoing review passes; findings and their statuses are tracked in the dated audits in docs/ (see the Docs Index below)

Platform Support (Current Releases)

Component Windows x64 Linux x64 Linux ARM64
Server binary Yes Yes Not yet
Desktop client Yes (NSIS installer) Yes (AppImage, .deb) Yes (AppImage, .deb)
Docker server N/A Build from source (compose) Not yet

Start Here

Quick Start

Option A: Prebuilt binaries

  1. Download assets from Releases (binaries, checksums, signatures, and a full source snapshot per release).
  2. Run the server binary:
    • Windows: chatserver.exe
    • Linux: ./chatserver
  3. Open https://localhost:8443/admin and complete the setup wizard — it creates your Owner account and configures the server for you (settings are saved to config.yaml automatically).
  4. Generate invite codes in the admin panel and share them with friends.

Option B: Docker (Linux server)

cd Server
cp .env.example .env
cp livekit.yaml.example livekit.yaml
# Edit both files before starting
docker compose up -d

See the full setup guide in docs/deployment.md.

The client uses TOFU (Trust On First Use) for self-signed certificates: it prompts once, then pins the certificate for future connections.

What OwnCord Already Has

  • Real-time channels and direct messages over WebSocket
  • Voice/video channels via LiveKit — the LiveKit server binary is downloaded and managed for you
  • Invite-only registration and role-based permissions
  • Web admin panel with logs, backups, and update tooling
  • File uploads and inline media rendering
  • TOTP 2FA support and API rate limiting
  • Desktop client auto-update with signature verification
  • WASM plugin system (slash commands; sandboxed, default-disabled — enable via plugins.enabled and build with -tags wazero)
  • GIF picker — off by default; each server supplies its own Klipy key via gif.api_key (setup)

See deeper feature and architecture docs in docs/architecture/ and docs/protocol.md.

Architecture

Two main components:

  • Go server (REST API, WebSocket hub, SQLite, admin panel)
  • Tauri v2 desktop client (Rust backend + TypeScript frontend)
+---------------------+         +---------------------+
|   OwnCord Client    |         |   OwnCord Server    |
|   (Tauri v2)        |         |       (Go)          |
|                     |         |                     |
|  +---------------+  |  WSS    |  +---------------+  |
|  |  Chat UI      |--+------->|  |  WebSocket Hub|  |
|  +---------------+  |         |  +---------------+  |
|  +---------------+  |  HTTPS  |  +---------------+  |
|  |  REST Client  |--+------->|  |  REST API     |  |
|  +---------------+  |         |  +---------------+  |
|  +---------------+  | LiveKit |  +---------------+  |
|  |  Voice/Video  |--+------->|  |  LiveKit SFU  |  |
|  +---------------+  |         |  +---------------+  |
+---------------------+         |  +---------------+  |
                                |  |  SQLite DB    |  |
                                |  +---------------+  |
                                +---------------------+

Build and Test

Prerequisites

  • Go 1.26+
  • Node.js 20+
  • Rust stable (client builds)

Build from source

# Server (Windows)
cd Server
go build -o chatserver.exe -ldflags "-s -w -X main.version=1.2.0-alpha.3" .

# Server (Linux)
cd Server
CGO_ENABLED=0 go build -o chatserver -ldflags "-s -w -X main.version=1.2.0-alpha.3" .

# Client
cd Client/tauri-client
npm install
npm run tauri build

Core verification commands

# Server
cd Server
go test ./...

# Client
cd Client/tauri-client
npm run typecheck
npm run lint
npm test

For the full command set, use docs/contributing.md.

Configuration

On first run, the server generates config.yaml and a local data/ directory:

data/
├── chatserver.db
├── certs/
├── uploads/
└── backups/

Key options include TLS mode, upload limits, LiveKit settings, and admin CIDR restrictions. See docs/server-configuration.md.

Security and Vulnerability Reporting

  • For vulnerabilities, use GitHub Security Advisories (private disclosure flow).
  • Do not open public issues for security bugs.
  • Read full policy and hardening notes in docs/security.md.

Update Signing Notes (Maintainers)

Client and server update signing keys are intentionally separate.

Required Actions secrets for release signing:

  • TAURI_SIGNING_PRIVATE_KEY
  • TAURI_SIGNING_PRIVATE_KEY_PASSWORD
  • SERVER_UPDATE_SIGNING_PRIVATE_KEY
  • SERVER_UPDATE_SIGNING_PRIVATE_KEY_PASSWORD

When rotating the server updater key, update Server/updater/server_update_public_key.txt and use staged rollover for live fleets.

Docs Index

Contributing

  1. Create a branch from dev (the active development branch).
  2. Keep changes focused and tested.
  3. Open a PR targeting devdev is merged to main for releases.

See docs/contributing.md for the full process.

License

AGPL-3.0

S
Description
OwnCord is a self-hosted, open-source chat platform with text channels, voice/video chat, direct messages, and a desktop client — built for communities that want full control over their data.
Readme AGPL-3.0
107 MiB
Languages
TypeScript 48.7%
Go 44%
JavaScript 2.2%
Rust 2.1%
CSS 1.4%
Other 1.5%