Commit Graph
849 Commits
Author SHA1 Message Date
jevb 76886ba72b feat: add virtual scrolling to MessageList for large channels
Implement DOM windowing so only visible messages (plus 10-item overscan
buffer) are rendered. Uses estimated heights with measured-height cache,
top/bottom spacer elements, and rAF-debounced scroll updates.

- Extract rendering helpers to components/message-list/renderers.ts
- MessageList uses VirtualItem abstraction for messages + day dividers
- Height cache keyed by message ID for accurate scroll positioning
- Update test assertion for new virtual scroll DOM structure

Resolves TODOS.md #11.
2026-03-17 02:25:49 +01:00
jevb 85acdba710 docs: mark TODOS #9 (split oversized files) as complete 2026-03-17 02:21:41 +01:00
jevb 1641824e65 refactor: split MainPage.ts into ChatHeader and OverlayManagers modules
Extract chat header builder and overlay lifecycle managers (quick
switcher, invite manager, pinned panel) from MainPage.ts (703→508 lines)
into pages/main-page/ subdirectory. Completes TODOS.md #9 (all 3 files).
2026-03-17 02:21:03 +01:00
jevb 79ea3ab42b refactor: split oversized files + add store notification batching
- Split Server/admin/api.go (788→281 lines) into handlers_users.go,
  handlers_channels.go, handlers_settings.go, handlers_backup.go
- Split Client SettingsOverlay.ts (~685→173 lines) into 7 per-tab
  modules under components/settings/
- Add queueMicrotask-based notification batching to createStore with
  flush() for synchronous test assertions
- Update 8 test files with flush() calls for batched store updates

Addresses TODOS.md #9 (split oversized files) for 2 of 3 targets.
2026-03-17 02:17:26 +01:00
J3vb 41cfdc3f59 Merge pull request #1 from J3vb/add-claude-github-actions-1773709783705
Add Claude Code GitHub Workflow
2026-03-17 02:11:04 +01:00
J3vb 70b59621f2 "Claude Code Review workflow" 2026-03-17 02:09:46 +01:00
J3vb ceb788db4b "Claude PR Assistant workflow" 2026-03-17 02:09:45 +01:00
jevb 4bdc83a368 fix: resolve 15 post-review issues across server and client
Server fixes:
- Move ATTACH_FILES permission check before CreateMessage to prevent
  orphaned messages on permission denial
- Fix hardcoded /api/files/ URL to /api/v1/files/ per spec
- Add error logging for GetAttachmentsByMessageIDs failure
- Set 1MB WebSocket read limit to match client-side limit
- Extract requireChannelPerm helper, replacing 8 repeated patterns

Client fixes:
- Wire onUnauthorized callback to clear auth on 401 responses
- Store auth token in authStore before WS connect
- Reset WS state to disconnected when Tauri APIs unavailable
- Add connectivity guard and 200ms send debounce on message send
- Add toast container to MainPage with error feedback on 5 API failures
- Clear voice currentChannelId on server-driven voice_leave for current user
- Apply stored theme/font/compact preferences at app startup
- Fix infinite scroll throttle to use store subscription instead of fixed timer

Tests:
- Add TestChatSend_AttachmentsDeniedNoMessageCreated
- Add attachments table to handler test schema
2026-03-17 01:59:34 +01:00
jevb 95c5b2d3b9 test: add authorization and contract tests for channel access
- REST authorization: 6 tests verifying READ_MESSAGES enforcement
  on GET /channels, GET /channels/{id}/messages, and GET /search
  with channel override deny and admin bypass
- WS authorization: 4 tests verifying channel_focus and chat_send
  permission checks with deny overrides and admin bypass
- Contract tests: 3 tests asserting response shapes match API.md
  (message fields, user object, attachments, reactions with me flag,
  search result fields)

Closes test gaps identified in CODE_REVIEW.md.
2026-03-16 17:17:00 +01:00
jevb 75b239ecd0 docs: align API.md paths to /api/v1/, fix CLAUDE.md contradiction, mark review resolved
All endpoints in API.md now use /api/v1/ prefix matching
the server router and client. CLAUDE.md no longer
contradicts itself about the base path. CODE_REVIEW.md
updated with ALL RESOLVED status. Also adds Obsidian-Brain
to .gitignore.
2026-03-16 17:11:17 +01:00
jevb 53d78feef6 feat: add attachment persistence and link on chat_send (High #3)
- Add attachment_queries.go with GetAttachmentByID, LinkAttachmentsToMessage,
  and GetAttachmentsByMessageIDs
- Wire attachment linking in handleChatSend with ATTACH_FILES permission check
- Include linked attachments in chat_message WS broadcast payload
- Wire attachment batch-fetch into GetMessagesForAPI for REST responses
- Add attachments table to channel handler test schema
2026-03-16 17:00:09 +01:00
jevb b2bfe5593c feat: align REST responses with API.md spec (High #1)
- Add MessageAPIResponse, UserPublic, AttachmentInfo, ReactionInfo types
- Add GetMessagesForAPI query with user object, reactions (with me flag),
  and attachments array matching API.md shape
- Update SearchMessages to return user object {id, username, avatar}
  instead of flat username field
- Update GET /messages handler to use new API-shaped query
- Batch-fetch reactions for all messages in a single query for performance
2026-03-16 16:57:01 +01:00
jevb 54221e8c07 fix: resolve 4 Critical + 2 High + 1 Medium server protocol violations
- Critical #1: Add READ_MESSAGES permission checks to channel_focus,
  GET /channels, GET /messages, and GET /search
- Critical #2: Send type "auth_error" instead of "error" with AUTH_ERROR
  code, preventing infinite client reconnect loops
- Critical #3: Replace role_id (number) with role (string name) in
  member_join, auth_ok, and ready payloads via JOIN on roles table
- Critical #4: Always include attachments field (empty array) in
  chat_message broadcasts to prevent client crash
- High #2: Add /api/v1/health endpoint alongside /health
- Medium #1: Handle ping WS messages with pong response
2026-03-16 16:54:56 +01:00
jevb 01387dc033 feat: fix all E2E failures, add credentials/window-state, wire QuickSwitcher + SettingsOverlay
- Fix 80 E2E test failures across 6 root causes (channel auto-select,
  settings overlay wiring, QuickSwitcher Ctrl+K, voice widget visibility,
  member list rendering, status dot positioning)
- Add Tauri credential storage (Rust + TS bridge) and window-state persistence
- Add ConnectedOverlay component and settings-overlay/window-state unit tests
- Expand profiles and rate-limiter with comprehensive test coverage
- Add CODE_REVIEW.md documenting 4 Critical + 3 High server-side issues
- Add Playwright E2E suite (135 tests across 14 spec files)
- All 586 tests passing (451 unit/integration + 135 E2E)
2026-03-16 16:43:46 +01:00
jevb 3d022b68e4 test: add test helpers and integration tests for dispatcher + stores
- Create mock-ws helper with simulateMessage/simulateStateChange
- Create fixture factories for messages, members, channels, reactions
- Create resetAllStores utility for clean test isolation
- Add 16 integration tests covering:
  - Ready payload hydration (channels, members, voice)
  - Chat message flow with unread tracking
  - Message edit and delete
  - Reaction add/remove via reaction_update
  - Chat send confirmation via chat_send_ok
  - Typing indicator updates
  - Member ban handling
  - Voice config and speakers state

385 tests passing across 22 test files.
2026-03-15 20:46:38 +01:00
jevb e07a1abede feat: align UI to mockup, wire WS handlers, fix 5 HIGH review issues
- Fix CSS classes across 8 components to match ui-mockup.html
  (ReactionBar, VoiceChannel, EmojiPicker, DmSidebar, Toast,
  ServerBanner, MessageActionsBar, MessageList)
- Rewrite MainPage to compose standalone components instead of
  inline builders, with reactive channel switching
- Wire all outbound WS handlers: chat send/edit/delete, typing,
  reactions, voice mute/deafen/disconnect
- Wire REST message loading with infinite scroll and abort on
  channel switch
- Wire reconnect banner to WS state and server_restart events
- Add reaction_update, chat_send_ok, member_ban, voice_config,
  voice_speakers dispatcher handlers
- Add updateReaction action in messages store
- Fix MessageList double-render bug when no code blocks present
- Fix membersStore subscription to skip re-render on typing events
- Add scroll-top debounce to prevent duplicate API calls
- Replace dead More button with functional Delete button
- Clear unread count on channel switch in channels store
- Add midnight theme, connectionStatus, error fields to UI store
- Add voiceConfigs state and setSpeakers action to voice store
- Update tests: 369 passing across 21 test files
2026-03-15 20:43:13 +01:00
jevb 77626e136b feat: add Tauri v2 desktop client with full chat UI and security hardening
Complete Tauri v2 client implementation migrated from WPF/.NET 8:
- Rust backend: WS proxy with TLS cert bypass for self-signed servers,
  settings storage, system tray, global hotkeys
- TypeScript frontend: login/register, chat messaging, channel sidebar,
  member list, voice channel UI, settings overlay with log viewer,
  server profiles, quick switcher, emoji picker, file uploads
- 21 test suites (364 tests) covering stores, services, and components
- Security: bounded WS channel, wss:// URL validation, TLS signature
  verification, profile import validation, token redaction, HTTPS-only
  HTTP scope

Also updates CLAUDE.md to correct API path rule (/api/v1/) and adds
Tauri client CI workflow.
2026-03-15 19:44:02 +01:00
jevb b7d63dd443 chore: update .gitignore to exclude local tooling, build artifacts, and internal docs
Remove Claude Code configs, skills, publish artifacts, HTML mockups,
and internal planning docs from git tracking. Files remain local.
2026-03-15 16:54:55 +01:00
jevb 049b58c183 fix: prevent stale "online" status for users not connected via WebSocket
- Remove premature UpdateUserStatus("online") from REST login handler;
  the WebSocket serve.go already sets "online" on actual WS connect
- Add ResetAllUserStatuses() called at server startup to clear stale
  statuses from previous runs or crashes (alongside ClearAllVoiceStates)
2026-03-15 12:21:10 +01:00
jevb 6f564c7d2f fix: add JSON tags to Role/VoiceState, fix WebSocket error surfacing
Root cause: server's db.Role and db.VoiceState structs had no JSON tags,
causing Go to serialize field names as PascalCase while the C# client
expected snake_case. Every role deserialized with Id=0, crashing
ToDictionary with "duplicate key: 0".

- Add json tags to Role and VoiceState in Server/db/models.go
- Change Disconnected event to carry reason string for diagnostics
- Wire ErrorReceived in MainViewModel to show server-side WS errors
- Fix MainWindow to surface WebSocket errors on MainPage (not ConnectPage)
- Use _reconnectCts.Token for receive loop instead of caller's token
- Make ToDictionary calls safe with TryAdd to prevent future crashes
2026-03-15 12:18:19 +01:00
jevb b4535aeea0 perf: fix O(n) allocations, freeze brushes, improve disposal and nullability
- Replace 5x ToList().FindIndex() with direct for-loops in MainViewModel
- UpdateUnreadCount now updates ChannelGroup in-place instead of full rebuild
- Remove redundant RebuildChannelGroups() call in OnReady
- Freeze all SolidColorBrush instances in converters for thread safety
- EmojiPicker search shows empty state instead of fallback to all categories
- MainViewModel implements IDisposable for _typingTimer cleanup
- ApiMessage.Username changed to string? to match server reality
2026-03-15 12:00:28 +01:00
jevb 7a374e0c79 fix: resolve critical TLS race, invisible messages, and 5 other review issues
- CRITICAL: Remove TofuHostContext AsyncLocal race — extract host from
  HttpRequestMessage.RequestUri in TLS callback instead
- HIGH: OnChatMessage now calls AddMessage() so live messages appear
- HIGH: LoadMessagesForChannelAsync reports errors instead of swallowing
- HIGH: IsSystemMessage no longer false-positives on "[" prefix
- HIGH: VoiceStateInfo.ChannelId now fires PropertyChanged
- HIGH: Profile import rejects files over 1 MB
- Deleted TofuHostContext.cs (no longer needed)
2026-03-15 11:53:52 +01:00
jevb c1c25ed26c feat: implement full client UI from mockup — 10 phases, 331 tests
Client UI:
- Design system: Colors, Typography, Controls resource dictionaries
- Message actions: reply compose bar, hover edit/delete/reply buttons
- Rich content: code blocks, attachments, system messages, content parser
- Server strip: 72px sidebar with server icons, home button, add server
- Status picker: popup for changing online/idle/dnd/invisible status
- ConnectPage: server health check dots with auto-refresh
- User popup: profile card with banner, avatar, roles, member since
- Emoji picker: 6 categories, search, grid of Unicode emojis
- Settings overlay: full-screen with sidebar navigation
- Friends/DM view: sidebar + friends list with tabs (online/all/pending)
- Toast notifications: auto-dismiss after 3s with fade animation

Models & services:
- Attachment model added to Message, ApiMessage, ChatMessagePayload
- EditMessageAsync, DeleteMessageAsync, SendStatusChangeAsync APIs
- MessageContentParser (code blocks, inline code, bold, italic)
- EmojiData, ToastService, HealthStatusToBrushConverter

Server (from prior session):
- Voice room management, SFU, speaker detection
- ACME/TLS support, config improvements
- Protocol and schema updates

Tests: 331 passing (61 converter + 24 voice service + 34 voice VM +
41 parser + 9 edit/delete + existing)
2026-03-15 11:42:25 +01:00
jevb 7ee190fc3f chore: gitignore Claude Code local config and research notes 2026-03-15 07:09:01 +01:00
jevb 6eba999233 feat: add Let's Encrypt ACME support, fix security issues, improve server UX
Server:
- Add Let's Encrypt (ACME) TLS mode with autocert, HTTP-01 challenges on :80,
  and automatic certificate renewal (tls.mode: "acme" in config.yaml)
- Add ASCII art startup banner with server info and endpoint URLs
- Fix CSP blocking admin panel inline styles/scripts (per-route override)
- Suppress TLS handshake error noise in console output
- Fix TOCTOU race in invite consumption (atomic UPDATE with row-count check)
- Fix sendMsg mutex race condition (hold lock for entire send)
- Fix permission override formula (deny-first, allow-wins)
- Fix voice join parsing channelID before permission check
- Add session expiry check at WebSocket auth and periodic revalidation
- Add message length limit (4000 chars) and emoji length validation (32 bytes)
- Add file size enforcement in storage after io.Copy
- Add checksum URL validation in updater
- Add backup path traversal protection (BackupToSafe)
- Add self-modification guard in admin handlePatchUser
- Fix admin ownerOnlyMiddleware to use context user instead of re-auth
- Remove redundant startup log lines (banner shows same info)
- Add periodic expired session cleanup (15-min ticker)
- Add permissions package with bitfield constants and EffectivePerms
- Add rate limiter cleanup goroutine to prevent unbounded growth
- Add auth helpers (IsEffectivelyBanned, IsSessionExpired)
- Add WebSocket origin validation

Client:
- Add TOFU certificate trust service
- Add receive loop error handling
- Fix redundant else-if in OnChatMessage
2026-03-15 07:07:59 +01:00
jevb 98decace45 chore: gitignore client publish output directories 2026-03-15 00:33:07 +01:00
jevb e33ec32afb fix: include SavePassword/LoadPassword/DeletePassword in ICredentialService interface 2026-03-15 00:31:56 +01:00
jevb 25449eb204 feat: redesign login UI, add save-password, fix permissions, add audit logging, member_join broadcast
- Redesign ConnectPage with modern dark theme, profile cards with delete buttons, login/register toggle
- Add DPAPI-encrypted password saving with "Remember my password" checkbox
- Fix permission bit constants to match SCHEMA.md (Member role 0x663)
- Add migration 004 to fix existing Member role permissions
- Add comprehensive audit logging across all server packages (auth, admin, ws, setup)
- Add member_join WebSocket broadcast so new users appear in members list in real-time
- Add host URL normalization (strip scheme prefix) for reverse proxy compatibility
- Add REST API client, ChatService orchestrator, WebSocket service with reconnection
- Add model types (WsEnvelope payloads, API responses), converters, tests
2026-03-15 00:31:39 +01:00
jevb b53098acec chore: gitignore server runtime artifacts (binary, config, data) 2026-03-14 22:38:08 +01:00
jevb d425dc5553 feat: add setup wizard for initial owner account creation
When no users exist, the admin panel shows a setup wizard instead of the
login form. Creates the first Owner account with a session token and
generates an unlimited invite code for onboarding other users. The setup
endpoint is locked out after the first user is created.

Also fixes the admin panel 404 by serving index.html directly for the
root path instead of delegating to http.FileServer.
2026-03-14 22:36:35 +01:00
jevb 80ceabc78b fix: set default TLS cert/key paths to data/cert.pem and data/key.pem 2026-03-14 22:17:47 +01:00
jevb da19fda9e1 chore: add .claude/settings.local.json to gitignore 2026-03-14 22:11:42 +01:00
jevb f28a7b8342 docs: add Phase 7 distribution and updates design spec 2026-03-14 22:09:11 +01:00
jevb 69b76ada12 feat: add update notification banner to admin dashboard 2026-03-14 22:06:54 +01:00
jevb 73a621ef0f feat: implement server auto-update API endpoints with download, verify, and restart 2026-03-14 22:05:13 +01:00
jevb bae586907f feat: implement client auto-update with GitHub Release checking and update dialog 2026-03-14 22:04:24 +01:00
jevb 82a9985a6a docs: add server_restart message type and update endpoints to specs 2026-03-14 22:03:12 +01:00
jevb 27b7c000da feat: add updater package with GitHub Release checking and checksum verification 2026-03-14 21:59:58 +01:00
jevb 7398756515 docs: add README, SECURITY, CONTRIBUTING, and setup guides 2026-03-14 21:58:53 +01:00
jevb 8ab2c93f1e feat: add server_restart WebSocket message type for update notifications 2026-03-14 21:58:18 +01:00
jevb aa2a1cf025 ci: add GitHub Actions CI and release workflows
CI runs build+test+lint for both server and client on push/PR.
Release workflow builds binaries, generates SHA256 checksums,
and creates a GitHub Release with auto-generated notes on tag push.
2026-03-14 21:58:06 +01:00
jevb 5aa216d991 fix: correct embed path (static not admin/static) and simplify audit_log migration 2026-03-14 21:37:47 +01:00
jevb ab389764b5 feat: implement Phase 5 (voice/WebRTC signaling) and Phase 6 (admin panel)
Phase 5 — Voice:
- migrations/002_voice_states.sql: voice_states table with FK + index
- db/voice_queries: JoinVoiceChannel, LeaveVoiceChannel, GetVoiceState,
  GetChannelVoiceStates, UpdateVoiceMute, UpdateVoiceDeafen, ClearVoiceState
- ws/voice_handlers: handleVoiceJoin (perm check, DB, broadcast existing
  states), handleVoiceLeave, handleVoiceMute, handleVoiceDeafen,
  handleVoiceSignal (rate-limited relay, SDP never logged),
  handleSoundboard (rate-limited, USE_SOUNDBOARD perm check)
- ws/handlers: dispatch voice_join/leave/mute/deafen/offer/answer/ice/soundboard
- ws/serve: call handleVoiceLeave on disconnect; include voice states in ready payload
- ws/messages: buildVoiceState, buildVoiceLeave, buildVoiceSignalRelay
- api/voice_handler: GET /api/v1/voice/credentials — HMAC-SHA1 TURN creds
- config: VoiceConfig (TURNSecret, STUNPort, TURNPort, TURNEnabled)

Phase 6 — Admin Panel:
- migrations/003_audit_log.sql: audit_log table with indexes
- db/admin_queries: GetServerStats, ListAllUsers, UpdateUserRole,
  ForceLogoutUser, AdminCreate/Update/DeleteChannel, LogAudit,
  GetAuditLog, GetSetting, SetSetting, GetAllSettings, BackupTo
- admin/api: full REST API — stats, users, channels, audit log, settings,
  backup; adminAuthMiddleware (ADMINISTRATOR bit), ownerOnlyMiddleware
- admin/static/index.html: single-page admin panel (dark theme, vanilla JS,
  no CDN) — dashboard, users, channels, audit log, settings sections
- admin/admin.go: NewHandler wiring go:embed static files + API

Fixes: Channel struct json tags (was serializing as "ID" not "id"),
duplicate getWithToken helper renamed in voice_handler_test.go

Test coverage: admin 59.1%, api 78.2%, auth 90.9%, db 82.0%, ws 37.9%
2026-03-14 21:31:03 +01:00
jevb 36640e3051 feat: implement Phase 4 real-time chat (WebSocket hub + message REST)
- db: channel_queries (ListChannels, GetChannel, CRUD, permissions),
  message_queries (CreateMessage, GetMessage, GetMessages paginated,
  EditMessage, DeleteMessage soft, AddReaction, RemoveReaction,
  GetReactions, SearchMessages FTS5, UpdateReadState)
- db: fix in-memory DB isolation — SetMaxOpenConns(1) for :memory: path
- ws/hub: replace stub with full Hub (register/unregister, broadcast to
  channel/all, send to user, thread-safe, buffered broadcast channel)
- ws/client: Client with send channel, NewTestClient helpers for tests
- ws/handlers: dispatch chat_send/edit/delete, reaction_add/remove,
  typing_start, presence_update — all with rate limiting and permission checks
- ws/messages: JSON builder helpers for all server→client message types
- ws/serve: ServeWS HTTP handler, WS auth handshake (10s timeout),
  ready payload, writePump/readPump goroutines, graceful disconnect
- api: channel_handler — GET /channels, GET /channels/{id}/messages,
  GET /search; fixed double-mount of /api/v1 route group
- api/router: mount channel routes, start hub, register /api/v1/ws

Test coverage: api 77.6%, auth 90.9%, db 84.2%, ws 26.7% (serve.go
requires live WS connection; hub/handlers/messages fully covered)
2026-03-14 21:17:09 +01:00
jevb 814653ea08 chore: add Client .gitignore, remove tracked build artifacts 2026-03-14 21:07:25 +01:00
jevb 9707c4d4af feat: scaffold Phase 3 WPF client shell with MVVM and TDD structure
- WPF (.NET 8) project targeting net8.0-windows
- Models: ServerProfile (record), Channel, Message, User, Role
- ViewModels: ViewModelBase (INotifyPropertyChanged), RelayCommand<T>,
  ConnectViewModel (profiles, login/register toggle, connect command),
  MainViewModel (channels, messages, typing indicator, send command),
  SettingsViewModel (dark theme, notifications, PTT key)
- Services: IProfileService + ProfileService (AppData JSON, immutable ops),
  ICredentialService + CredentialService (DPAPI via ProtectedData),
  IWebSocketService + WebSocketService (ClientWebSocket stub)
- Views: ConnectPage (server address, login/register, profile selector),
  MainPage (3-column: channel list, message area, member list),
  App.xaml wires converters and startup
- Converters: BoolToVisibilityConverter, IntToVisibilityConverter
- Tests: ConnectViewModelTests (11 cases), MainViewModelTests (11 cases),
  ProfileServiceTests (6 cases) — ready to run once NuGet accessible
  (run: dotnet restore && dotnet test OwnCord.Client.Tests/)

Build: dotnet build OwnCord.Client/ succeeds with 0 warnings
2026-03-14 21:07:07 +01:00
jevb b7dd6eabe9 feat: implement Phase 2 auth & security with TDD
- auth/session: 256-bit crypto-random tokens, SHA-256 hashing for storage
- auth/password: bcrypt cost 12, strength validation (8-72 chars)
- auth/ratelimit: sliding-window RateLimiter with lockout, thread-safe
- db/models: User, Session, Invite, Role types
- db/auth_queries: full user/session/invite CRUD with in-memory test coverage
- api/middleware: AuthMiddleware (Bearer token), RequirePermission (bitfield),
  RateLimitMiddleware (X-Real-IP, Retry-After header)
- api/auth_handler: POST register/login, POST logout, GET me
  - Generic errors — username existence never revealed
  - Rate limits: 3/min register, 5/min login, lockout after 10 failures
- api/invite_handler: create/list/revoke behind MANAGE_INVITES permission
- bluemonday sanitization on all user-supplied string fields

Test coverage: auth 90.9%, db 84.4%, api 80.9%
2026-03-14 20:52:11 +01:00
jevb a1434ad07f feat: implement Phase 1 server skeleton with TDD
- Scaffold Go module (github.com/owncord/server) with all package dirs
- config: koanf-based YAML loader with env var overrides, default generation
- db: pure-Go SQLite (modernc, no CGO), WAL mode, FK enforcement, full
  15-table schema from SCHEMA.md including FTS5 and idempotent migrations
- auth/tls: ECDSA P-256 self-signed cert generation, LoadOrGenerate for
  all 4 TLS modes (self_signed, acme, manual, off)
- api: chi router with request ID middleware, /health and /api/v1/info
- main: graceful shutdown (30s timeout), structured slog JSON logging
- Stubs for ws, storage, admin packages ready for Phase 2+

Test coverage: api 100%, auth 85.7%, db 82.4%, config 80.6%
Binary: chatserver.exe 12MB, GOOS=windows GOARCH=amd64
2026-03-14 20:34:37 +01:00
jevb bcf563f36c chore: initial commit with project specs and configuration
Add all specification files (CHATSERVER, PROTOCOL, SCHEMA, API, SETUP),
Claude Code config, and skill definitions for the OwnCord chat platform.
2026-03-14 19:57:39 +01:00