Commit Graph
479 Commits
Author SHA1 Message Date
J3vb c3a8aa477c fix: resolve 20 code review bugs across Rust, TypeScript, and Go
Critical/High Rust (Tauri client):
- BUG-140: replace .run() with .build() + RunEvent::Exit handler; native error dialog on startup failure
- BUG-141: eliminate PTT thread TOCTOU race with Mutex critical section; add AtomicBool shutdown and catch_unwind
- BUG-144: fix TOFU cert store corruption — read-before-write rollback restores previous fingerprint on save failure (all 3 write sites)
- BUG-145: add VK code range guard (1..=254) in is_key_down; fix cast to (state as i16) < 0
- BUG-147: replace bare spawns with JoinSet; abort_all + drain on exit; unconditional closed event
- BUG-150: add CRLF guard in handle_connection before header rewriting
- BUG-151: wrap header read loop in tokio::time::timeout(10s)
- BUG-158: extract CERTS_STORE/SETTINGS_STORE to constants.rs (eliminate 3 duplicates)
- HIGH-2: PTT thread self-cleanup uses unwrap_or_else defensive pattern
- HIGH-4: ws_send distinguishes Full vs Closed errors; warn log on backpressure

Critical/High TypeScript (Tauri client):
- BUG-142: join-generation counter prevents stale connectAndSetup completions
- BUG-143: replace 8 mutable LiveKit session fields with discriminated union SessionState
- BUG-146: 60s token refresh deadline; cleared on reply or voice leave
- BUG-148: ResizeObserver hoisted to outer scope; disconnect() in destroy() before ac.abort()
- BUG-152: dismissSignal.aborted guard already present (no change needed)
- BUG-153: measureRendered split into two-pass read-then-write; eliminates per-message reflow
- BUG-154: WS dedup cache batch-evicts to 80% on overflow (amortised O(1))
- BUG-157: pendingUpdates replaced with coalesced function-composition slot (O(1) queue depth)

Go server:
- BUG-149: safe two-value type assertion in getOutboundIP with localhost fallback
- BUG-155: broadcast buffer 256→1024; broadcastDrops atomic counter exposed in /api/v1/metrics
- BUG-156: LiveKitHealthCheck and implementations accept ctx context.Context; all call sites pass r.Context() (12 files)
- BUG-159: MaxMessageBytes constant in config/constants.go; replaces 1<<20 literals in serve.go and updater.go
- HIGH-1: cert store rollback reads old value before write; restores previous cert on save failure

All validation passes: go build, go vet, cargo check, npm typecheck
2026-04-03 23:18:06 +02:00
j3vbandClaude Sonnet 4.6 dcbcc09777 fix: update device_query v2 Keycode variants in ptt.rs for Linux
Return→Enter, Meta→LMeta|RMeta, remove NumLock/ScrollLock (not in v2).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 17:51:32 +02:00
J3vb 1fccb1cb9f fix: format gif-provider.test.ts with Prettier 2026-04-03 16:59:10 +02:00
J3vb ae6ee0b06d fix: correct docker/setup-buildx-action SHA and update TenorGif to GifResult in tests
- Fix typo in setup-buildx-action pin (d8db...→d36ec...) that caused CI to fail
- Replace stale TenorGif type with GifResult in gif-picker.test.ts lines 531-532
2026-04-03 16:49:07 +02:00
J3vb 4332541b3a fix: return f.Close() error in downloadFile to catch disk-full flush failures 2026-04-03 14:45:03 +02:00
J3vb 18d3161db6 docs: update README for Linux/ARM64/Docker/Klipy
- Quick start: add Linux x64/ARM64 download options, Docker quick-start
- Voice setup: show both binary (companion process) and Docker paths
- Features: GIF picker Tenor → Klipy, desktop client Windows → cross-platform,
  credential storage Windows Credential Manager → system keychain
- Building from source: update prerequisites and client output paths
- Tech Stack: add AppImage/deb, Docker LiveKit option
2026-04-03 14:40:49 +02:00
J3vb 344d39892f docs: update contributing and quick-start for Linux/ARM64/Docker
contributing.md:
- Prerequisites now show Windows/Linux/ARM64 support matrix
- Client commands split into Build, Tests, Typecheck/Lint/Format sections
- Add 7 missing commands: lint:ox, format, format:check, knip,
  test:mutate, test:mutate:dry, test:browser

quick-start.md:
- Prerequisites table covers Windows + Linux x64 + ARM64
- Step 1 split into 3 options: pre-built binaries, Docker, build from source
- Release table lists all platform artifacts (exe, AppImage, deb)
- Docker quick-start references deployment.md Docker section
2026-04-03 14:37:46 +02:00
J3vb 38da6cb2bd docs: add Docker + LiveKit deployment guide
- deployment.md: new Docker section with quick-start, config.yaml notes,
  data persistence, upgrade, and LiveKit reference
- livekit-setup.md: new Docker section with .env / livekit.yaml setup,
  node_ip explanation, and firewall table; companion process section
  retitled for clarity
2026-04-03 14:36:10 +02:00
J3vb d5cbd41bcb feat: add docker-compose with LiveKit for server Docker deployment
- docker-compose.yml: owncord + livekit/livekit-server on shared network
- Secrets (API key/secret) injected via .env → OWNCORD_VOICE_* env vars
- livekit.yaml.example: template config with port ranges and node_ip guidance
- .env.example: secret template with min-length reminder for API secret
- .gitignore: add .env / Server/.env to prevent accidental secret commits

Users: cp .env.example .env && cp livekit.yaml.example livekit.yaml,
fill in values, then docker compose up -d
2026-04-03 14:32:20 +02:00
J3vb 03969575e0 feat: Linux client port, ARM64 CI, and server Docker image
Client:
- Replace Win32 Credential Manager with cross-platform keyring crate
  (Windows Credential Manager / Linux Secret Service / macOS Keychain)
- Add Linux PTT support via device_query crate with VK-code-compatible
  mapping; thread-local DeviceState avoids repeated /dev/input/ opens
- Add AppImage + deb bundle targets to tauri.conf.json with Linux
  metadata and deb runtime dependencies

Cargo.toml:
- Add keyring = "3" (all platforms)
- Add device_query = "2" (Linux only, cfg guard)
- Remove Win32_Security_Credentials feature (no longer needed)

CI/CD:
- Add ubuntu-22.04 and ubuntu-22.04-arm to tauri-build matrix
- Fix Linux deps step condition: startsWith(matrix.os, 'ubuntu')
- Add server Docker build verification job (build-only, no push)
- Add release-client-linux (x86_64) and release-client-linux-arm64
  jobs producing AppImage + deb artifacts
- Add release-server-docker job pushing to ghcr.io on version tags
- Update publish job to include all Linux and ARM64 artifacts

Server:
- Add multi-stage Dockerfile (golang:1.25-bookworm → distroless/static)
- Non-root user (uid 65532), /app/data volume, port 8443 exposed
- Add .dockerignore excluding binaries, data, and local config
2026-04-03 14:26:26 +02:00
J3vb 0a08fd72bd feat: migrate GIF picker from Tenor to Klipy
Tenor shuts down June 30, 2026. Klipy is a drop-in replacement built
by the ex-Tenor team, free for production use.

- Replace tenor.ts with gifProvider.ts (api.klipy.com/v2)
- CDN allowlist updated to *.klipy.com (static.klipy.com is the real CDN)
- Add Klipy watermark logo to sent GIFs in chat (bottom-left)
- Update attribution text to "Powered by Klipy"
- Wire VITE_KLIPY_API_KEY secret into release workflow
- Add .env to .gitignore to protect local API key
2026-04-03 13:58:40 +02:00
J3vb 9d9d543179 docs: update deployment and contributing docs for Linux server support 2026-04-03 12:53:48 +02:00
J3vb 4393bf1349 fix: remove duplicate setScreenshareAudioVolume in video-grid mock 2026-04-03 12:43:24 +02:00
J3vb 5b5fb708f3 feat: add server Linux support (#105)
PR#88 Added server linux support and changed workflow
2026-04-03 12:42:30 +02:00
J3vb 0b1d178d31 fix: wire parseChecksumFileAny for Linux checksum lookup and add missing mock export
- updater.go: DownloadAndVerify now uses parseChecksumFileAny with
  checksumEntryNamesForGOOS so the linux/ path prefix produced by the
  release workflow's sha256sum is found correctly (fixes
  TestDownloadAndVerify_Success on ubuntu-latest)
- video-grid.test.ts: add setScreenshareAudioVolume to the
  @lib/livekitSession mock so vitest does not throw on the export
  that VideoGrid.ts imports
2026-04-03 12:27:33 +02:00
J3vb 0fab93361c fix: resolve CodeQL code scanning alerts
- ci.yml: add top-level `permissions: contents: read` to restrict
  GITHUB_TOKEN to minimum required (fixes 3 missing-workflow-permissions alerts)
- claude-code-review.yml: remove unsafe `ref: pull_request.head.sha`
  checkout in pull_request_target workflow and pin checkout to SHA
  (fixes untrusted-checkout/high alert)
- tenor.ts: add codeql suppression comment for hard-coded-credentials;
  the fallback key is Google's public anonymous demo key, not a secret
2026-04-03 11:47:44 +02:00
J3vbandClaude Sonnet 4.6 dc7859d284 fix: resolve Tauri full build TypeScript errors from tauri-typegen
- Consolidate ws-state and cert-tofu emit calls in ws_proxy.rs into
  private helper functions (emit_ws_state, emit_cert_tofu). One call
  site per event name prevents tauri-typegen 0.5.0 from generating
  duplicate event listener functions.
- Add CI fixup step that injects 'export type Value = unknown' into
  generated types.ts — tauri-typegen cannot map serde_json::Value to
  a TypeScript type, so the generated file references an undefined type.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 11:10:40 +02:00
J3vb d4f254b945 fix: bump rustls-webpki 0.103.9 → 0.103.10 (RUSTSEC-2026-0049) 2026-04-03 10:40:09 +02:00
J3vb 3b2ac9e8f2 ci: bump cargo-audit to 0.22.1 (CVSS 4.0 support) 2026-04-03 10:36:35 +02:00
J3vb 9a7318dd35 fix: resolve Clippy -D warnings in Tauri client
- Remove unused `use tauri::Manager` in commands.rs
- Remove dead hotkeys.rs module (register_push_to_talk, unregister_all never called)
- Fix `mut cred` → immutable in credentials.rs (CredWriteW takes &CREDENTIALW)
2026-04-03 10:21:06 +02:00
J3vb 7bd37ca750 ci: fix tauri-typegen version (0.1.3 → 0.5.0, matches Cargo.toml) 2026-04-03 10:05:01 +02:00
J3vb 79d0b29ec8 docs: add built-with attribution to README 2026-04-03 09:48:20 +02:00
J3vb 56c2875180 ci: fix Tauri rust-toolchain SHA and increase server test timeout
- Update dtolnay/rust-toolchain from stale SHA to current stable HEAD
- Add -timeout 20m to go test -race to prevent false timeouts on Windows
  CI runners where the race detector adds significant overhead across the
  large api test suite (was hitting the default 10m limit)
2026-04-03 09:44:55 +02:00
J3vb 8d1d1aa91f chore: move TODOS.md to local vault (docs/brain/) 2026-04-03 09:15:20 +02:00
J3vb 8c2ba52904 chore: move DESIGN.md to local vault (docs/brain/) 2026-04-03 09:14:50 +02:00
J3vb 07b2d7b578 Merge branch 'main' into dev 2026-04-03 09:10:14 +02:00
J3vb f1eee8dfc3 fix: add setScreenshareAudioVolume to livekitSession mocks in video tests 2026-04-03 09:05:18 +02:00
J3vb 998e06d947 chore: merge dev — resolve conflicts between Linux support and signing hardening
- release.yml: integrate signing/manifest/changelog steps with new
  multi-platform artifact layout (windows/ + linux/ dirs)
- updater.go: combine Linux tar.gz support with existing signature
  verification; merge platform-aware asset matching into switch
- updater_test.go: keep PR Linux tests + dev signing/manifest tests
2026-04-03 08:59:57 +02:00
J3vb 9e399384c3 fix: suppress gosec false positives in Linux server support
- G204 in proc_spawner_nix.go and proc_spawner_win.go: exePath is the
  server's own validated binary path, not arbitrary user input
- G302 in updater.go: 0o755 is required for the extracted Linux binary
  to be executable
2026-04-03 08:45:45 +02:00
J3vb 9f32736278 fix: resolve all 12 golangci-lint issues
- nilerr: mark intentional nil returns in DecryptTOTPSecret (backwards compat for unencrypted legacy secrets)
- gosec G703: suppress path traversal false positives in backup handlers (paths already sanitized by HasPrefix guard)
- contextcheck: thread context through handleWebhookParticipantJoined/Left; nolint goroutine in handleFreshConnect that intentionally detaches from request context
- errcheck: handle fmt.Fprintf return in handleWAFInterruption
- gocritic elseif: flatten else-if chain in upload_handler access check
- gocritic ifElseChain: rewrite asset name matching as switch in updater
- unparam: remove unused totpKey param from handleLogin (TOTP verification handled by separate handleVerifyTOTP endpoint)
2026-04-03 08:33:55 +02:00
J3vb 485040be32 security: validate avatar URLs on server and client
- Add validateAvatarURL helper enforcing https:// scheme, non-empty host, and 512-char max length
- Add rate limiting (10/min) to PATCH /api/v1/users/me profile update endpoint
- Guard avatar rendering in DmSidebar, DmProfileSidebar, and UserProfilePopup with isSafeUrl check to prevent unsafe URL injection in the UI
2026-04-03 08:10:26 +02:00
J3vb 5dbb89f237 feat: auto-grant microphone permission in WebView2 via --use-fake-ui-for-media-stream 2026-04-02 23:41:01 +02:00
J3vb e65a7d6a70 fix: harden server update signing 2026-04-02 23:35:11 +02:00
Vladislav Borisov 52a59b064f PR#88 Added server linux support and optimized ci/release workflow for multiplatform server build 2026-04-03 00:04:17 +07:00
J3vb 8184283ab0 fix: enable Claude Code Review for fork PRs via pull_request_target
OIDC tokens are not available for fork PRs with pull_request trigger.
Switch to pull_request_target and checkout the PR head SHA explicitly.
Also grant pull-requests: write so the action can post review comments.
2026-04-02 17:36:16 +02:00
J3vb 4ffd6731c2 fix: resolve CI failures from invalid golangci-lint SHA and ESLint unknown rules
Update golangci-lint-action to v9.2.0 with correct commit SHA. Change
eslint-disable-next-line to oxlint-disable-next-line for oxlint-specific
rules (consistent-function-scoping, prefer-add-event-listener,
require-post-message-target-origin) that ESLint doesn't recognize.
2026-04-02 17:32:36 +02:00
J3vb 2762e9a4ef chore: remove soundboard feature entirely
Soundboard was never implemented — remove USE_SOUNDBOARD permission bit,
rate limiter, protocol entry, admin mockup reference, TODOS entry, and
all related test assertions.
2026-04-02 17:00:27 +02:00
J3vb 56d330b930 updated readme 2026-04-02 16:54:33 +02:00
J3vb 7cdc2ef1ca feat: broadcast username changes to all connected clients via WebSocket
Add user_update event so other clients see profile changes in real-time
without needing to reconnect. Also updates saved credentials in Windows
Credential Manager when the current user changes their username.

Fixes: livekit-session test mock missing unpublishTrack property.
2026-04-02 16:33:11 +02:00
J3vb 9d0e9d95ec Merge pull request #101 from arcadia16/main
Add tech stack badges to the ReadMe
2026-04-02 16:24:57 +02:00
Arcadia 40f8f68297 Add tech stack
Dropped some badges, related to the project tech stack
2026-04-02 17:11:12 +03:00
J3vb 371862861f fix: mount profile routes so PATCH /api/v1/users/me works
MountProfileRoutes was never called in the router, causing 404 for
profile update, password change, and session management endpoints.
2026-04-02 16:04:25 +02:00
J3vb f7f5059a3a docs: sync README from dev — move Quick Start up, add IPv4 note 2026-04-02 15:50:50 +02:00
J3vb 0b6a0a80f8 updated readme 2026-04-02 15:50:07 +02:00
J3vb 9aa81ea83a Merge pull request #97 from arcadia16/readme-clarify
IPv4 + Quick start update
2026-04-02 15:43:10 +02:00
J3vb 9f74710d91 fix: send invite code instead of numeric ID for revoke endpoint
The client was sending DELETE /api/v1/invites/{id} with a numeric database
ID, but the server expects the invite code string. This caused a 404 since
no invite has a code matching a numeric ID.
2026-04-02 15:41:25 +02:00
Arcadia a3cee4f0cc IPv4 + Quick start update
1. Clarified where and how servers IPv4 is obtained
2. Moved "Quick start" to the top (why would you place it so far?)
2026-04-02 16:34:54 +03:00
J3vb f40e6787a9 fix: resolve remaining LOW security findings (L2-L14)
- Document single-instance requirement for in-memory rate stores (L2)
- Add IsOwnerRole() helper for explicit owner guards (L4)
- WS auth deadline uses request context, not context.Background (L5)
- Double-check voice state before clearing in webhook handler (L8)
- Upload stores measured write size instead of client header.Size (L11)
- Startup warning when config upload size exceeds HTTP body limit (L12)
- Update check endpoint now requires owner role (L13)
- Backup paths resolved to absolute at init time (L14)
2026-04-02 15:22:03 +02:00
J3vb e35e1b346c fix: encrypt TOTP secrets at rest and filter replay buffer by permissions
M1 — TOTP secrets are now AES-256-GCM encrypted before being stored in
the database. Key is auto-generated on first run (data/totp.key) or set
via OWNCORD_TOTP_KEY env var. Existing plaintext secrets are detected
and returned as-is for backwards compatibility.

M3 — Replay buffer events are now tagged with their channel ID. On
reconnect, the server computes the user's current accessible channels
and only replays events from those channels. Global broadcasts (presence,
voice state, member updates) are always replayed. Falls back to full
ready payload if permission computation fails.
2026-04-02 15:05:56 +02:00
J3vb 9e48e8d8e8 fix: security hardening — 11 findings across auth, WS, upload, admin, data
Security audit across all 11 sections (AUTH-001 through DATA-001) found
0 critical, 1 high, 7 medium, 15 low issues. This commit addresses:

- Add json:"-" to User.PasswordHash, User.TOTPSecret, Session.TokenHash
  to prevent accidental serialization of sensitive fields (M7)
- Add X-Content-Type-Options: nosniff to file serve responses (M5)
- Apply owner-only guard to backup list endpoint for consistency (M6)
- Persist rate-limit lockouts to SQLite so they survive restarts (M2)
- Normalize DM non-participant responses to 404 to prevent oracle (L3)
- Add explicit per-entry expiry check in partial auth Lookup/Consume (L1)
- Truncate unknown WS message type to 64 chars before echo (L6)
- Rate-limit ping handler to 2/sec per user (L7)
- Replace raw error strings in update handlers with generic messages (L15)
- Update 4 tests to match new 404 behavior for DM non-participant
2026-04-02 14:51:16 +02:00