Skip to content

Latest commit

 

History

History
130 lines (109 loc) · 10.4 KB

File metadata and controls

130 lines (109 loc) · 10.4 KB

Changelog

All notable changes to RushTalk are documented here. Format follows Keep a Changelog. Versioning follows Semantic Versioning.


[Unreleased]

Added — Authentication

  • Steam OAuth (OpenID 2.0) — full handshake with check_authentication round-trip, SteamID64 extraction from claimed_id, profile lookup via ISteamUser/GetPlayerSummaries
  • Google OAuth 2.0 + PKCE (S256) — confidential-client flow with backend-mediated token exchange, OIDC nonce validation
  • Tauri deep-link callback (rushtalk://auth/callback) via tauri-plugin-deep-link; tokens land in the desktop app via custom URL scheme
  • Redis-backed OAuth state store with single-use semantics (GETDEL) and 10-minute TTL — prevents CSRF and replay
  • Username derivation from provider display name with sanitisation + collision suffix; provider_* fallback for guaranteed uniqueness
  • Email-collision guard: OAuth users don't silently merge with existing password accounts
  • OAUTH_DESKTOP_CALLBACK_URL and OAUTH_STEAM_CALLBACK_URL env vars (with sane localhost defaults)
  • OAuth init and callback HTTP handlers under /auth/oauth/:provider/{init,callback}
  • Frontend: "Continue with Google" / "Continue with Steam" buttons on login page; /oauth/callback route handles deep-link tokens

Added — Social features

  • Friendships — full stack: domain entity (Friendship, FriendshipStatus), Postgres repo with unique-violation mapping, application service with auto-accept on mutual request, HTTP handlers (POST/GET/DELETE /api/v1/friends, /accept, /block), WS events (friend_request, friend_accept, friend_remove), Svelte store with derived acceptedFriends/incomingRequests/outgoingRequests, FriendsPanel.svelte modal with tabs (All/Pending/Add), badge on UserPanel for incoming requests
  • Message reactions — full stack: migration 004_reactions with (message_id, user_id, emoji) PK, Reaction entity, ReactionRepository with AddIfMissing (ON CONFLICT DO NOTHING + RowsAffected dedup), HTTP handlers (GET/POST/DELETE /api/v1/messages/:id/reactions[/...]), WS events (reaction_add, reaction_remove), reactionsStore with optimistic toggle + revert on API failure, MessageReactions.svelte sub-component with chips + inline picker (👍 ❤️ 😂 🎉 🚀 👀)
  • Typing indicators — frontend store with 5s TTL + GC tick, throttled notify() (3s), animated label in ChatPanel ("X is typing…", "X and Y are typing…", "Several people are typing…")

Added — Voice infrastructure

  • LiveKit Admin API integration — replaced stub CreateRoom/DeleteRoom with real Twirp HTTP calls to livekit.RoomService, idempotent room creation, ws://http:// URL conversion for the admin endpoint
  • Admin token minting with roomCreate/roomAdmin/roomList grants
  • Voice room Open/Close Prometheus gauge wired in VoiceHandler

Added — Audio engine

  • Linear-interpolation resampler (crates/rushtalk-audio/src/resampler.rs) — stateful, zero-alloc on hot path, is_identity() short-circuit at 48kHz; engages automatically when device's native rate isn't 48kHz (44.1k/96k/16k/etc.)
  • build_input_config rewrite: 4-tier fallback (i16@48k → i16@any → format@48k → device default) — every supported rate now produces correct 48kHz mono i16 downstream
  • Device hot-swap watchdog — Rust thread polls AudioEngine::capture_stream_errored() every 500ms; on stream error (mic unplugged, driver crash) emits audio:stream-error, calls restart_capture() to rebuild with current default device, emits audio:stream-recovered on success
  • cpal::StreamError propagation via shared Arc<AtomicBool> from err_fn into CaptureEngine::stream_error
  • New events: EVENT_AUDIO_STREAM_ERROR, EVENT_AUDIO_STREAM_RECOVERED in rushtalk-protocol/events.rs

Added — Observability

  • Custom Prometheus metrics (pkg/metrics):
    • rushtalk_http_requests_total{method,route,status} — uses route template (not URL) to bound cardinality
    • rushtalk_http_request_duration_seconds histogram
    • rushtalk_ws_connections_active gauge — wired to hub register/unregister
    • rushtalk_ws_events_published_total{op} counter
    • rushtalk_voice_rooms_active gauge
  • Structured audit logging (pkg/audit) — fixed-schema slog output with audit:true tag for downstream filtering. Wired in KickMember, CreateRole, DeleteRole, AssignRoles, ChannelDelete, MessageDelete

Added — Documentation

  • OpenAPI 3.0 spec (apps/api/docs/openapi.yaml) — hand-written, 21 endpoints, schemas for all entities; served at /openapi.yaml via //go:embed
  • Swagger UI at /docs (HTML loads swagger-ui-dist@5 from unpkg — no Go dep added)
  • CONTRIBUTING.md — local setup, repo layout, conventions per language, test commands, commit/PR style, security disclosure note

Added — UX & i18n

  • svelte-i18n integration with en and pt-PT locales (~150 keys across auth, oauth, voice, friends, chat, errors, sidebar, settings, audioToast, common)
  • Auto-detect: persisted choice in localStorage → browser locale (pt*pt-PT) → English fallback
  • setLocale() exposed for future language-picker UI
  • Components translated: +layout.svelte, login, register, oauth/callback, FriendsPanel, ChatPanel (typing labels with interpolation/pluralisation), UserPanel, ChannelSidebar, SettingsModal (all 5 tabs)
  • Error boundary in root layout via <svelte:boundary> with i18n-localised fallback UI and retry button
  • Toast notification system (stores/toasts.ts + ToastContainer.svelte) — info/success/error kinds, per-kind TTLs (errors sticky), update() for in-place morph without re-stack, fly+flip transitions
  • Audio stream error → toast lifecycle: "reconnecting…" (info, sticky) → "reconnected" (success, auto-dismiss) on recovery, or escalates to "Microphone is unavailable. Plug a mic in or pick one in Settings." (error) after 8s without recovery — single toast morphs through states, no stack churn

Added — Tests

  • Go: friendship/service_test.go (8 tests), auth/oauth/service_test.go (9 tests), infrastructure/livekit/client_test.go (URL conversion), interface/http/handler/reaction_test.go (validEmoji boundaries)
  • Frontend: stores/friends.test.ts (6 tests), stores/typing.test.ts (4 tests), stores/reactions.test.ts (6 tests)
  • Rust: resampler::tests (3 tests — identity, 44100→48000 upsample, multi-callback continuity)
  • Total test count: 25 Rust (was 22), 28 frontend (was 12), Go suites green across auth, oauth, friendship, server, livekit, handler

Changed

  • auth.Service.issueTokenPair → exported IssueTokenPair so OAuth flow can finalise login through the same session/JWT bookkeeping path
  • Handlers struct in interface/http/router.go extended with Friendship and Reaction handlers
  • AudioEngine: new fields capture_stream_error (Arc) and methods current_input_device(), capture_stream_errored(), restart_capture()
  • CaptureEngine::into_streaminto_parts() returning both Stream and the shared error flag
  • tauri.conf.json declares deep-link plugin with scheme rushtalk
  • tauri-plugin-deep-link = "2" added to src-tauri/Cargo.toml; deep-link:default capability added

Migrations

  • 004_reactionsmessage_reactions table with (message_id, user_id, emoji) PK, (message_id, emoji) covering index, FK cascade to messages/users

Added — original (pre-session)

  • Tauri auto-updater via tauri-plugin-updater (minisign-signed GitHub releases)
  • GitHub Actions CI: Go / Rust / Vitest test pipelines
  • GitHub Actions Release: multi-platform Tauri builds + Docker image push to GHCR
  • Multi-stage Dockerfile for the Go API (distroless runtime, ~20 MB image)
  • docker-compose.yml for full local dev stack (API + Postgres + Redis + MinIO + LiveKit + Prometheus + Grafana)
  • MinIO bucket auto-init service in docker-compose (rushtalk-uploads)
  • Kubernetes manifests: Namespace, ConfigMap, Deployment + Service + HPA, Ingress (nginx + cert-manager TLS)
  • Prometheus scrape config with K8s pod annotation discovery
  • deploy/k8s/secrets.example.yaml — template for all required K8s secrets
  • Root Makefile with dev-up/down, test, build, k8s-*, keys, migrate-* targets
  • /metrics endpoint (Prometheus) on the Go API
  • Audio diagnostic counters: underrun events + PLC (Packet Loss Concealment) frames
  • Diagnostics tab in Settings modal with 2-second auto-refresh
  • WebSocket Hub context cancellation for clean shutdown
  • SQL migrations (golang-migrate): all 16 tables across 3 migration files

Changed

  • ws.Hub.Run() now accepts context.Context to support graceful shutdown
  • Voice command signature updated: join_channel now takes livekit_url and token

[0.1.0] — Phase 5.1

Added

  • Adaptive jitter buffer with EMA-based target depth (10–80 ms)
  • Time-based audio mixer: 10 ms tick, per-user silence/PLC fallback, stale-user GC
  • Thread priority boost for capture and playback audio threads
  • Spin-yield capture loop (64-iter spin budget before sleep fallback)
  • 5 ms cpal buffer requests (Fixed(240) samples) for both capture and playback
  • Adaptive Opus FEC: report_network_stats(loss_pct) wired to encoder set_packet_loss_perc
  • LiveKit NativeAudioSource queue reduced from 100 ms to 20 ms

[0.1.0-beta] — Phase 1–4

Added

  • Tauri 2.0 desktop app with Svelte 5 frontend
  • Rust audio engine: cpal capture, Opus encode/decode, LiveKit PCM pipeline, cpal playback
  • LiveKit SFU integration (livekit = "0.7") for voice rooms
  • Go backend (Echo framework): auth (JWT RS256), servers, channels, messages, voice, file uploads
  • WebSocket Gateway (gorilla/websocket): presence, typing, message, voice-state events
  • Discord-style UI: ServerSidebar, ChannelSidebar, ChatPanel, VoicePanel, UserPanel
  • Gaming overlay: always-on-top transparent Tauri window, Shift+` global shortcut, drag-to-reposition
  • Settings modal: Audio / Voice / Overlay tabs + Diagnostics
  • Context menus: right-click channels and voice users
  • Prometheus metrics via /metrics
  • PostgreSQL repositories for all domain entities
  • Redis session blocklist (JWT revocation)
  • Rich presence / game detection via sysinfo