Commit Graph
98 Commits
Author SHA1 Message Date
jevb 13797e7075 fix: resolve 6 medium issues from full go-review
- MED-1: Document soundboard channelID=0 server-wide permission intent
- MED-2: Document os.Exit(0) in update handler skipping deferred cleanup
- MED-3: Replace os.ReadFile/WriteFile with streaming io.Copy in backup
  restore to avoid loading entire DB into memory
- MED-4: Add GetAllVoiceStates bulk query, eliminating N+1 per-channel
  queries in collectAllVoiceStates
- MED-5: Wrap handlePatchSettings updates in a transaction for atomicity
- MED-6: Add rows.Err() check after scan loop in getReactionsBatch
- MED-9: Replace manual port-stripping in serverHost with net.SplitHostPort
  for correct IPv6 handling
2026-03-19 04:04:53 +01:00
jevb 65a8403a92 fix: resolve 1 critical and 5 high security/reliability issues from go-review
- CRIT-2: Prevent HTTP header injection in Content-Disposition via mime.FormatMediaType
- HIGH-1: Call hub.GracefulStop() on server shutdown to clean up WebSocket/voice state
- HIGH-2: Remove double send on serveErr channel that caused goroutine leak
- HIGH-3: Handle GetUserByID error after registration to prevent nil panic
- HIGH-4: Return nil,nil on sql.ErrNoRows in GetAttachmentByID (matching codebase convention)
- HIGH-5: Add voiceDone channel to bound RTP goroutine lifetime on voice teardown
- Fix handleVoiceICE to return VOICE_ERROR when no PC (consistent with other voice handlers)
- Update tests to match corrected behavior
2026-03-19 03:53:40 +01:00
jevb a06d805ada docs: update README with voice NAT traversal, per-user volume, noise suppression
- Replace inaccurate "built-in TURN/STUN" with actual setup (Google STUN + external_ip)
- Add per-user volume, RNNoise noise suppression, VAD, silence suppression to features
- Add voice.external_ip to config table
- Update tech stack to reflect Google STUN instead of built-in TURN
2026-03-18 23:09:52 +01:00
jevb 577f50decb chore: add chatserver.exe~ to gitignore 2026-03-18 23:03:14 +01:00
jevb 5311d0a7e3 feat: fix voice chat over NAT, audio pipeline, and add comprehensive debugging
Voice was broken over NAT due to multiple issues across the audio pipeline:

- Fix GainNode silence: WebView2 silences remote WebRTC streams routed through
  Web Audio createMediaStreamSource→GainNode→createMediaStreamDestination.
  Replaced with direct HTMLAudioElement playback for remote audio.
- Fix NAT traversal: Add Google public STUN server (stun.l.google.com:19302)
  so remote clients can discover their public IP for ICE connectivity.
- Fix signaling race: Catch createOffer InvalidStateError when server
  renegotiation offer arrives before client's initial offer is sent.
- Fix device switch: Use replaceTrack() instead of removeTrack+addTrack
  to avoid SDP renegotiation. Safe rollback on failure (stop old last).
- Fix speaking flicker: setSpeakers skips local user (VAD is sole authority).
- Fix VAD sample rate: Force 48kHz AudioContext instead of system default
  (192kHz) which spread FFT bins too wide for voice frequency detection.
- Fix CSP for WASM: Add wasm-unsafe-eval to script-src for RNNoise.
- Fix clearAuth leak: leaveVoice() called before resetVoiceStore().
- Fix ICE rate limit: Separate limit for ICE candidates (50/s vs 20/s).
- Fix stale ICE errors: Silently drop voice_ice with no PeerConnection.
- Fix audio play() race: Deferred to queueMicrotask after DOM attachment.

Debugging infrastructure:
- Logs tab: Copy All button, Voice Diagnostics panel with live session
  state, Probe Audio Levels (measures actual signal at 3 pipeline points),
  Test Direct Playback button, Copy Diagnostics button.
- Client logging: WebRTC (PeerConnection lifecycle, ICE candidates with
  type/address, track events, negotiation), VAD (start/threshold/destroy),
  Audio (device acquisition with settings, device changes), noise suppression
  (WASM load timing, worklet vs fallback path), voiceSession (remote stream
  parsing failures, deafen state, audio element playback events).
- Server logging: SFU init config, voice room mode transitions/track
  lifecycle/close, RTP forwarding with packet counts and first-packet
  detection, 5s no-packet warning, track fan-out counts, subscriber
  transceiver state, ICE candidate details, voice credentials issued.
- Logger: Error objects now serialize .message and .stack instead of {}.

Per-user volume right-click now works on voice user rows in sidebar.
RNNoise ML noise suppression with AudioWorklet + ScriptProcessor fallback.
Tests: 7 new test cases (replaceTrack, setSpeakers skip-local, clearAuth).
2026-03-18 23:02:06 +01:00
jevb b3bcb283ee docs: rewrite README with current features, architecture, and config 2026-03-18 17:56:03 +01:00
jevb 01e4d4bec3 feat: client auto-update with Ed25519 signing and dynamic server URL
- Add tauri-plugin-updater and tauri-plugin-process for in-app updates
- Rust commands (check_client_update, download_and_install_update) build
  updater with dynamic endpoint at runtime for self-hosted compatibility
- Server endpoint GET /api/v1/client-update/{target}/{version} translates
  GitHub Releases into Tauri updater JSON format with .sig content
- UpdateNotifier banner component with install/dismiss controls
- CI workflow produces signed .nsis.zip + .sig updater artifacts
- Self-signed TLS support via dangerousAcceptInvalidCerts config
2026-03-18 17:47:59 +01:00
jevb 750a7af052 feat: native file downloads, upload size fix, native E2E tests
- Add file download with native save dialog (Tauri dialog + fs plugins)
- Make attachment filename clickable as additional download trigger
- Add download button with hover styling to file attachments
- Exempt /api/v1/uploads from global 1MB body size limit (MaxBodySizeUnless)
- Add native E2E test suite (8 specs) with Playwright CDP fixture
2026-03-18 17:10:16 +01:00
jevb 13be0fd6d3 feat: file uploads, URL previews, emoji search, voice mute fixes, UX improvements
Server:
- Add POST /api/v1/uploads and GET /api/v1/files/{id} endpoints
- Add CreateAttachment DB method for file upload records
- Allow empty message content when attachments are present
- CORS headers on file serving for WebView2 compatibility

Client — File uploads & attachments:
- Clipboard paste (Ctrl+V) and attach button (+) for file uploads
- Preview bar above input with thumbnail, spinner, and remove button
- Images fetched via Tauri HTTP plugin as base64 data URIs (bypasses
  self-signed cert rejection in WebView2)
- Three-layer image cache: memory → IndexedDB → network
- In-flight deduplication prevents duplicate concurrent fetches
- Image lightbox with click-to-zoom, scroll wheel zoom, pan, keyboard shortcuts

Client — URL previews & embeds:
- URLs in messages rendered as clickable links
- YouTube embeds with thumbnail, play button, video title via oEmbed API
- Generic link previews with OG metadata (title, description, image)
- Fetched via Tauri HTTP plugin with Facebook crawler User-Agent
- YouTube title cache and OG metadata cache prevent re-fetch on re-render
- Links open in default browser via tauri-plugin-opener

Client — Voice & audio fixes:
- Mute uses replaceTrack(null) for reliable RTP-level muting in WebView2
- Deafen also mutes mic; undeafen/unmute unmutes both
- Muted users show crossed mic icon, deafened show crossed mic + headphone
- Re-apply mute state after input device switch

Client — UX improvements:
- Disable browser context menu globally (only custom menus show)
- Emoji search now matches by keyword names (smile, heart, fire, etc.)
- Emoji picker closes on click outside
- User bar status text moved below username
- Messages sorted chronologically (oldest first, newest at bottom)
- Scroll to bottom on initial load with deferred retries for layout shifts
- Image attachments constrained to 400x350px with click-to-lightbox
2026-03-18 14:13:52 +01:00
jevb e1659fcfd2 fix: remove duplicate mute/deafen buttons from user bar, disable browser context menu
- Remove microphone and headphone buttons from UserBar (already in VoiceWidget)
- Disable default browser right-click menu globally so only custom context menus show
2026-03-18 11:33:59 +01:00
jevb f36fb1ffdc feat: channel management — create, edit, delete, reorder with category-type enforcement
Server:
- Enforce category-type validation: text/announcement only under text categories,
  voice only under voice categories (400 on mismatch)
- Admin panel category field changed to dropdown with auto-filtered type options
- Default setup creates both Text Channels and Voice Channels categories

Client:
- Add create/edit/delete channel modals (admin/owner only)
- "+" button on category headers to create channels with pre-filled category
- Right-click context menu on channels for edit/delete
- Mouse-based drag-and-drop reordering within categories
- Admin API methods: adminCreateChannel, adminUpdateChannel, adminDeleteChannel
- Immediate local store update on reorder for instant feedback

Tests: 7 server integration tests, 31 client unit tests (create/edit/delete modals)
2026-03-18 11:28:13 +01:00
jevb 32c39e95aa fix: prevent stale PeerConnection callbacks from killing new voice sessions
When switching voice channels, the old PC's OnICEConnectionStateChange(closed)
fires asynchronously after the new PC is set. Both server and client had the
same race: the stale callback saw "voice is active" and called handleVoiceLeave,
closing the new session.

Server: setupICEMonitor now compares the PC reference before acting on events
Client: joinVoice now calls leaveVoice(false) to clean up old session first
2026-03-18 07:24:19 +01:00
jevb b0b7fa146a fix: add missing localCamera/localScreenshare to VoiceState resets in tests 2026-03-18 07:09:45 +01:00
jevb 5140505704 fix: voice session safety, delete confirm UX, image URL validation, test coverage (BUG-039 through BUG-045)
- BUG-039: switchOutputDevice continues loop on partial failure instead of early return
- BUG-040: clearOnError() prevents stale callback after MainPage destroy
- BUG-041: voice store tests cover localCamera, localScreenshare, setLocalSpeaking
- BUG-042: auth store updateUser tests and UserBar mute/deafen callback tests
- BUG-043: switchInputDevice guards against no active WebRTC session
- BUG-044: replace synchronous confirm() with double-click-to-delete via toast
- BUG-045: isSafeUrl() blocks javascript: URLs in image attachment src
2026-03-18 07:03:53 +01:00
jevb dcea5bc0ab fix: device switching, DM highlight, WebRTC error toast, close false positives (BUG-031, BUG-032, BUG-033, BUG-034, BUG-035, BUG-036)
- BUG-031: Add switchInputDevice/switchOutputDevice to voiceSession;
  VoiceAudioTab now applies device changes to active WebRTC session.
- BUG-032: Closed as false positive — channel WS handlers already wired
  in dispatcher.ts:173-200.
- BUG-033: Closed as false positive — member WS handlers already wired
  in dispatcher.ts:219-229.
- BUG-034: Closed as false positive — InviteManager filter runs inside
  .then(), not before promise resolves.
- BUG-035: DmSidebar click handler now toggles .active class on items.
- BUG-036: Add setOnError callback to voiceSession; MainPage wires it
  to toast for WebRTC failure feedback.
2026-03-18 06:45:05 +01:00
jevb 036ed3e4ed fix: render actual images for attachments, remove orphaned components (BUG-026, BUG-030)
- BUG-026: Replace placeholder div with <img src=att.url> element in
  renderAttachment, with lazy loading and error fallback.
- BUG-030: Delete orphaned MessageActionsBar.ts and ReactionBar.ts
  components (never imported) along with their tests.
2026-03-18 06:40:12 +01:00
jevb 25101c4ac4 fix: message operations — reaction toggle, delete confirm, edit validation, toasts (BUG-024, BUG-028, BUG-029, BUG-037, BUG-038)
- BUG-024: Toggle reaction_add/reaction_remove based on me field.
- BUG-028: Add confirm() guard before chat_delete.
- BUG-029: Validate edit content is non-empty and changed.
- BUG-037: Show error toast when reaction rate limited.
- BUG-038: Add success toasts for delete and edit operations.
2026-03-18 06:35:55 +01:00
jevb 182ca41b4d fix: wire voice controls — camera, screenshare, UserBar mute/deafen, VAD (BUG-021, BUG-022, BUG-023, BUG-027)
- BUG-021: Camera toggle reads actual localCamera state from voice store
  instead of hardcoded false.
- BUG-022: Screenshare toggle sends voice_screenshare WS message with
  localScreenshare state tracking.
- BUG-023: UserBar mute/deafen buttons wired via UserBarOptions callbacks
  passed from MainPage, with voice channel guard and rate limiting.
- BUG-027: VAD onSpeakingChange callback wired to setLocalSpeaking in
  voice store for local speaking indicator feedback.
- Added localCamera, localScreenshare, setLocalSpeaking to voice store.
2026-03-18 06:33:17 +01:00
jevb b1b4f4c76b fix: wire account settings callbacks and theme store sync (BUG-020, BUG-025)
- BUG-020: Wire api.changePassword() and api.updateProfile() into
  MainPage settings overlay callbacks. Add updateUser() to auth store
  for username sync. Add toast feedback for success/error.
- BUG-025: Call setTheme() in AppearanceTab click handler so uiStore
  stays in sync with localStorage and applied CSS.
- Update test mock to include setTheme export.
2026-03-18 06:28:45 +01:00
jevb 681edab65a fix: harden E2E tests with anti-flakiness config and voice widget selector fixes
Add actionTimeout, navigationTimeout, local retry, video capture, and
reducedMotion to both Playwright configs. Introduce waitForWsReady(),
navigateToMainPageReady(), and emitWsMessageAndWait() helpers. Fix
voice-widget selectors to match actual DOM structure. Update
E2E-ISSUES.md to reflect 209/209 passing.
2026-03-18 05:38:53 +01:00
jevb e7f53000f3 fix: add nil hub tests for PatchUser ban and role change paths (BUG-001)
Closes the last untested nil-pointer panic path in admin API handlers.
BUG-002 (window-state.ts any) confirmed already resolved.
2026-03-18 05:15:54 +01:00
jevb fca1b0cc0c test: boost server test coverage to 80%+ across all packages
Add comprehensive tests for db, storage, updater, and ws packages
covering edge cases, error paths, and voice handler functions.
New test files for attachment queries and WebSocket coverage boost.
2026-03-18 05:03:38 +01:00
J3vb 8a85386480 Merge pull request #24 from J3vb/tauri-migration
feat: add working voice chat with SFU track forwarding
2026-03-18 04:34:40 +01:00
jevb b78c9319fa fix: resolve CI failures — coverage exclusion and stale test removal
- Exclude voiceSession.ts from coverage (browser API dependency, same
  pattern as audio.ts/vad.ts/webrtc.ts)
- Remove stale TestHub_Register_CleansUpOldVoiceState test that tested
  old duplicate-login behavior removed in b53c729
2026-03-18 04:30:38 +01:00
jevb 6ca8449fc9 fix: guard ICE close handler to prevent double voice_leave and SQLITE_BUSY 2026-03-18 04:16:49 +01:00
jevb 66abbed49d fix: voice session cleanup on ICE close and connection failure
- Server: handle ICEConnectionStateClosed in setupICEMonitor to clean up
  phantom participants when client PC is destroyed
- Server: skip TURN config when turn_secret is empty (suppresses noisy
  "password is empty" errors)
- Client: voiceSession.leaveVoice() now sends voice_leave to server by
  default, fixing the case where WebRTC failure triggers local cleanup
  but server never learns the user left
- Client: explicit leave paths (UI button, logout, beforeunload) pass
  sendWs=false to avoid double-sending voice_leave
2026-03-18 04:13:12 +01:00
jevb b067c71c13 feat: wire voiceSession into MainPage and main.ts lifecycle 2026-03-18 04:02:05 +01:00
jevb b3293b2720 feat: add voice_offer/answer/ice dispatcher handlers 2026-03-18 03:59:41 +01:00
jevb 0a964cc35f feat: create voiceSession module for voice lifecycle orchestration 2026-03-18 03:57:57 +01:00
jevb 2461903520 feat: add handleServerOffer with SDP rollback and createOffer 2026-03-18 03:55:49 +01:00
jevb 64b5f43176 feat: wire SFU track forwarding and renegotiation in voice handlers
Rewrites setupOnTrack to create TrackLocalStaticRTP for fan-out,
store tracks on VoiceRoom, add them to other participants' PCs,
and forward RTP while parsing audio levels. Updates handleVoiceJoin
to subscribe new joiners to existing tracks and handleVoiceLeave
to remove departing users' tracks from all subscribers.
2026-03-18 03:53:22 +01:00
jevb db6cd01afe feat: add renegotiateParticipant with Perfect Negotiation
Adds Hub.renegotiateParticipant to ws/voice_handlers.go. The function
creates a new SDP offer for a client's PeerConnection and sends it as
voice_offer, implementing the impolite side of Perfect Negotiation by
skipping renegotiation when the PC is in have-remote-offer state.
2026-03-18 03:49:23 +01:00
jevb 6034bb1929 feat: add GetClient helper and ICE candidate callback 2026-03-18 03:47:30 +01:00
jevb 8889faddef feat: add buildVoiceOffer and buildVoiceICE message builders
Add two new server-to-client WebSocket message builders following the
existing buildVoiceAnswer pattern. Expose them via export_test.go
wrappers and cover with ws_test package tests (TDD: RED → GREEN).
2026-03-18 03:44:38 +01:00
jevb b3e4dd7adb feat: add VoiceTrack struct and track CRUD to VoiceRoom
Introduces VoiceTrack (Remote/Local track pair + per-subscriber RTPSender map)
and five thread-safe methods on VoiceRoom (SetTrack, RemoveTrack, GetTracks,
TrackUserIDs, GetTrack) needed for SFU audio forwarding in Phase 3.
Close() now also resets the tracks map. Five new tests cover all paths (TDD).
2026-03-18 03:41:48 +01:00
jevb 2181e184cb fix: correct VoiceIcePayload candidate type to RTCIceCandidateInit
The candidate field was typed as string but the server's handleVoiceICE
parses it as webrtc.ICECandidateInit (an object with candidate, sdpMid,
sdpMLineIndex, usernameFragment fields). Corrected to RTCIceCandidateInit.
PROTOCOL.md voice_ice example updated locally (gitignored vault).
2026-03-18 03:38:04 +01:00
jevb b53c729f89 fix: reject duplicate WebSocket logins to prevent reconnect ping-pong
Server now checks IsUserConnected before accepting a new WebSocket and
returns an auth_error with a clear message instead of silently replacing
the old session. Client dispatcher surfaces the error via transient UI
state so the ConnectPage can display it.
2026-03-18 02:41:55 +01:00
jevb 6f35973c1b feat: TOFU cert pinning, voice channel sidebar, scroll-to-message, profiles, and review fixes
- Add cert mismatch modal for TOFU certificate pinning
- Separate voice channels from text in sidebar with user lists
- Implement scrollToMessage and jump-to-pinned-message in overlay
- Add server profiles with credential auto-fill on connect page
- Fix credential auto-fill race condition on rapid profile clicks
- Add channel_focus event for channel-scoped message delivery
- Fix member list case-insensitive role filtering
- Server normalizes role names to lowercase for protocol consistency
- Remove redundant permission-denied log in handleChannelFocus
- Voice store: bulk set states from ready payload, leave cleanup
- WebSocket reconnect and structured logging improvements
- Add tests for cert modal, overlay managers, voice sidebar,
  message list scroll, quick switcher, and profile management
2026-03-17 20:25:15 +01:00
jevb aa2410e9ea fix: voice channel join/leave visibility and disconnect bugs
- Fix VoiceWidget disconnect not sending voice_leave to server
- Add voice cleanup on logout (send voice_leave before ws.disconnect)
- Add beforeunload handler for best-effort voice_leave on app close
- Broadcast voice_state/voice_leave to ALL clients (not just channel
  members) so every sidebar updates when users join/leave voice
- Fix CleanupVoiceForChannel using BroadcastToChannel instead of
  BroadcastToAll
- Remove user list from VoiceWidget (users only shown in sidebar)
- Guard VoiceWidget disconnect against double-click
- Add 6 tests for voice disconnect behavior
2026-03-17 20:03:34 +01:00
J3vb 28bd30a495 Merge pull request #15 from J3vb/tauri-migration
feat: TOFU cert pinning, settings cache refactor, ban enforcement & 80%+ coverage
2026-03-17 15:05:13 +01:00
claude[bot]andJ3vb 404764ce97 fix: resolve CI failures — errcheck lint and TS noUncheckedIndexedAccess errors
- ws_integration_test.go:42: wrap resp.Body.Close() to handle errcheck
- dispatcher.ts:183: add non-null assertion on sorted[0] array access
- keybinds-tab.test.ts: add non-null assertions on NodeList index accesses
- logs-tab.test.ts: add non-null assertions on querySelectorAll index accesses

Co-authored-by: J3vb <J3vb@users.noreply.github.com>
2026-03-17 14:01:26 +00:00
jevb 45b720811e fix: address PR #15 review issues (#16-#23)
- #16: Fix golangci-lint issues (unchecked Close(), unused funcs, naming)
- #17: Add KeybindsTab and LogsTab unit tests (19 tests, 81%+ coverage)
- #18: Add rate limiting to chat_edit and chat_delete handlers
- #19: Fix cert mismatch handling via event listener instead of string match
- #20: Validate SHA-256 colon-hex fingerprint format in Rust ws_proxy
- #21: Optimize session+ban check with single JOIN query
- #22: Sort channels by position when redirecting after deletion
- #23: Rename admin test files for clarity

Also fixes ban expiry regression (H-1 from code review) by using
auth.IsEffectivelyBanned() to properly respect temporary ban expiry.
2026-03-17 14:54:50 +01:00
jevb 4d1a1676c7 feat: TOFU cert pinning, settings cache refactor, ban enforcement, and 80%+ test coverage
- Implement TOFU certificate pinning in Rust WS proxy with accept_cert_fingerprint command
- Refactor settings cache from package-level globals to Hub methods (eliminates global state)
- Add runtime ban check on WS message handling (kicks banned users mid-session)
- Sanitize reaction error messages to prevent IDOR information leaks
- Add slog error logging to REST handlers (channel, invite, search)
- Handle channel_delete for active channel in client dispatcher
- Add certMismatchBlock to prevent auto-reconnect on TOFU mismatch
- Consolidate root-level spec docs into docs/brain/06-Specs/ vault
- Add 80%+ test coverage for ws (80.9%) and admin (81.7%) packages
- Delete completed TODOS.md (all items resolved)
2026-03-17 11:05:52 +01:00
J3vb 88eafbc4f7 Merge pull request #2 from J3vb/tauri-migration
feat: server enhancements, client test selectors, and UI polish
2026-03-17 08:28:27 +01:00
jevb ce4326766a fix: resolve all golangci-lint issues blocking CI server build
Fix 70+ errcheck violations by adding explicit error discards (`_ =`)
for unchecked return values across test helpers and deferred Close()
calls. Remove unused `senderID` field from broadcastMsg and unused
`defaultCleanupMaxWindow` const. Apply De Morgan's law, remove empty
branch, and simplify redundant type declaration per staticcheck.
2026-03-17 08:09:52 +01:00
jevb 9c1d99683c fix: address PR review findings (issues #9-#14)
- Fix capacity over-allocation and use strings.Builder in getReactionsBatch (#9)
- Replace `any` types and cache Tauri invoke in window-state.ts (#10)
- Remove custom `contains` helper, fix NilHub tests to pass nil (#11)
- Add nil guards before hub method calls in admin handlers (#12)
- Run golangci-lint v2: modernize interface{}/any, range-over-int loops,
  remove dead code, fix errcheck, add .golangci.yml config (#13)
- Add 23 client unit test suites (694 tests), exclude Tauri-coupled
  files from coverage, achieve 80%+ threshold (#14)

Closes #9, closes #10, closes #11, closes #12, closes #13, closes #14
2026-03-17 04:11:04 +01:00
jevb 1b596367c4 fix: address PR review findings (issues #3-#8)
- Fix double-close panic in Hub.Stop/GracefulStop using sync.Once (#3)
- Bump golangci-lint action to v9 with v2.11.3 for Go 1.25 support (#4)
- Add input validation guards to SearchMessages (#5)
- Handle promise rejections in InviteManager with error toasts (#6)
- Add missing reply_to and edited_at columns to admin test schema (#7)
- Add ClientCount to HubBroadcaster interface and wire into stats endpoint (#8)
2026-03-17 03:20:37 +01:00
jevb 8f4349ba42 feat: server enhancements, client test selectors, and UI polish
Server:
- Add message search and pinned messages support
- Add admin hub integration and live connection stats
- Update admin test mocks for hub interface

Client:
- Add data-testid attributes to components for E2E testing
- Add window management capabilities (position, size, maximize)
- Add prod E2E test config and script
- Fix CSS imports (use vite bundling instead of HTML link tags)
- Add inline styles to InviteManager overlay for reliability
- Update CHATSERVER.md references from WPF to Tauri

Docs:
- Update quick-start guide
2026-03-17 02:56:19 +01:00
jevb 8e33be3c1d chore: clean up remaining WPF artifacts and track missing files
- Remove Client/.gitignore (WPF-specific, no longer needed)
- Add playwright-report/, test-results/, coverage/ to client .gitignore
- Track CLIENT-REVIEW.md, playwright.config.prod.ts, and design specs
- Delete empty WPF directories and debug screenshots
2026-03-17 02:52:49 +01:00
jevb 5903d4e39c chore: remove legacy WPF client code and references
The WPF/.NET 8 client has been fully replaced by the Tauri v2
client. Remove all WPF source, tests, solution file, and build
output directories. Update CLAUDE.md, CONTRIBUTING.md, and
SETUP.md to remove WPF references and simplify branch strategy.

Removed:
- Client/OwnCord.Client/ (WPF source)
- Client/OwnCord.Client.Tests/ (WPF tests)
- Client/OwnCord.Client.sln
- Client/publish*/ (build outputs)
2026-03-17 02:49:45 +01:00