- Replace static badge block with CI, release, status, Go, Tauri,
platforms, and license badges (release badge tracks the public
OwnCord-releases repo)
- Update platform support table for v1.1.0-alpha.2 assets (Linux x64
server, Linux x64/ARM64 client)
- Stamp build examples with the current version
- Point contributing docs at main now that dev is pruned
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- gitignore .serena/ and Client/tauri-client/.env; untrack the .env
(the KLIPY key it held is treated as burned; rotation + server-side
proxy tracked for P3)
- CI: verify generated sqlc output (make sqlc-verify) on the ubuntu leg
- CHANGELOG: honest reset narrative (v1.1.0-alpha series), remove
references to deleted roadmap files
- delete stale docs/phase-a-status.md; fix dangling ref in
docs/plans/slash-commands.md
- add root SECURITY.md (GitHub-surfaced policy; reporting works while
the source repo is private)
- docs/audit-2026-04-07.md: add maintained finding-closure table
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Publish every release to the public OwnCord-releases repo with a full
source snapshot (AGPL section 6 for binary recipients), and make the
updater's repo coordinates configurable (github.owner/github.repo),
defaulting to OwnCord-releases. Both the server self-update and the
/client-update chain follow the new default, so deployed servers keep
updating after the source repo goes private.
The publish step fails closed: a private source repo with no
RELEASES_REPO_TOKEN aborts the release instead of silently shipping
binaries with no public source or update feed.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds docs/plans/security-hardening-remediation.md capturing the code-review
findings against fix/security-hardening-review and sequencing the fixes into
three waves (availability/backend-breaking, behavioral regressions, cleanup).
Each item names root cause, right-altitude fix, files, and verification.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
First of two phase-D parity plans. Grounded in the existing V2 command
dispatcher (Server/ws/command.go) and the dormant
plugin.Registry.DispatchCommand + host_commands.go — this is not a
green-field design, it's a wiring plan for code that already exists.
Covers:
- Wire format: command_invoke, command_autocomplete, command_reply,
command_autocomplete_result
- Manifest extension: commands[] with option types, default_member_permissions,
contexts, autocomplete flag
- Schema: migrations/016_plugin_commands.sql with a unique name index
so two plugins can't both own /ban
- Code surface: enumerated file-by-file touch list
- Permission model: server-enforces default_member_permissions BEFORE
the plugin is invoked, plugins never get to gate their own commands
- Built-in commands: /me + /shrug ship in-tree as reference handlers
- Concurrency: 3s deadline via context.WithTimeout passed to DispatchCommand
- Failure modes & UX: 6-row table from "unknown command" through panic
auto-disable
- Testing: unit + integration + contract round trip
- Telemetry: 3 new counters + OTel span
- 4-stage rollout, each step independently shippable
- Open questions: bot identity for broadcasts, component v2 reservation,
cross-plugin imports, DM-context handling
Plan #8 (E2EE DMs + DAVE voice) and PHASE_D_PARITY_TODO.md items 2-7
to follow in a subsequent commit.
https://claude.ai/code/session_01UsBsQW2YiA2usk9pnJjAWk
Resolves the modify/delete conflict with dev (which removed
phase-a-foundation.md in a1e8970). The Implementation Status and
Actionable TODOs sections are preserved under docs/ alongside the
other project docs, matching the existing docs/*.md convention.
The original phase-a-foundation.md design brief is gone per dev's
intent; only the post-implementation status and follow-up checklist
survive.
- 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
Soundboard was never implemented — remove USE_SOUNDBOARD permission bit,
rate limiter, protocol entry, admin mockup reference, TODOS entry, and
all related test assertions.
teardownForReconnect only cleaned up audio pipeline and token timer,
leaving manual camera/screenshare MediaStreamTracks capturing
indefinitely after unexpected disconnect. Added stopManualCameraTrack
and stopManualScreenTracks calls before room is nulled, plus store
flag resets so the UI reflects the actual state.
Add 7 new tasks for killing surviving Stryker mutants across
livekitSession, media-visibility, streamPreview, screenShare,
safe-render, roomEventHandlers, and livekitDiagnostics.
Mark Coraza WAF middleware (T-448) as completed.
CRITICAL (5):
- Hub panic recovery now calls h.Stop() after 3 panics (ws/hub.go)
- Ring buffer EventsSince returns non-nil empty slice for current seq (ws/ringbuffer.go)
- PTT event listener stores unsubscribe handle to prevent leak (ptt.ts)
- verifyTotp respects config.allowSelfSigned instead of hardcoding (api.ts)
- ptt_listen_for_key uses spawn_blocking to avoid thread pool starvation (ptt.rs)
HIGH - Server (13):
- TOTP rate-limit checked after body decode; counters reset on success
- TOTP enable returns 409 if already enabled (must disable first)
- Global search pre-computes accessible channel IDs for FTS WHERE clause
- DeleteAccount queries roles by name instead of hard-coded IDs
- BackupToSafe uses absClean in VACUUM INTO
- Voice camera slot uses atomic EnableCameraIfUnderLimit DB method
- readPump snapshots voiceChID before unregister for TOCTOU safety
- Voice join sets state after token send; rollback takes broadcast flag
- Updater download uses probe pattern instead of overflow write
- Webhook checks Authorization header before reading body
- Storage.Save adds fsync and fixes double-close
- Default WS origin denies cross-origin (was: accept all)
HIGH - Client (6):
- WS reconnect uses generation counter to discard stale events
- AudioPipeline uses generation counter against stale worklet callbacks
- Screenshare mute state preserved across reconnect (not full leave)
- handleVoiceToken uses iterative loop instead of unbounded recursion
- store.ts re-entrancy guard with pending update queue
- Notification AudioContext cleaned up on logout
Reviewed by 4 parallel agents across Server Core, Server Realtime,
Client & Tauri, and Security. 55 total findings; 24 CRITICAL+HIGH
fixed here, 31 MEDIUM+LOW tracked in vault backlog (T-265–T-295).
Fix multiple bugs across settings tabs (AppearanceTab theme restoration,
AdvancedTab testability, LogsTab refresh, VoiceAudioTab device listing),
harden embeds/media/attachments with cache validation, add logPersistence
rotation logic, and add 8 new test files with expanded test cases for
existing tests. Brings client test coverage from ~68% to ~72%.
- Add auto-login feature description (lightning bolt toggle, startup flow)
- Add server health with online_users and 15s periodic health checks
- Update sidebar layout: DMs above channels (3-item preview, bubble to
top, unread badge), collapsible member list with persisted state
- Add voice call duration timer to Key Features
- Note accent color is restored on startup (not just settings)
- Add DM authorization critical rule (IsDMParticipant checks)
- Document full 1-on-1 DM implementation with REST endpoints, WebSocket events
- Add unified sidebar architecture replacing 4-column Discord layout
- Document theme system (neon-glow default, custom theme support)
- Add quick-switch server overlay feature (door button)
- Update PROTOCOL.md with dm_create, dm_channel_open/close events
- Add ready payload dm_channels field for initial DM state
- Expand CLAUDE.md key features section with all new implementations
Changes reflect completed session work on sidebar redesign and DM system.
Two specs for the video/screenshare experience:
1. SCREENSHARE-AUDIO.md — system audio capture + per-tile mute
2. VIDEO-FOCUS-MODE.md — Discord-style opt-in viewing with focus layout
The refactored LiveKit session dropped track.attach() for remote audio,
so no <audio> element was created and remote participants were silent.
Also refactors noise suppression to use LiveKit TrackProcessor API,
adds input volume gain node bypass at 100%, and exposes __lkDebug()
on window for DevTools diagnostics.
- 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
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