scaffold: M0 skeleton + agent onboarding (build, architecture, progress)
Turn the design into a buildable, dependency-free M0 skeleton plus the
onboarding layer so a new agent can pick up instantly.
Build system:
- CMake + CMakePresets (dev = no deps; server-release = vcpkg) + vcpkg.json
- Skeleton builds with just a C++20 compiler; deps stay off until needed
- .gitattributes (LF), .gitignore, .clang-format
Core (libvoicecat):
- core/include/voicecat.h: full C ABI (the client/server contract), stubbed
- core/proto/voicecat.proto: control-plane wire format, matches docs/protocol.md
- src/{net,crypto,codec,protocol,session,audio,core}: subsystem stubs that
return VC_ERR_NOT_IMPLEMENTED, each pointing to its design doc
- server/ (voicecat-server) and tools/vccli/ link the core
- tests/: CTest smoke test asserting the C ABI contract (behavior, not just build)
- clients/{apple,windows}: M4 placeholders
Onboarding for agents:
- CLAUDE.md: hub — build/test commands, architecture at a glance, doc map, rules
- AGENTS.md: working method (behavior-driven; clean compile is the floor not the goal)
- PROGRESS.md: living tracker — M0 done, M1 task checklist, "where we left off"
Verified: cmake --preset dev && cmake --build --preset dev && ctest --preset dev → green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 21:09:09 +02:00
|
|
|
|
// VoiceCat control-plane wire format. SOURCE OF TRUTH for the protocol.
|
|
|
|
|
|
// Spec: docs/protocol.md. Each TCP/TLS frame is [u32 length][encoded Envelope].
|
|
|
|
|
|
// Media frames (voice) are NOT here — they use the fixed binary header in docs/voice.md §2.
|
|
|
|
|
|
//
|
|
|
|
|
|
// Extensibility rules (docs/protocol.md §8): never reuse/renumber tags; new oneof arms and
|
|
|
|
|
|
// fields are additive; gate new features behind capability strings in ClientHello/ServerHello.
|
|
|
|
|
|
syntax = "proto3";
|
|
|
|
|
|
package voicecat.v1;
|
|
|
|
|
|
|
|
|
|
|
|
// ── Envelope ──────────────────────────────────────────────────────────────────
|
|
|
|
|
|
message Envelope {
|
|
|
|
|
|
// Nonzero on a request; echoed in the matching response for correlation. 0 = unsolicited.
|
|
|
|
|
|
uint64 request_id = 1;
|
|
|
|
|
|
|
|
|
|
|
|
oneof body {
|
|
|
|
|
|
// Session / handshake (tags 10–19)
|
|
|
|
|
|
ClientHello client_hello = 10;
|
|
|
|
|
|
ServerHello server_hello = 11;
|
|
|
|
|
|
AuthRequest auth_request = 12;
|
|
|
|
|
|
AuthResult auth_result = 13;
|
|
|
|
|
|
Disconnect disconnect = 14;
|
|
|
|
|
|
Ping ping = 15;
|
|
|
|
|
|
Pong pong = 16;
|
|
|
|
|
|
|
|
|
|
|
|
// State sync (20–29)
|
|
|
|
|
|
ServerStateSnapshot server_state = 20;
|
|
|
|
|
|
ChannelEvent channel_event = 21;
|
|
|
|
|
|
UserEvent user_event = 22;
|
|
|
|
|
|
SubscribeRequest subscribe = 23;
|
|
|
|
|
|
|
|
|
|
|
|
// Channel operations (30–39)
|
|
|
|
|
|
JoinChannelRequest join_channel = 30;
|
|
|
|
|
|
JoinChannelResult join_channel_result = 31;
|
|
|
|
|
|
LeaveChannelRequest leave_channel = 32;
|
|
|
|
|
|
CreateChannelRequest create_channel = 33;
|
|
|
|
|
|
EditChannelRequest edit_channel = 34;
|
|
|
|
|
|
DeleteChannelRequest delete_channel = 35;
|
|
|
|
|
|
MoveUserRequest move_user = 36;
|
|
|
|
|
|
GenericResult generic_result = 37;
|
|
|
|
|
|
|
|
|
|
|
|
// Voice signaling — media is on UDP (40–49)
|
|
|
|
|
|
StreamAnnounce stream_announce = 40;
|
|
|
|
|
|
StreamAnnounceResult stream_announce_result = 41;
|
|
|
|
|
|
StreamStop stream_stop = 42;
|
|
|
|
|
|
StreamStateUpdate stream_state = 43;
|
|
|
|
|
|
UdpBinding udp_binding = 44;
|
feat: fix voice join/leave, channel edit defaults, channel-update stream restart
Three bugs fixed across the full stack (proto/server/core/ABI/Win/macOS/iOS):
1. Join/Leave Voice now truly subscribes/unsubscribes from the voice plane.
Previously the button only toggled the local mic — receiving was always on
(gated by channel membership alone). Added a protocol-level voice subscription
concept: new SubscribeVoiceRequest/UnsubscribeVoiceRequest/VoiceSubscriptionResult
proto messages, User.voice_subscribed field, vc_join_voice/vc_leave_voice C ABI
functions, VC_EVENT_VOICE_STATE event, server-side voice_subscribed flag checked
by the SFU relay recipient filter, and core-client gating of remote-stream
decoder setup. All three clients rewired to subscribe+mic on Join / unsubscribe
on Leave. Text chat works regardless of voice subscription.
2. Channel edit dialog now shows the channel's actual current settings. The read
struct vc_channel was missing sort_order and audio fields — only the write
struct vc_channel_info had them. Extended vc_channel with both (additive, no
ABI break), updated the session model and list_channels marshaling to populate
them, and updated all three clients' edit callers to use actual channel info
instead of hardcoded defaults.
3. Channel parameter updates now automatically restart everyone's streams.
Previously editing a channel's audio config persisted and broadcast a
ChannelEvent::UPDATED, but no layer restarted streams — encoders/decoders are
frozen at announce time. handle_channel_event now detects audio-config changes
on the user's current channel and stop->starts each active local stream. The
server reads the updated config on re-announce; peers wire up fresh decoders
at the new ssrc.
All 29 CTest tests pass; Windows DLL + C# client build clean. Apple clients not
yet compile-verified (Windows environment).
2026-06-24 14:29:39 +02:00
|
|
|
|
SubscribeVoiceRequest subscribe_voice = 45;
|
|
|
|
|
|
UnsubscribeVoiceRequest unsubscribe_voice = 46;
|
|
|
|
|
|
VoiceSubscriptionResult voice_subscription_result = 47;
|
scaffold: M0 skeleton + agent onboarding (build, architecture, progress)
Turn the design into a buildable, dependency-free M0 skeleton plus the
onboarding layer so a new agent can pick up instantly.
Build system:
- CMake + CMakePresets (dev = no deps; server-release = vcpkg) + vcpkg.json
- Skeleton builds with just a C++20 compiler; deps stay off until needed
- .gitattributes (LF), .gitignore, .clang-format
Core (libvoicecat):
- core/include/voicecat.h: full C ABI (the client/server contract), stubbed
- core/proto/voicecat.proto: control-plane wire format, matches docs/protocol.md
- src/{net,crypto,codec,protocol,session,audio,core}: subsystem stubs that
return VC_ERR_NOT_IMPLEMENTED, each pointing to its design doc
- server/ (voicecat-server) and tools/vccli/ link the core
- tests/: CTest smoke test asserting the C ABI contract (behavior, not just build)
- clients/{apple,windows}: M4 placeholders
Onboarding for agents:
- CLAUDE.md: hub — build/test commands, architecture at a glance, doc map, rules
- AGENTS.md: working method (behavior-driven; clean compile is the floor not the goal)
- PROGRESS.md: living tracker — M0 done, M1 task checklist, "where we left off"
Verified: cmake --preset dev && cmake --build --preset dev && ctest --preset dev → green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 21:09:09 +02:00
|
|
|
|
|
|
|
|
|
|
// Text (50–59)
|
|
|
|
|
|
TextMessage text_message = 50;
|
|
|
|
|
|
TextMessageAck text_message_ack = 51;
|
|
|
|
|
|
TypingIndicator typing = 52;
|
|
|
|
|
|
|
|
|
|
|
|
// Moderation / permissions (60–69)
|
|
|
|
|
|
KickRequest kick = 60;
|
|
|
|
|
|
BanRequest ban = 61;
|
|
|
|
|
|
SetPermissionRequest set_permission = 62;
|
M5: moderation, permissions, channel CRUD, in-app account management
- Server-side moderation & permissions (kick/ban/move/server-mute, channel CRUD).
- Database schema v2: channels, bans; BLAKE2b channel passwords, Argon2id accounts.
- C ABI additions and client-side handling (vc_kick_user, vc_ban_user, vc_set_permission, vc_set_server_mute, vc_move_user, vc_create/edit/delete_channel, vc_create/reset/delete/list_account).
- vccli flags for all M5 operations plus --username/--password auth.
- Four new tests covering permissions, kick/ban/move/mute, admin accounts, channel CRUD.
- Docs: protocol.md envelope updates, security.md channel-password hashing, PROGRESS.md.
2026-06-17 15:08:05 +02:00
|
|
|
|
ServerMuteRequest server_mute = 63;
|
scaffold: M0 skeleton + agent onboarding (build, architecture, progress)
Turn the design into a buildable, dependency-free M0 skeleton plus the
onboarding layer so a new agent can pick up instantly.
Build system:
- CMake + CMakePresets (dev = no deps; server-release = vcpkg) + vcpkg.json
- Skeleton builds with just a C++20 compiler; deps stay off until needed
- .gitattributes (LF), .gitignore, .clang-format
Core (libvoicecat):
- core/include/voicecat.h: full C ABI (the client/server contract), stubbed
- core/proto/voicecat.proto: control-plane wire format, matches docs/protocol.md
- src/{net,crypto,codec,protocol,session,audio,core}: subsystem stubs that
return VC_ERR_NOT_IMPLEMENTED, each pointing to its design doc
- server/ (voicecat-server) and tools/vccli/ link the core
- tests/: CTest smoke test asserting the C ABI contract (behavior, not just build)
- clients/{apple,windows}: M4 placeholders
Onboarding for agents:
- CLAUDE.md: hub — build/test commands, architecture at a glance, doc map, rules
- AGENTS.md: working method (behavior-driven; clean compile is the floor not the goal)
- PROGRESS.md: living tracker — M0 done, M1 task checklist, "where we left off"
Verified: cmake --preset dev && cmake --build --preset dev && ctest --preset dev → green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 21:09:09 +02:00
|
|
|
|
|
|
|
|
|
|
// Admin account management — privileged; accounts are admin-provisioned (70–79)
|
|
|
|
|
|
CreateAccountRequest create_account = 70;
|
|
|
|
|
|
ResetPasswordRequest reset_password = 71;
|
|
|
|
|
|
DeleteAccountRequest delete_account = 72;
|
|
|
|
|
|
ListAccountsRequest list_accounts = 73;
|
M5: moderation, permissions, channel CRUD, in-app account management
- Server-side moderation & permissions (kick/ban/move/server-mute, channel CRUD).
- Database schema v2: channels, bans; BLAKE2b channel passwords, Argon2id accounts.
- C ABI additions and client-side handling (vc_kick_user, vc_ban_user, vc_set_permission, vc_set_server_mute, vc_move_user, vc_create/edit/delete_channel, vc_create/reset/delete/list_account).
- vccli flags for all M5 operations plus --username/--password auth.
- Four new tests covering permissions, kick/ban/move/mute, admin accounts, channel CRUD.
- Docs: protocol.md envelope updates, security.md channel-password hashing, PROGRESS.md.
2026-06-17 15:08:05 +02:00
|
|
|
|
ListAccountsResult list_accounts_result = 74;
|
scaffold: M0 skeleton + agent onboarding (build, architecture, progress)
Turn the design into a buildable, dependency-free M0 skeleton plus the
onboarding layer so a new agent can pick up instantly.
Build system:
- CMake + CMakePresets (dev = no deps; server-release = vcpkg) + vcpkg.json
- Skeleton builds with just a C++20 compiler; deps stay off until needed
- .gitattributes (LF), .gitignore, .clang-format
Core (libvoicecat):
- core/include/voicecat.h: full C ABI (the client/server contract), stubbed
- core/proto/voicecat.proto: control-plane wire format, matches docs/protocol.md
- src/{net,crypto,codec,protocol,session,audio,core}: subsystem stubs that
return VC_ERR_NOT_IMPLEMENTED, each pointing to its design doc
- server/ (voicecat-server) and tools/vccli/ link the core
- tests/: CTest smoke test asserting the C ABI contract (behavior, not just build)
- clients/{apple,windows}: M4 placeholders
Onboarding for agents:
- CLAUDE.md: hub — build/test commands, architecture at a glance, doc map, rules
- AGENTS.md: working method (behavior-driven; clean compile is the floor not the goal)
- PROGRESS.md: living tracker — M0 done, M1 task checklist, "where we left off"
Verified: cmake --preset dev && cmake --build --preset dev && ctest --preset dev → green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 21:09:09 +02:00
|
|
|
|
|
|
|
|
|
|
// Future families: file transfer = 100–109. Extension escape hatch = 200+.
|
|
|
|
|
|
Extension extension = 200;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ── Enums ──────────────────────────────────────────────────────────────────────
|
|
|
|
|
|
enum ChannelType { CHANNEL_PERMANENT = 0; CHANNEL_TEMPORARY = 1; }
|
|
|
|
|
|
enum ChannelMode { MODE_MONO = 0; MODE_STEREO = 1; }
|
|
|
|
|
|
enum StreamKind { STREAM_MIC = 0; STREAM_SCREEN_AUDIO = 1; STREAM_AUX_DEVICE = 2; }
|
|
|
|
|
|
enum TextScope { TEXT_CHANNEL = 0; TEXT_PRIVATE = 1; TEXT_SERVER = 2; }
|
|
|
|
|
|
enum OpusApplication { OPUS_VOIP = 0; OPUS_AUDIO = 1; OPUS_LOWDELAY = 2; }
|
|
|
|
|
|
|
|
|
|
|
|
// ── Common types ────────────────────────────────────────────────────────────────
|
|
|
|
|
|
message AudioConfig {
|
|
|
|
|
|
uint32 codec = 1; // 0 = OPUS
|
|
|
|
|
|
ChannelMode mode = 2;
|
|
|
|
|
|
uint32 sample_rate = 3; // 48000 recommended
|
|
|
|
|
|
uint32 bitrate_bps = 4;
|
|
|
|
|
|
uint32 frame_ms = 5; // 2.5/5/10/20/40/60
|
|
|
|
|
|
OpusApplication application = 6;
|
|
|
|
|
|
bool fec = 7;
|
|
|
|
|
|
uint32 expected_packet_loss = 8; // %
|
|
|
|
|
|
bool dtx = 9;
|
|
|
|
|
|
uint32 complexity = 10; // 0..10
|
2026-06-20 13:40:47 +02:00
|
|
|
|
bool dred = 11; // Deep REDundancy (Opus 1.6); off by default
|
scaffold: M0 skeleton + agent onboarding (build, architecture, progress)
Turn the design into a buildable, dependency-free M0 skeleton plus the
onboarding layer so a new agent can pick up instantly.
Build system:
- CMake + CMakePresets (dev = no deps; server-release = vcpkg) + vcpkg.json
- Skeleton builds with just a C++20 compiler; deps stay off until needed
- .gitattributes (LF), .gitignore, .clang-format
Core (libvoicecat):
- core/include/voicecat.h: full C ABI (the client/server contract), stubbed
- core/proto/voicecat.proto: control-plane wire format, matches docs/protocol.md
- src/{net,crypto,codec,protocol,session,audio,core}: subsystem stubs that
return VC_ERR_NOT_IMPLEMENTED, each pointing to its design doc
- server/ (voicecat-server) and tools/vccli/ link the core
- tests/: CTest smoke test asserting the C ABI contract (behavior, not just build)
- clients/{apple,windows}: M4 placeholders
Onboarding for agents:
- CLAUDE.md: hub — build/test commands, architecture at a glance, doc map, rules
- AGENTS.md: working method (behavior-driven; clean compile is the floor not the goal)
- PROGRESS.md: living tracker — M0 done, M1 task checklist, "where we left off"
Verified: cmake --preset dev && cmake --build --preset dev && ctest --preset dev → green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 21:09:09 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
message StreamInfo {
|
|
|
|
|
|
uint32 stream_id = 1; // unique within the user
|
|
|
|
|
|
uint32 ssrc = 2; // media-plane id assigned by server
|
|
|
|
|
|
StreamKind kind = 3;
|
|
|
|
|
|
AudioConfig audio = 4;
|
|
|
|
|
|
string label = 5;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
message Channel {
|
|
|
|
|
|
uint32 id = 1;
|
|
|
|
|
|
uint32 parent_id = 2; // 0 = root
|
|
|
|
|
|
string name = 3;
|
|
|
|
|
|
string topic = 4;
|
|
|
|
|
|
bool password_protected = 5;
|
|
|
|
|
|
uint32 max_users = 6;
|
|
|
|
|
|
ChannelType type = 7;
|
|
|
|
|
|
AudioConfig audio = 8;
|
|
|
|
|
|
int32 order = 9;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
message User {
|
|
|
|
|
|
uint32 id = 1;
|
|
|
|
|
|
string nickname = 2;
|
|
|
|
|
|
bool is_guest = 3;
|
|
|
|
|
|
uint32 channel_id = 4;
|
|
|
|
|
|
bool self_mic_muted = 5;
|
|
|
|
|
|
bool self_deafened = 6;
|
|
|
|
|
|
bool server_muted = 7;
|
|
|
|
|
|
repeated StreamInfo streams = 8;
|
M5: moderation, permissions, channel CRUD, in-app account management
- Server-side moderation & permissions (kick/ban/move/server-mute, channel CRUD).
- Database schema v2: channels, bans; BLAKE2b channel passwords, Argon2id accounts.
- C ABI additions and client-side handling (vc_kick_user, vc_ban_user, vc_set_permission, vc_set_server_mute, vc_move_user, vc_create/edit/delete_channel, vc_create/reset/delete/list_account).
- vccli flags for all M5 operations plus --username/--password auth.
- Four new tests covering permissions, kick/ban/move/mute, admin accounts, channel CRUD.
- Docs: protocol.md envelope updates, security.md channel-password hashing, PROGRESS.md.
2026-06-17 15:08:05 +02:00
|
|
|
|
bool server_deafened = 9; // M5: server-imposed deafen
|
feat: fix voice join/leave, channel edit defaults, channel-update stream restart
Three bugs fixed across the full stack (proto/server/core/ABI/Win/macOS/iOS):
1. Join/Leave Voice now truly subscribes/unsubscribes from the voice plane.
Previously the button only toggled the local mic — receiving was always on
(gated by channel membership alone). Added a protocol-level voice subscription
concept: new SubscribeVoiceRequest/UnsubscribeVoiceRequest/VoiceSubscriptionResult
proto messages, User.voice_subscribed field, vc_join_voice/vc_leave_voice C ABI
functions, VC_EVENT_VOICE_STATE event, server-side voice_subscribed flag checked
by the SFU relay recipient filter, and core-client gating of remote-stream
decoder setup. All three clients rewired to subscribe+mic on Join / unsubscribe
on Leave. Text chat works regardless of voice subscription.
2. Channel edit dialog now shows the channel's actual current settings. The read
struct vc_channel was missing sort_order and audio fields — only the write
struct vc_channel_info had them. Extended vc_channel with both (additive, no
ABI break), updated the session model and list_channels marshaling to populate
them, and updated all three clients' edit callers to use actual channel info
instead of hardcoded defaults.
3. Channel parameter updates now automatically restart everyone's streams.
Previously editing a channel's audio config persisted and broadcast a
ChannelEvent::UPDATED, but no layer restarted streams — encoders/decoders are
frozen at announce time. handle_channel_event now detects audio-config changes
on the user's current channel and stop->starts each active local stream. The
server reads the updated config on re-announce; peers wire up fresh decoders
at the new ssrc.
All 29 CTest tests pass; Windows DLL + C# client build clean. Apple clients not
yet compile-verified (Windows environment).
2026-06-24 14:29:39 +02:00
|
|
|
|
bool voice_subscribed = 10; // true when the user is on the voice plane (hears + can send)
|
scaffold: M0 skeleton + agent onboarding (build, architecture, progress)
Turn the design into a buildable, dependency-free M0 skeleton plus the
onboarding layer so a new agent can pick up instantly.
Build system:
- CMake + CMakePresets (dev = no deps; server-release = vcpkg) + vcpkg.json
- Skeleton builds with just a C++20 compiler; deps stay off until needed
- .gitattributes (LF), .gitignore, .clang-format
Core (libvoicecat):
- core/include/voicecat.h: full C ABI (the client/server contract), stubbed
- core/proto/voicecat.proto: control-plane wire format, matches docs/protocol.md
- src/{net,crypto,codec,protocol,session,audio,core}: subsystem stubs that
return VC_ERR_NOT_IMPLEMENTED, each pointing to its design doc
- server/ (voicecat-server) and tools/vccli/ link the core
- tests/: CTest smoke test asserting the C ABI contract (behavior, not just build)
- clients/{apple,windows}: M4 placeholders
Onboarding for agents:
- CLAUDE.md: hub — build/test commands, architecture at a glance, doc map, rules
- AGENTS.md: working method (behavior-driven; clean compile is the floor not the goal)
- PROGRESS.md: living tracker — M0 done, M1 task checklist, "where we left off"
Verified: cmake --preset dev && cmake --build --preset dev && ctest --preset dev → green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 21:09:09 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
message Permissions {
|
|
|
|
|
|
// Minimal v1 flag set; the moderation milestone expands this. Server-side is authoritative.
|
|
|
|
|
|
bool can_create_temp_channel = 1;
|
|
|
|
|
|
bool can_kick = 2;
|
|
|
|
|
|
bool can_ban = 3;
|
|
|
|
|
|
bool can_move_users = 4;
|
|
|
|
|
|
bool can_admin_accounts = 5;
|
|
|
|
|
|
bool is_admin = 6;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ── Session / handshake ─────────────────────────────────────────────────────────
|
|
|
|
|
|
message ClientHello {
|
|
|
|
|
|
uint32 proto_version = 1;
|
|
|
|
|
|
repeated string features = 2; // "opus", "fec", "screen-audio", ...
|
|
|
|
|
|
string client_name = 3;
|
|
|
|
|
|
string client_version = 4;
|
|
|
|
|
|
string preferred_locale = 5;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
message ServerHello {
|
|
|
|
|
|
uint32 proto_version = 1;
|
|
|
|
|
|
repeated string features = 2;
|
|
|
|
|
|
string server_name = 3;
|
|
|
|
|
|
string server_version = 4;
|
|
|
|
|
|
repeated string auth_methods = 5; // "guest", "password"
|
|
|
|
|
|
uint32 udp_port = 6;
|
|
|
|
|
|
bytes server_identity_fingerprint = 7; // Ed25519 fp for TOFU
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
message GuestAuth { string nickname = 1; }
|
|
|
|
|
|
message PasswordAuth { string username = 1; string password = 2; }
|
|
|
|
|
|
|
|
|
|
|
|
message AuthRequest {
|
|
|
|
|
|
oneof method {
|
|
|
|
|
|
GuestAuth guest = 1;
|
|
|
|
|
|
PasswordAuth password = 2;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
message AuthResult {
|
|
|
|
|
|
bool ok = 1;
|
|
|
|
|
|
string error = 2;
|
|
|
|
|
|
uint64 session_id = 3;
|
|
|
|
|
|
User self = 4;
|
|
|
|
|
|
Permissions permissions = 5;
|
|
|
|
|
|
bytes udp_token = 6; // bind the UDP 5-tuple with this (security.md §3)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
message Disconnect { uint32 code = 1; string reason = 2; }
|
|
|
|
|
|
message Ping { uint64 nonce = 1; }
|
|
|
|
|
|
message Pong { uint64 nonce = 1; }
|
|
|
|
|
|
|
|
|
|
|
|
// ── State sync ──────────────────────────────────────────────────────────────────
|
|
|
|
|
|
message ServerStateSnapshot {
|
|
|
|
|
|
repeated Channel channels = 1;
|
|
|
|
|
|
repeated User users = 2;
|
|
|
|
|
|
}
|
|
|
|
|
|
message ChannelEvent {
|
|
|
|
|
|
enum Kind { CREATED = 0; UPDATED = 1; DELETED = 2; }
|
|
|
|
|
|
Kind kind = 1;
|
|
|
|
|
|
Channel channel = 2;
|
|
|
|
|
|
uint32 deleted_id = 3;
|
|
|
|
|
|
}
|
|
|
|
|
|
message UserEvent {
|
|
|
|
|
|
enum Kind { JOINED = 0; LEFT = 1; UPDATED = 2; }
|
|
|
|
|
|
Kind kind = 1;
|
|
|
|
|
|
User user = 2;
|
|
|
|
|
|
uint32 left_id = 3;
|
M5: moderation, permissions, channel CRUD, in-app account management
- Server-side moderation & permissions (kick/ban/move/server-mute, channel CRUD).
- Database schema v2: channels, bans; BLAKE2b channel passwords, Argon2id accounts.
- C ABI additions and client-side handling (vc_kick_user, vc_ban_user, vc_set_permission, vc_set_server_mute, vc_move_user, vc_create/edit/delete_channel, vc_create/reset/delete/list_account).
- vccli flags for all M5 operations plus --username/--password auth.
- Four new tests covering permissions, kick/ban/move/mute, admin accounts, channel CRUD.
- Docs: protocol.md envelope updates, security.md channel-password hashing, PROGRESS.md.
2026-06-17 15:08:05 +02:00
|
|
|
|
string reason = 4; // M5: kick/ban reason for LEFT events
|
scaffold: M0 skeleton + agent onboarding (build, architecture, progress)
Turn the design into a buildable, dependency-free M0 skeleton plus the
onboarding layer so a new agent can pick up instantly.
Build system:
- CMake + CMakePresets (dev = no deps; server-release = vcpkg) + vcpkg.json
- Skeleton builds with just a C++20 compiler; deps stay off until needed
- .gitattributes (LF), .gitignore, .clang-format
Core (libvoicecat):
- core/include/voicecat.h: full C ABI (the client/server contract), stubbed
- core/proto/voicecat.proto: control-plane wire format, matches docs/protocol.md
- src/{net,crypto,codec,protocol,session,audio,core}: subsystem stubs that
return VC_ERR_NOT_IMPLEMENTED, each pointing to its design doc
- server/ (voicecat-server) and tools/vccli/ link the core
- tests/: CTest smoke test asserting the C ABI contract (behavior, not just build)
- clients/{apple,windows}: M4 placeholders
Onboarding for agents:
- CLAUDE.md: hub — build/test commands, architecture at a glance, doc map, rules
- AGENTS.md: working method (behavior-driven; clean compile is the floor not the goal)
- PROGRESS.md: living tracker — M0 done, M1 task checklist, "where we left off"
Verified: cmake --preset dev && cmake --build --preset dev && ctest --preset dev → green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 21:09:09 +02:00
|
|
|
|
}
|
|
|
|
|
|
message SubscribeRequest { repeated uint32 channel_ids = 1; bool presence = 2; }
|
|
|
|
|
|
|
|
|
|
|
|
// ── Channel operations ──────────────────────────────────────────────────────────
|
|
|
|
|
|
message JoinChannelRequest { uint32 channel_id = 1; string password = 2; }
|
|
|
|
|
|
message JoinChannelResult {
|
|
|
|
|
|
bool ok = 1; string error = 2;
|
|
|
|
|
|
uint32 channel_id = 3;
|
|
|
|
|
|
repeated User members = 4;
|
|
|
|
|
|
AudioConfig audio = 5; // authoritative channel Opus params
|
|
|
|
|
|
}
|
|
|
|
|
|
message LeaveChannelRequest {}
|
|
|
|
|
|
message CreateChannelRequest { Channel channel = 1; string password = 2; }
|
|
|
|
|
|
message EditChannelRequest { Channel channel = 1; string password = 2; }
|
|
|
|
|
|
message DeleteChannelRequest { uint32 channel_id = 1; }
|
|
|
|
|
|
message MoveUserRequest { uint32 user_id = 1; uint32 channel_id = 2; }
|
|
|
|
|
|
message GenericResult { bool ok = 1; uint32 code = 2; string message = 3; }
|
|
|
|
|
|
|
|
|
|
|
|
// ── Voice signaling ─────────────────────────────────────────────────────────────
|
|
|
|
|
|
message StreamAnnounce { StreamKind kind = 1; AudioConfig requested_audio = 2; string label = 3; }
|
|
|
|
|
|
message StreamAnnounceResult{ bool ok = 1; string error = 2; uint32 stream_id = 3; uint32 ssrc = 4; AudioConfig effective_audio = 5; }
|
|
|
|
|
|
message StreamStop { uint32 stream_id = 1; }
|
|
|
|
|
|
message StreamStateUpdate { uint32 user_id = 1; uint32 stream_id = 2; bool muted = 3; bool talking = 4; }
|
|
|
|
|
|
message UdpBinding { bytes udp_token = 1; bool ack = 2; }
|
feat: fix voice join/leave, channel edit defaults, channel-update stream restart
Three bugs fixed across the full stack (proto/server/core/ABI/Win/macOS/iOS):
1. Join/Leave Voice now truly subscribes/unsubscribes from the voice plane.
Previously the button only toggled the local mic — receiving was always on
(gated by channel membership alone). Added a protocol-level voice subscription
concept: new SubscribeVoiceRequest/UnsubscribeVoiceRequest/VoiceSubscriptionResult
proto messages, User.voice_subscribed field, vc_join_voice/vc_leave_voice C ABI
functions, VC_EVENT_VOICE_STATE event, server-side voice_subscribed flag checked
by the SFU relay recipient filter, and core-client gating of remote-stream
decoder setup. All three clients rewired to subscribe+mic on Join / unsubscribe
on Leave. Text chat works regardless of voice subscription.
2. Channel edit dialog now shows the channel's actual current settings. The read
struct vc_channel was missing sort_order and audio fields — only the write
struct vc_channel_info had them. Extended vc_channel with both (additive, no
ABI break), updated the session model and list_channels marshaling to populate
them, and updated all three clients' edit callers to use actual channel info
instead of hardcoded defaults.
3. Channel parameter updates now automatically restart everyone's streams.
Previously editing a channel's audio config persisted and broadcast a
ChannelEvent::UPDATED, but no layer restarted streams — encoders/decoders are
frozen at announce time. handle_channel_event now detects audio-config changes
on the user's current channel and stop->starts each active local stream. The
server reads the updated config on re-announce; peers wire up fresh decoders
at the new ssrc.
All 29 CTest tests pass; Windows DLL + C# client build clean. Apple clients not
yet compile-verified (Windows environment).
2026-06-24 14:29:39 +02:00
|
|
|
|
|
|
|
|
|
|
// Voice-plane subscription. Joining voice = you can hear and send voice in your channel;
|
|
|
|
|
|
// leaving voice = the server stops relaying voice frames to you and you stop receiving.
|
|
|
|
|
|
// Text chat is unaffected. The server toggles a per-session flag checked by the SFU relay's
|
|
|
|
|
|
// recipient filter (docs/protocol.md §5). Result arrives as voice_subscription_result.
|
|
|
|
|
|
message SubscribeVoiceRequest {}
|
|
|
|
|
|
message UnsubscribeVoiceRequest {}
|
|
|
|
|
|
message VoiceSubscriptionResult { bool ok = 1; string error = 2; bool subscribed = 3; }
|
scaffold: M0 skeleton + agent onboarding (build, architecture, progress)
Turn the design into a buildable, dependency-free M0 skeleton plus the
onboarding layer so a new agent can pick up instantly.
Build system:
- CMake + CMakePresets (dev = no deps; server-release = vcpkg) + vcpkg.json
- Skeleton builds with just a C++20 compiler; deps stay off until needed
- .gitattributes (LF), .gitignore, .clang-format
Core (libvoicecat):
- core/include/voicecat.h: full C ABI (the client/server contract), stubbed
- core/proto/voicecat.proto: control-plane wire format, matches docs/protocol.md
- src/{net,crypto,codec,protocol,session,audio,core}: subsystem stubs that
return VC_ERR_NOT_IMPLEMENTED, each pointing to its design doc
- server/ (voicecat-server) and tools/vccli/ link the core
- tests/: CTest smoke test asserting the C ABI contract (behavior, not just build)
- clients/{apple,windows}: M4 placeholders
Onboarding for agents:
- CLAUDE.md: hub — build/test commands, architecture at a glance, doc map, rules
- AGENTS.md: working method (behavior-driven; clean compile is the floor not the goal)
- PROGRESS.md: living tracker — M0 done, M1 task checklist, "where we left off"
Verified: cmake --preset dev && cmake --build --preset dev && ctest --preset dev → green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 21:09:09 +02:00
|
|
|
|
|
|
|
|
|
|
// ── Text (ephemeral — server does not persist history, docs/protocol.md §5) ──────
|
|
|
|
|
|
message TextMessage {
|
|
|
|
|
|
TextScope scope = 1;
|
|
|
|
|
|
uint32 target_id = 2; // channel_id or user_id per scope
|
|
|
|
|
|
uint32 sender_id = 3; // set by server on relay
|
|
|
|
|
|
string body = 4; // UTF-8, server-bounded length
|
|
|
|
|
|
uint64 sent_at_unix_ms = 5; // server timestamp on relay
|
|
|
|
|
|
string client_msg_id = 6; // echoed in ack (dedup)
|
|
|
|
|
|
}
|
|
|
|
|
|
message TextMessageAck { string client_msg_id = 1; bool ok = 2; }
|
|
|
|
|
|
message TypingIndicator { TextScope scope = 1; uint32 target_id = 2; uint32 user_id = 3; }
|
|
|
|
|
|
|
|
|
|
|
|
// ── Moderation / permissions ─────────────────────────────────────────────────────
|
|
|
|
|
|
message KickRequest { uint32 user_id = 1; string reason = 2; }
|
|
|
|
|
|
message BanRequest { uint32 user_id = 1; string reason = 2; uint64 expires_unix_ms = 3; }
|
|
|
|
|
|
message SetPermissionRequest { uint32 user_id = 1; Permissions permissions = 2; }
|
M5: moderation, permissions, channel CRUD, in-app account management
- Server-side moderation & permissions (kick/ban/move/server-mute, channel CRUD).
- Database schema v2: channels, bans; BLAKE2b channel passwords, Argon2id accounts.
- C ABI additions and client-side handling (vc_kick_user, vc_ban_user, vc_set_permission, vc_set_server_mute, vc_move_user, vc_create/edit/delete_channel, vc_create/reset/delete/list_account).
- vccli flags for all M5 operations plus --username/--password auth.
- Four new tests covering permissions, kick/ban/move/mute, admin accounts, channel CRUD.
- Docs: protocol.md envelope updates, security.md channel-password hashing, PROGRESS.md.
2026-06-17 15:08:05 +02:00
|
|
|
|
message ServerMuteRequest { uint32 user_id = 1; bool muted = 2; bool deafened = 3; }
|
scaffold: M0 skeleton + agent onboarding (build, architecture, progress)
Turn the design into a buildable, dependency-free M0 skeleton plus the
onboarding layer so a new agent can pick up instantly.
Build system:
- CMake + CMakePresets (dev = no deps; server-release = vcpkg) + vcpkg.json
- Skeleton builds with just a C++20 compiler; deps stay off until needed
- .gitattributes (LF), .gitignore, .clang-format
Core (libvoicecat):
- core/include/voicecat.h: full C ABI (the client/server contract), stubbed
- core/proto/voicecat.proto: control-plane wire format, matches docs/protocol.md
- src/{net,crypto,codec,protocol,session,audio,core}: subsystem stubs that
return VC_ERR_NOT_IMPLEMENTED, each pointing to its design doc
- server/ (voicecat-server) and tools/vccli/ link the core
- tests/: CTest smoke test asserting the C ABI contract (behavior, not just build)
- clients/{apple,windows}: M4 placeholders
Onboarding for agents:
- CLAUDE.md: hub — build/test commands, architecture at a glance, doc map, rules
- AGENTS.md: working method (behavior-driven; clean compile is the floor not the goal)
- PROGRESS.md: living tracker — M0 done, M1 task checklist, "where we left off"
Verified: cmake --preset dev && cmake --build --preset dev && ctest --preset dev → green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 21:09:09 +02:00
|
|
|
|
|
|
|
|
|
|
// ── Admin account management (privileged) ────────────────────────────────────────
|
|
|
|
|
|
message CreateAccountRequest { string username = 1; string password = 2; }
|
|
|
|
|
|
message ResetPasswordRequest { string username = 1; string new_password = 2; }
|
|
|
|
|
|
message DeleteAccountRequest { string username = 1; }
|
|
|
|
|
|
message ListAccountsRequest {}
|
M5: moderation, permissions, channel CRUD, in-app account management
- Server-side moderation & permissions (kick/ban/move/server-mute, channel CRUD).
- Database schema v2: channels, bans; BLAKE2b channel passwords, Argon2id accounts.
- C ABI additions and client-side handling (vc_kick_user, vc_ban_user, vc_set_permission, vc_set_server_mute, vc_move_user, vc_create/edit/delete_channel, vc_create/reset/delete/list_account).
- vccli flags for all M5 operations plus --username/--password auth.
- Four new tests covering permissions, kick/ban/move/mute, admin accounts, channel CRUD.
- Docs: protocol.md envelope updates, security.md channel-password hashing, PROGRESS.md.
2026-06-17 15:08:05 +02:00
|
|
|
|
message AccountEntry { string username = 1; bool is_admin = 2; uint64 created_at_unix_ms = 3; uint64 last_login_unix_ms = 4; }
|
|
|
|
|
|
message ListAccountsResult { repeated AccountEntry accounts = 1; }
|
scaffold: M0 skeleton + agent onboarding (build, architecture, progress)
Turn the design into a buildable, dependency-free M0 skeleton plus the
onboarding layer so a new agent can pick up instantly.
Build system:
- CMake + CMakePresets (dev = no deps; server-release = vcpkg) + vcpkg.json
- Skeleton builds with just a C++20 compiler; deps stay off until needed
- .gitattributes (LF), .gitignore, .clang-format
Core (libvoicecat):
- core/include/voicecat.h: full C ABI (the client/server contract), stubbed
- core/proto/voicecat.proto: control-plane wire format, matches docs/protocol.md
- src/{net,crypto,codec,protocol,session,audio,core}: subsystem stubs that
return VC_ERR_NOT_IMPLEMENTED, each pointing to its design doc
- server/ (voicecat-server) and tools/vccli/ link the core
- tests/: CTest smoke test asserting the C ABI contract (behavior, not just build)
- clients/{apple,windows}: M4 placeholders
Onboarding for agents:
- CLAUDE.md: hub — build/test commands, architecture at a glance, doc map, rules
- AGENTS.md: working method (behavior-driven; clean compile is the floor not the goal)
- PROGRESS.md: living tracker — M0 done, M1 task checklist, "where we left off"
Verified: cmake --preset dev && cmake --build --preset dev && ctest --preset dev → green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 21:09:09 +02:00
|
|
|
|
|
|
|
|
|
|
// ── Extension escape hatch ───────────────────────────────────────────────────────
|
|
|
|
|
|
message Extension { string ns = 1; bytes payload = 2; }
|