diff --git a/docs/governance/master-todo-list-2026-06-11.md b/docs/governance/master-todo-list-2026-06-11.md index 1aca6c4..2f6cdac 100644 --- a/docs/governance/master-todo-list-2026-06-11.md +++ b/docs/governance/master-todo-list-2026-06-11.md @@ -457,6 +457,7 @@ - **Description:** Chanora forks `tsclientlib` for a p256 fix. Submit PR upstream to reduce fork maintenance burden. - **Effort:** M - **Dependencies:** None +- **Status:** PR DRAFT READY — `docs/references/upstream-p256-pr-draft.md` (2026-06-11) ### TODO-058 — Monitor tsdeclarations for TS5 protocol updates - **Priority:** P2 @@ -464,6 +465,7 @@ - **Description:** No full TS5 client protocol exists yet. Watch `tsdeclarations` repo for updates that may affect Chanora compatibility. - **Effort:** S - **Dependencies:** None (ongoing) +- **Status:** MONITORING — no TS5 protocol updates detected; `tsdeclarations` last checked 2026-06-11 ### TODO-059 — Build auto-reconnect logic internally - **Priority:** P2 @@ -488,6 +490,7 @@ - **Description:** YaTQA's `/ressourcen/` section has comprehensive unofficial server error codes. Extract for Chanora error handling reference. - **Effort:** S - **Dependencies:** None +- **Status:** VERIFIED COMPLETE — 170+ error codes in yatqa-offline-reference.md §9, cross-reference with ReSpeak in §13 (2026-06-11) ### TODO-061 — Extract anti-flood/rate-limiting reference from YaTQA - **Priority:** P3 @@ -495,6 +498,7 @@ - **Description:** YaTQA documents anti-flood mechanics and rate limiting. Use as reference when implementing Chanora's rate limiting. - **Effort:** S - **Dependencies:** None +- **Status:** PARTIALLY COMPLETE — summary tiers in yatqa-offline-reference.md §5; detailed action table still needs backfill (see TODO-081) --- @@ -521,7 +525,8 @@ - **Description:** TS claims UTF-8 but uses UCS-2 (BMP only). Mobile apps use CESU-8. Server 3.2.0+ adds partial emoji support. tsclientlib/tsproto delivers Rust `String` (UTF-8) via `str::from_utf8()` at the protocol layer (ReSpeak §1.8.3 confirms: "Command string encoded in UTF-8"). If encoding bugs exist, the fix belongs in the EdisonJwa/tsclientlib fork, not in chanora_protocol. - **Verification:** Confirm tsclientlib handles UCS-2 correctly. Document encoding behavior in protocol-implementation-traps.md (TODO-070). - **Effort:** S (verification + documentation) -- **Status:** Scope revised from implementation to verification (2026-06-11) +- **Status:** VERIFIED — strict UTF-8 via `str::from_utf8()`, no UCS-2/CESU-8 code exists, non-UTF-8 causes errors not corruption (2026-06-11) +- **Evidence:** `docs/references/encoding-verification.md` - **Dependencies:** TODO-070 (protocol traps doc) ### TODO-064 — Implement client-side anti-flood point awareness @@ -579,6 +584,7 @@ - **Description:** TS3 server 3.1.6-3.1.7 has IPv6 canonicalization bug in Blacklist2 protocol. Chanora should be aware when connecting to older servers. - **Effort:** S - **Dependencies:** None +- **Status:** DOCUMENTED — trap #6 in protocol-implementation-traps.md (2026-06-11) ### TODO-072 — Establish connection/message performance benchmarks - **Priority:** P3 @@ -586,6 +592,7 @@ - **Description:** tsclientlib benchmarks: ~199ms connect, ~189µs/message. Use as baseline for Chanora's performance testing. - **Effort:** S - **Dependencies:** None +- **Status:** DOCUMENT CREATED — `docs/references/performance-benchmarks.md` (2026-06-11) ### TODO-073 — Assess web client feasibility - **Priority:** P3 @@ -593,6 +600,7 @@ - **Description:** TeaSpeak's web client was a compelling installation-less option. Evaluate whether a future Chanora web client makes sense. Not current scope. - **Effort:** S - **Dependencies:** None +- **Status:** ASSESSMENT COMPLETE — `docs/references/web-client-feasibility.md`; verdict: defer indefinitely (UDP transport blocker) (2026-06-11) --- diff --git a/docs/references/encoding-verification.md b/docs/references/encoding-verification.md new file mode 100644 index 0000000..77a172f --- /dev/null +++ b/docs/references/encoding-verification.md @@ -0,0 +1,102 @@ +# tsclientlib Encoding Handling Verification + +**Date:** 2026-06-11 +**Scope:** Verification of encoding handling in Chanora's tsclientlib fork +**Checkout analyzed:** `~/.cargo/git/checkouts/tsclientlib-b9d0d0212095a0c5/3fbfa26/` + +--- + +## 1. How tsclientlib Handles Encoding + +### Command Layer (`tsproto-packets/src/commands.rs`) + +The `CommandParser` operates on raw `&[u8]` bytes. String conversion happens at the value level: + +- **`CommandArgumentValue::get_str()`** (line 157): Returns `Result>` using `str::from_utf8()` on raw bytes or `String::from_utf8()` on unescaped bytes. +- **`CommandArgumentValue::get_parse()`** (line 166): Calls `get_str()` then `.parse()` for typed values. +- Both methods return `Utf8Error` on invalid UTF-8 — **strict validation, not lossy**. + +### Packet Layer (`tsproto/src/`) + +| File | Line | Usage | Behavior | +|------|------|-------|----------| +| `license.rs` | 482, 550 | `str::from_utf8(&data[...])` | Strict — returns `Error::DeserializeString` on failure | +| `log.rs` | 84, 101 | `if let Ok(s) = str::from_utf8(packet.content())` | Silent skip — invalid UTF-8 packets are not logged | +| `client.rs` | 363 | `str::from_utf8(name)` | Used in error message formatting only | +| `algorithms.rs` | 450 | `String::from_utf8_lossy(&dec)` | Lossy — only in debug `println!` | + +### Bookkeeping Layer (`utils/ts-bookkeeping/`) + +- All string fields in `Connection`, `Server`, `Client`, `Channel` structs are `String` (Rust's UTF-8 type). +- Generated message parsers (via `MessageDeclarations.tt` line 47) use `str::from_utf8(s)?.to_string()` — strict UTF-8 validation. +- `ParseError::StringParse` wraps `std::str::Utf8Error` (messages.rs:26). + +--- + +## 2. UCS-2 and CESU-8 Handling + +**No UCS-2 or CESU-8 code exists anywhere in the fork.** + +Search for `ucs`, `UCS`, `cesu`, `CESU`, `utf16`, `UTF16`, `utf-16`, `UTF-16` across all `.rs` files returned zero results. + +The fork treats all protocol data as UTF-8 bytes. There is no: +- UCS-2 to UTF-8 conversion +- CESU-8 decoding +- UTF-16 handling +- Encoding detection or negotiation + +--- + +## 3. What Happens with Non-UTF-8 Data + +If the server sends non-UTF-8 bytes (e.g., UCS-2 encoded emoji from an older client): + +| Layer | Behavior | +|-------|----------| +| `CommandParser::get_str()` | Returns `Err(Utf8Error)` — call site decides | +| License parsing | Returns `Err(Error::DeserializeString)` — connection fails | +| Log parsing | `if let Ok(s)` — silently skipped, packet not logged | +| Message parsing | Returns `Err(ParseError::StringParse)` — command rejected | + +**Critical:** There is no graceful fallback. Non-UTF-8 data causes errors at the protocol layer. + +--- + +## 4. What the TS3 Protocol Actually Sends + +Per ReSpeak protocol reference §1.8.3: "Command string encoded in UTF-8" + +The TS3 protocol itself uses UTF-8 for command strings. The UCS-2 concern applies to: +- **Older mobile clients** (pre-3.2.0) that may send CESU-8 encoded supplementary characters +- **Server-side storage** where some servers may store UCS-2 for certain fields +- **Emoji support** added in Server 3.2.0+ (UTF-8 with full Unicode) + +In practice, the protocol wire format is UTF-8. The UCS-2 issue is a server/client implementation detail, not a protocol encoding issue. + +--- + +## 5. Risks for Chanora + +### Low Risk +- **Normal operation:** Modern TS3 servers and clients send valid UTF-8. No issues expected. +- **Chanora's own strings:** Always valid UTF-8 (Rust `String` type guarantees this). + +### Medium Risk +- **Legacy clients:** Older mobile clients sending CESU-8 will cause `Utf8Error` in command parsing. Commands will be rejected, not silently corrupted. +- **Server names/channel names with emoji:** If a server stores names in UCS-2 format (some older databases), Chanora will fail to parse them. + +### Mitigation +- The fork uses **strict** UTF-8 validation (not lossy). This is correct behavior — rejecting malformed data is safer than silently corrupting it. +- If UCS-2 compatibility is needed, the fix belongs in the `EdisonJwa/tsclientlib` fork, not in Chanora's protocol layer. + +--- + +## 6. Conclusion + +tsclientlib handles encoding correctly for the TS3 protocol: +- All string parsing uses `str::from_utf8()` — strict UTF-8 validation +- No UCS-2/CESU-8 code exists — the fork assumes UTF-8 wire format +- Invalid UTF-8 causes errors, not silent corruption +- The protocol itself is UTF-8; UCS-2 is an edge case from legacy implementations + +**Status:** VERIFIED — encoding handling is correct as-is. diff --git a/docs/references/permission-id-mapping.md b/docs/references/permission-id-mapping.md new file mode 100644 index 0000000..5ff6b31 --- /dev/null +++ b/docs/references/permission-id-mapping.md @@ -0,0 +1,428 @@ +# TS3 Permission ID Mapping to Chanora + +**TODO-069** — Map TS3 permissions to Chanora's permission system. + +--- + +## 1. TS3 Permission System Overview + +### 1.1 Permission Tiers (from YaTQA §1.2) + +Permissions are evaluated top-to-bottom, lowest tier wins: + +| Tier | Level | Description | +|------|-------|-------------| +| 0 | Server Groups | Highest value wins (unless Negate flag) | +| 1 | Client (Server level) | Client-specific server permissions | +| 2 | Channel | Skipped if Skip flag set | +| 3 | Channel Group | Skipped if Skip flag set | +| 4 | Client (Channel level) | Client-specific channel permissions | + +### 1.2 Permission Types (from Enums.toml) + +| Type | ID1 | ID2 | +|------|-----|-----| +| ServerGroup | ServerGroupId | 0 | +| GlobalClient | ClientDbId | 0 | +| Channel | ChannelId | 0 | +| ChannelGroup | ChannelId | ChannelGroupId | +| ChannelClient | ChannelId | ClientDbId | + +### 1.3 Special Flags + +- **Skip flag**: Skips channel and channel group permissions +- **Negate flag**: If ANY server group has Negate, only Negate groups count +- **Grant permission**: `i_needed_permission_modify_power_*` — controls who can modify a permission + +--- + +## 2. Chanora's Current Permission Handling + +### 2.1 What Exists + +| Component | Permission Handling | Location | +|-----------|-------------------|----------| +| `chanora_bridge::permission_jni` | Android `RECORD_AUDIO` runtime permission only | `crates/chanora_bridge/src/permission_jni.rs` | +| `chanora_bridge::api::PermissionStateKind` | Android permission state enum (Granted/Denied/PermanentlyDenied) | `crates/chanora_bridge/src/api.rs` | +| `chanora_core` | No TS3 permission model | — | +| `chanora_protocol` | Error code `0x0a08` (permissions_client_insufficient) recognized but no permission ID mapping | `crates/chanora_protocol/src/lib.rs:109` | +| `chanora_protocol::adapter` | Permission-gated fields (e.g., `client_address` empty when no permission) | `crates/chanora_protocol/src/dto.rs:181` | +| `VoiceJoinErrorCode::JoinDenied` | Generic "denied by server policy/permission" | `core/chanora_core/src/events.rs:267` | + +### 2.2 What Does NOT Exist + +- No TS3 permission ID constants +- No permission evaluation engine (Skip/Negate/Grant logic) +- No per-permission checks before protocol commands +- No permission-aware UI gating +- No server group / channel group permission tracking + +--- + +## 3. Permission ID Mapping + +The following table maps all TS3 permission IDs from `Permissions.csv` / ReSpeak reference §3 to Chanora's current handling. + +### 3.1 Server Instance Permissions + +| Permission Name | Category | Chanora Status | Notes | +|----------------|----------|----------------|-------| +| `b_serverinstance_help_view` | Query | Not needed | ServerQuery only | +| `b_serverinstance_version_view` | Query | Not needed | ServerQuery only | +| `b_serverinstance_info_view` | Query | Not needed | ServerQuery only | +| `b_serverinstance_virtualserver_list` | Query | Not needed | ServerQuery only | +| `b_serverinstance_binding_list` | Query | Not needed | ServerQuery only | +| `b_serverinstance_permission_list` | Query | Not needed | ServerQuery only | +| `b_serverinstance_permission_find` | Query | Not needed | ServerQuery only | +| `b_virtualserver_create` | Admin | Not needed | Admin operation | +| `b_virtualserver_delete` | Admin | Not needed | Admin operation | +| `b_virtualserver_start_any` | Admin | Not needed | Admin operation | +| `b_virtualserver_stop_any` | Admin | Not needed | Admin operation | +| `b_virtualserver_change_machine_id` | Admin | Not needed | Admin operation | +| `b_virtualserver_change_template` | Admin | Not needed | Admin operation | +| `b_serverquery_login` | Query | Not needed | ServerQuery only | +| `b_serverinstance_textmessage_send` | Query | Not needed | ServerQuery only | +| `b_serverinstance_log_view` | Query | Not needed | ServerQuery only | +| `b_serverinstance_log_add` | Query | Not needed | ServerQuery only | +| `b_serverinstance_stop` | Admin | Not needed | Admin operation | +| `b_serverinstance_modify_settings` | Admin | Not needed | Admin operation | +| `b_serverinstance_modify_querygroup` | Admin | Not needed | Admin operation | +| `b_serverinstance_modify_templates` | Admin | Not needed | Admin operation | + +### 3.2 Virtual Server Permissions + +| Permission Name | Category | Chanora Status | Priority | Notes | +|----------------|----------|----------------|----------|-------| +| `b_virtualserver_select` | Query | Not needed | — | ServerQuery only | +| `b_virtualserver_info_view` | Read | **Implicit** | P3 | Used by `serverinfo` command | +| `b_virtualserver_connectioninfo_view` | Read | **Implicit** | P3 | Used by `serverrequestconnectioninfo` | +| `b_virtualserver_channel_list` | Read | **Implicit** | P3 | Used by `channellist` command | +| `b_virtualserver_channel_search` | Read | Not needed | — | ServerQuery only | +| `b_virtualserver_client_list` | Read | **Implicit** | P3 | Used by `clientlist` command | +| `b_virtualserver_client_search` | Read | Not needed | — | ServerQuery only | +| `b_virtualserver_client_dblist` | Read | Not needed | — | ServerQuery only | +| `b_virtualserver_client_dbsearch` | Read | Not needed | — | ServerQuery only | +| `b_virtualserver_client_dbinfo` | Read | **Implicit** | P3 | Used by `clientdbinfo` | +| `b_virtualserver_permission_find` | Read | Not needed | — | ServerQuery only | +| `b_virtualserver_custom_search` | Read | Not needed | — | ServerQuery only | +| `b_virtualserver_start` | Admin | Not needed | — | Admin operation | +| `b_virtualserver_stop` | Admin | Not needed | — | Admin operation | +| `b_virtualserver_token_list` | Admin | Not needed | — | Admin operation | +| `b_virtualserver_token_add` | Admin | Not needed | — | Admin operation | +| `b_virtualserver_token_use` | Connect | **Implicit** | P2 | Used in `clientinit` default_token | +| `b_virtualserver_token_delete` | Admin | Not needed | — | Admin operation | +| `b_virtualserver_log_view` | Query | Not needed | — | ServerQuery only | +| `b_virtualserver_log_add` | Query | Not needed | — | ServerQuery only | +| `b_virtualserver_join_ignore_password` | Connect | Not needed | — | Rare | +| `b_virtualserver_notify_register` | Read | **Implicit** | P3 | Used by `servernotifyregister` | +| `b_virtualserver_notify_unregister` | Read | **Implicit** | P3 | Used by `servernotifyunregister` | +| `b_virtualserver_snapshot_create` | Admin | Not needed | — | Admin operation | +| `b_virtualserver_snapshot_deploy` | Admin | Not needed | — | Admin operation | +| `b_virtualserver_permission_reset` | Admin | Not needed | — | Admin operation | +| `b_virtualserver_modify_name` | Admin | Not needed | — | Admin operation | +| `b_virtualserver_modify_welcomemessage` | Admin | Not needed | — | Admin operation | +| `b_virtualserver_modify_maxclients` | Admin | Not needed | — | Admin operation | +| `b_virtualserver_modify_reserved_slots` | Admin | Not needed | — | Admin operation | +| `b_virtualserver_modify_password` | Admin | Not needed | — | Admin operation | +| `b_virtualserver_modify_default_servergroup` | Admin | Not needed | — | Admin operation | +| `b_virtualserver_modify_default_channelgroup` | Admin | Not needed | — | Admin operation | +| `b_virtualserver_modify_default_channeladmingroup` | Admin | Not needed | — | Admin operation | +| `b_virtualserver_modify_channel_forced_silence` | Admin | Not needed | — | Admin operation | +| `b_virtualserver_modify_complain` | Admin | Not needed | — | Admin operation | +| `b_virtualserver_modify_antiflood` | Admin | Not needed | — | Admin operation | +| `b_virtualserver_modify_ft_settings` | Admin | Not needed | — | Admin operation | +| `b_virtualserver_modify_ft_quotas` | Admin | Not needed | — | Admin operation | +| `b_virtualserver_modify_hostmessage` | Admin | Not needed | — | Admin operation | +| `b_virtualserver_modify_hostbanner` | Admin | Not needed | — | Admin operation | +| `b_virtualserver_modify_hostbutton` | Admin | Not needed | — | Admin operation | +| `b_virtualserver_modify_port` | Admin | Not needed | — | Admin operation | +| `b_virtualserver_modify_autostart` | Admin | Not needed | — | Admin operation | +| `b_virtualserver_modify_needed_identity_security_level` | Admin | Not needed | — | Admin operation | +| `b_virtualserver_modify_priority_speaker_dimm_modificator` | Admin | Not needed | — | Admin operation | +| `b_virtualserver_modify_log_settings` | Admin | Not needed | — | Admin operation | +| `b_virtualserver_modify_min_client_version` | Admin | Not needed | — | Admin operation | +| `b_virtualserver_modify_icon_id` | Admin | Not needed | — | Admin operation | +| `b_virtualserver_modify_weblist` | Admin | Not needed | — | Admin operation | +| `b_virtualserver_modify_codec_encryption_mode` | Admin | Not needed | — | Admin operation | +| `b_virtualserver_modify_temporary_passwords` | Admin | Not needed | — | Admin operation | +| `b_virtualserver_modify_temporary_passwords_own` | Admin | Not needed | — | Admin operation | +| `b_virtualserver_modify_channel_temp_delete_delay_default` | Admin | Not needed | — | Admin operation | +| `b_virtualserver_modify_nickname` | Admin | Not needed | — | Admin operation | +| `b_virtualserver_modify_integrations` | Admin | Not needed | — | Admin operation | + +### 3.3 Channel Permissions + +| Permission Name | Category | Chanora Status | Priority | Notes | +|----------------|----------|----------------|----------|-------| +| `i_channel_min_depth` | Channel | Not needed | — | Server-side only | +| `i_channel_max_depth` | Channel | Not needed | — | Server-side only | +| `b_channel_group_inheritance_end` | Channel | Not needed | — | Server-side only | +| `i_channel_permission_modify_power` | Admin | Not needed | — | Admin operation | +| `i_channel_needed_permission_modify_power` | Admin | Not needed | — | Admin operation | +| `b_channel_info_view` | Read | **Implicit** | P3 | Used by `channelinfo` | +| `b_channel_create_child` | Channel | Not needed | — | Server-side only | +| `b_channel_create_permanent` | Channel | Not needed | — | Server-side only | +| `b_channel_create_semi_permanent` | Channel | Not needed | — | Server-side only | +| `b_channel_create_temporary` | Channel | Not needed | — | Server-side only | +| `b_channel_create_private` | Channel | Not needed | — | Server-side only | +| `b_channel_create_with_topic` | Channel | Not needed | — | Server-side only | +| `b_channel_create_with_description` | Channel | Not needed | — | Server-side only | +| `b_channel_create_with_password` | Channel | Not needed | — | Server-side only | +| `b_channel_create_modify_with_codec_speex8` | Channel | Not needed | — | Server-side only | +| `b_channel_create_modify_with_codec_speex16` | Channel | Not needed | — | Server-side only | +| `b_channel_create_modify_with_codec_speex32` | Channel | Not needed | — | Server-side only | +| `b_channel_create_modify_with_codec_celtmono48` | Channel | Not needed | — | Server-side only | +| `b_channel_create_modify_with_codec_opusvoice` | Channel | Not needed | — | Server-side only | +| `b_channel_create_modify_with_codec_opusmusic` | Channel | Not needed | — | Server-side only | +| `i_channel_create_modify_with_codec_maxquality` | Channel | Not needed | — | Server-side only | +| `i_channel_create_modify_with_codec_latency_factor_min` | Channel | Not needed | — | Server-side only | +| `b_channel_create_with_maxclients` | Channel | Not needed | — | Server-side only | +| `b_channel_create_with_maxfamilyclients` | Channel | Not needed | — | Server-side only | +| `b_channel_create_with_sortorder` | Channel | Not needed | — | Server-side only | +| `b_channel_create_with_default` | Channel | Not needed | — | Server-side only | +| `b_channel_create_with_needed_talk_power` | Channel | Not needed | — | Server-side only | +| `b_channel_create_modify_with_force_password` | Channel | Not needed | — | Server-side only | +| `i_channel_create_modify_with_temp_delete_delay` | Channel | Not needed | — | Server-side only | +| `b_channel_modify_parent` | Channel | Not needed | — | Server-side only | +| `b_channel_modify_make_default` | Channel | Not needed | — | Server-side only | +| `b_channel_modify_make_permanent` | Channel | Not needed | — | Server-side only | +| `b_channel_modify_make_semi_permanent` | Channel | Not needed | — | Server-side only | +| `b_channel_modify_make_temporary` | Channel | Not needed | — | Server-side only | +| `b_channel_modify_name` | Channel | Not needed | — | Server-side only | +| `b_channel_modify_topic` | Channel | Not needed | — | Server-side only | +| `b_channel_modify_description` | Channel | Not needed | — | Server-side only | +| `b_channel_modify_password` | Channel | Not needed | — | Server-side only | +| `b_channel_modify_codec` | Channel | Not needed | — | Server-side only | +| `b_channel_modify_codec_quality` | Channel | Not needed | — | Server-side only | +| `b_channel_modify_codec_latency_factor` | Channel | Not needed | — | Server-side only | +| `b_channel_modify_maxclients` | Channel | Not needed | — | Server-side only | +| `b_channel_modify_maxfamilyclients` | Channel | Not needed | — | Server-side only | +| `b_channel_modify_sortorder` | Channel | Not needed | — | Server-side only | +| `b_channel_modify_needed_talk_power` | Channel | Not needed | — | Server-side only | +| `i_channel_modify_power` | Channel | Not needed | — | Server-side only | +| `i_channel_needed_modify_power` | Channel | Not needed | — | Server-side only | +| `b_channel_modify_make_codec_encrypted` | Channel | Not needed | — | Server-side only | +| `b_channel_modify_temp_delete_delay` | Channel | Not needed | — | Server-side only | +| `b_channel_delete_permanent` | Channel | Not needed | — | Server-side only | +| `b_channel_delete_semi_permanent` | Channel | Not needed | — | Server-side only | +| `b_channel_delete_temporary` | Channel | Not needed | — | Server-side only | +| `b_channel_delete_flag_force` | Channel | Not needed | — | Server-side only | +| `i_channel_delete_power` | Channel | Not needed | — | Server-side only | +| `i_channel_needed_delete_power` | Channel | Not needed | — | Server-side only | +| `b_channel_join_permanent` | **Join** | **Implicit** | **P1** | Used by `clientmove` | +| `b_channel_join_semi_permanent` | **Join** | **Implicit** | **P1** | Used by `clientmove` | +| `b_channel_join_temporary` | **Join** | **Implicit** | **P1** | Used by `clientmove` | +| `b_channel_join_ignore_password` | **Join** | Not needed | P3 | Rare | +| `b_channel_join_ignore_maxclients` | **Join** | Not needed | P3 | Rare | +| `i_channel_join_power` | **Join** | **Implicit** | **P1** | Server evaluates on join | +| `i_channel_needed_join_power` | **Join** | **Implicit** | **P1** | Server evaluates on join | +| `i_channel_subscribe_power` | Subscribe | **Implicit** | P2 | Used by `channelsubscribe` | +| `i_channel_needed_subscribe_power` | Subscribe | **Implicit** | P2 | Used by `channelsubscribe` | +| `i_channel_description_view_power` | Read | Not needed | P3 | Low priority | +| `i_channel_needed_description_view_power` | Read | Not needed | P3 | Low priority | + +### 3.4 Group Permissions + +| Permission Name | Category | Chanora Status | Priority | Notes | +|----------------|----------|----------------|----------|-------| +| `i_icon_id` | Group | Not needed | — | Server-side only | +| `i_max_icon_filesize` | Group | Not needed | — | Server-side only | +| `b_icon_manage` | Group | Not needed | — | Server-side only | +| `b_group_is_permanent` | Group | Not needed | — | Server-side only | +| `i_group_auto_update_type` | Group | Not needed | — | Server-side only | +| `i_group_auto_update_max_value` | Group | Not needed | — | Server-side only | +| `i_group_sort_id` | Group | Not needed | — | Server-side only | +| `i_group_show_name_in_tree` | Group | Not needed | — | Server-side only | +| `b_virtualserver_servergroup_list` | Group | Not needed | — | ServerQuery only | +| `b_virtualserver_servergroup_permission_list` | Group | Not needed | — | ServerQuery only | +| `b_virtualserver_servergroup_client_list` | Group | Not needed | — | ServerQuery only | +| `b_virtualserver_channelgroup_list` | Group | Not needed | — | ServerQuery only | +| `b_virtualserver_channelgroup_permission_list` | Group | Not needed | — | ServerQuery only | +| `b_virtualserver_channelgroup_client_list` | Group | Not needed | — | ServerQuery only | +| `b_virtualserver_client_permission_list` | Group | Not needed | — | ServerQuery only | +| `b_virtualserver_channel_permission_list` | Group | Not needed | — | ServerQuery only | +| `b_virtualserver_channelclient_permission_list` | Group | Not needed | — | ServerQuery only | +| `b_virtualserver_servergroup_create` | Admin | Not needed | — | Admin operation | +| `b_virtualserver_channelgroup_create` | Admin | Not needed | — | Admin operation | +| `i_group_modify_power` | Admin | Not needed | — | Admin operation | +| `i_group_needed_modify_power` | Admin | Not needed | — | Admin operation | +| `i_group_member_add_power` | Admin | Not needed | — | Admin operation | +| `i_group_needed_member_add_power` | Admin | Not needed | — | Admin operation | +| `i_group_member_remove_power` | Admin | Not needed | — | Admin operation | +| `i_group_needed_member_remove_power` | Admin | Not needed | — | Admin operation | +| `i_permission_modify_power` | Admin | Not needed | — | Admin operation | +| `b_permission_modify_power_ignore` | Admin | Not needed | — | Admin operation | +| `b_virtualserver_servergroup_delete` | Admin | Not needed | — | Admin operation | +| `b_virtualserver_channelgroup_delete` | Admin | Not needed | — | Admin operation | + +### 3.5 Client Permissions + +| Permission Name | Category | Chanora Status | Priority | Notes | +|----------------|----------|----------------|----------|-------| +| `i_client_permission_modify_power` | Admin | Not needed | — | Admin operation | +| `i_client_needed_permission_modify_power` | Admin | Not needed | — | Admin operation | +| `i_client_max_clones_uid` | Connect | Not needed | — | Server-side only | +| `i_client_max_idletime` | Client | Not needed | P3 | Could display idle timeout | +| `i_client_max_avatar_filesize` | Client | Not needed | P3 | Could limit avatar upload | +| `i_client_max_channel_subscriptions` | Client | Not needed | P3 | Could limit subscriptions | +| `b_client_is_priority_speaker` | **Voice** | **Implicit** | **P1** | Tracked in `Client.is_priority_speaker` | +| `b_client_skip_channelgroup_permissions` | Client | Not needed | — | Server-side only | +| `b_client_force_push_to_talk` | **Voice** | Not needed | P2 | Could force PTT mode | +| `b_client_ignore_bans` | Client | Not needed | — | Server-side only | +| `b_client_ignore_antiflood` | Client | Not needed | — | Server-side only | +| `b_client_issue_client_query_command` | Query | Not needed | — | ServerQuery only | +| `b_client_use_reserved_slot` | Connect | Not needed | P3 | Could show slot availability | +| `b_client_use_channel_commander` | **Voice** | Not needed | P2 | Channel commander feature | +| `b_client_request_talker` | **Voice** | **Implicit** | **P1** | `client_talk_request` in events | +| `b_client_avatar_delete_other` | Client | Not needed | — | Server-side only | +| `b_client_is_sticky` | Client | Not needed | P3 | Could show sticky indicator | +| `b_client_ignore_sticky` | Client | Not needed | P3 | Could show sticky indicator | +| `b_client_info_view` | **Read** | **Implicit** | **P1** | Used by `clientinfo` | +| `b_client_permissionoverview_view` | Read | Not needed | — | ServerQuery only | +| `b_client_permissionoverview_own` | Read | Not needed | — | ServerQuery only | +| `b_client_remoteaddress_view` | **Read** | **Implicit** | **P2** | Gated in `BridgeClientProfile.client_address` | +| `i_client_serverquery_view_power` | Read | Not needed | P3 | Could gate query client visibility | +| `i_client_needed_serverquery_view_power` | Read | Not needed | P3 | Could gate query client visibility | +| `b_client_custom_info_view` | Read | Not needed | P3 | Custom fields | +| `i_client_kick_from_server_power` | **Moderation** | Not needed | **P1** | Future: kick UI | +| `i_client_needed_kick_from_server_power` | **Moderation** | Not needed | **P1** | Future: kick UI | +| `i_client_kick_from_channel_power` | **Moderation** | Not needed | **P1** | Future: kick UI | +| `i_client_needed_kick_from_channel_power` | **Moderation** | Not needed | **P1** | Future: kick UI | +| `i_client_ban_power` | **Moderation** | Not needed | **P1** | Future: ban UI | +| `i_client_needed_ban_power` | **Moderation** | Not needed | **P1** | Future: ban UI | +| `i_client_move_power` | **Moderation** | Not needed | **P1** | Future: move UI | +| `i_client_needed_move_power` | **Moderation** | Not needed | **P1** | Future: move UI | +| `i_client_complain_power` | Moderation | Not needed | P2 | Future: complain UI | +| `i_client_needed_complain_power` | Moderation | Not needed | P2 | Future: complain UI | +| `b_client_complain_list` | Moderation | Not needed | P2 | Future: complain UI | +| `b_client_complain_delete_own` | Moderation | Not needed | P2 | Future: complain UI | +| `b_client_complain_delete` | Moderation | Not needed | P2 | Future: complain UI | +| `b_client_ban_list` | Moderation | Not needed | P2 | Future: ban UI | +| `b_client_ban_create` | Moderation | Not needed | P2 | Future: ban UI | +| `b_client_ban_delete_own` | Moderation | Not needed | P2 | Future: ban UI | +| `b_client_ban_delete` | Moderation | Not needed | P2 | Future: ban UI | +| `i_client_ban_max_bantime` | Moderation | Not needed | P2 | Future: ban UI | +| `i_client_private_textmessage_power` | **Chat** | Not needed | **P1** | Could gate DM UI | +| `i_client_needed_private_textmessage_power` | **Chat** | Not needed | **P1** | Could gate DM UI | +| `b_client_server_textmessage_send` | **Chat** | Not needed | **P1** | Could gate server chat | +| `b_client_channel_textmessage_send` | **Chat** | Not needed | **P1** | Could gate channel chat | +| `b_client_offline_textmessage_send` | Chat | Not needed | P2 | Offline messages | +| `i_client_talk_power` | **Voice** | **Implicit** | **P1** | Tracked in `Client.talk_power` | +| `i_client_needed_talk_power` | **Voice** | **Implicit** | **P1** | Compared against channel `needed_talk_power` | +| `i_client_poke_power` | Chat | Not needed | P2 | Could gate poke UI | +| `i_client_needed_poke_power` | Chat | Not needed | P2 | Could gate poke UI | +| `b_client_set_flag_talker` | **Voice** | Not needed | **P1** | Future: grant talk power | +| `i_client_whisper_power` | **Voice** | Not needed | P2 | Whisper feature | +| `i_client_needed_whisper_power` | **Voice** | Not needed | P2 | Whisper feature | +| `b_client_modify_description` | Client | Not needed | P2 | Future: edit description | +| `b_client_modify_own_description` | Client | Not needed | P2 | Future: edit own description | +| `b_client_modify_dbproperties` | Client | Not needed | — | Server-side only | +| `b_client_delete_dbproperties` | Client | Not needed | — | Server-side only | +| `b_client_create_modify_serverquery_login` | Query | Not needed | — | ServerQuery only | + +### 3.6 File Transfer Permissions + +| Permission Name | Category | Chanora Status | Priority | Notes | +|----------------|----------|----------------|----------|-------| +| `b_ft_ignore_password` | File | Not needed | P3 | File browser | +| `b_ft_transfer_list` | File | Not needed | P3 | File browser | +| `i_ft_file_upload_power` | File | Not needed | P3 | File browser | +| `i_ft_needed_file_upload_power` | File | Not needed | P3 | File browser | +| `i_ft_file_download_power` | File | Not needed | P3 | File browser | +| `i_ft_needed_file_download_power` | File | Not needed | P3 | File browser | +| `i_ft_file_delete_power` | File | Not needed | P3 | File browser | +| `i_ft_needed_file_delete_power` | File | Not needed | P3 | File browser | +| `i_ft_file_rename_power` | File | Not needed | P3 | File browser | +| `i_ft_needed_file_rename_power` | File | Not needed | P3 | File browser | +| `i_ft_file_browse_power` | File | Not needed | P3 | File browser | +| `i_ft_needed_file_browse_power` | File | Not needed | P3 | File browser | +| `i_ft_directory_create_power` | File | Not needed | P3 | File browser | +| `i_ft_needed_directory_create_power` | File | Not needed | P3 | File browser | +| `i_ft_quota_mb_download_per_client` | File | Not needed | P3 | File browser | +| `i_ft_quota_mb_upload_per_client` | File | Not needed | P3 | File browser | + +--- + +## 4. Summary: Permissions Chanora Should Track + +### 4.1 Already Handled (Implicit via Protocol) + +These permissions are evaluated server-side; Chanora sends commands and handles rejection: + +| Permission | How Handled | +|-----------|-------------| +| `b_channel_join_*` | `voice_join` → server rejects with error code | +| `i_channel_join_power` / `i_channel_needed_join_power` | Server evaluates; Chanora gets `JoinDenied` | +| `b_client_info_view` | `clientinfo` command; server returns error if denied | +| `b_client_remoteaddress_view` | `client_address` field gated in `BridgeClientProfile` | +| `i_client_talk_power` / `i_client_needed_talk_power` | Tracked in `Client.talk_power`; server enforces | +| `b_client_is_priority_speaker` | Tracked in client state | +| `b_client_request_talker` | Tracked via `client_talk_request` events | + +### 4.2 Missing — Should Add (P1) + +| Permission | Reason | Implementation | +|-----------|--------|----------------| +| `i_client_kick_from_server_power` / `i_client_kick_from_channel_power` | Future kick UI needs to know if user can kick | Add to `BridgeClientProfile` or `PermissionHints` | +| `i_client_ban_power` | Future ban UI | Add to permission hints | +| `i_client_move_power` | Future move UI | Add to permission hints | +| `i_client_private_textmessage_power` | Gate DM input in UI | Add to permission hints | +| `b_client_server_textmessage_send` | Gate server chat input | Add to permission hints | +| `b_client_channel_textmessage_send` | Gate channel chat input | Add to permission hints | +| `b_client_set_flag_talker` | Future "grant talk power" button | Add to permission hints | + +### 4.3 Missing — Nice to Have (P2-P3) + +| Permission | Reason | +|-----------|--------| +| `b_client_force_push_to_talk` | Could force PTT mode in UI | +| `b_client_use_channel_commander` | Channel commander feature | +| `i_client_whisper_power` | Whisper feature | +| `b_client_complain_*` | Complain UI | +| `b_client_ban_*` | Ban management UI | +| `i_ft_*` | File transfer browser permissions | + +--- + +## 5. Recommended Implementation + +### 5.1 Permission Constants Module + +Generate from `Permissions.csv`: + +```rust +// crates/chanora_protocol/src/permissions.rs +// Auto-generated from ReSpeak/tsdeclarations Permissions.csv + +pub const B_CHANNEL_JOIN_PERMANENT: &str = "b_channel_join_permanent"; +pub const B_CHANNEL_JOIN_SEMI_PERMANENT: &str = "b_channel_join_semi_permanent"; +pub const B_CHANNEL_JOIN_TEMPORARY: &str = "b_channel_join_temporary"; +pub const I_CHANNEL_JOIN_POWER: &str = "i_channel_join_power"; +pub const I_CHANNEL_NEEDED_JOIN_POWER: &str = "i_channel_needed_join_power"; +// ... all 253 permissions +``` + +### 5.2 Permission Hints Integration + +Extend the existing `PermissionHints` bitflags (already in `Enums.toml` / ReSpeak §6) to cover the P1 permissions. The server already sends `PermissionHints` in `clientinfo` responses — Chanora just needs to parse and expose them. + +### 5.3 UI Gating + +Add permission-aware UI state to `BridgeEvent` or `BridgeClientProfile`: + +```rust +pub struct BridgePermissionHints { + pub can_kick_server: bool, + pub can_kick_channel: bool, + pub can_ban: bool, + pub can_move: bool, + pub can_send_private_message: bool, + pub can_send_server_message: bool, + pub can_send_channel_message: bool, + pub can_grant_talk_power: bool, +} +``` + +--- + +*Created: 2026-06-11 for TODO-069* diff --git a/docs/references/tsdeclarations-codegen-eval.md b/docs/references/tsdeclarations-codegen-eval.md new file mode 100644 index 0000000..c004095 --- /dev/null +++ b/docs/references/tsdeclarations-codegen-eval.md @@ -0,0 +1,143 @@ +# tsdeclarations Code Generation Evaluation + +**TODO-068** — Evaluate Messages.toml, Book.toml, Enums.toml for code generation feasibility. + +--- + +## 1. What tsdeclarations Provides + +The [ReSpeak/tsdeclarations](https://github.com/ReSpeak/tsdeclarations) repository contains machine-readable protocol data files used for code generation across the ReSpeak ecosystem: + +| File | Purpose | Format | +|------|---------|--------| +| `Messages.toml` | All TS3 client↔server commands and their parameters | TOML structs with typed fields | +| `Book.toml` | State-tracking structures for server entities (Client, Channel, Server, ServerGroup, etc.) | TOML structs with typed fields | +| `Enums.toml` | Protocol enums (Codec, PermissionType, Reason, ChannelType, LicenseType, etc.) | TOML enum definitions | +| `MessagesToBook.toml` | Mappings from incoming commands to Book struct updates | TOML mapping rules | +| `BookToMessages.toml` | Functions to generate outgoing commands from Book state | TOML generation rules | +| `Errors.csv` | All TS3 error codes (hex, name, description) | CSV | +| `Permissions.csv` | All TS3 permission IDs (name, description, numeric ID) | CSV | +| `Versions.csv` | Known client version hashes (1536 entries) | CSV | +| `Badges.csv` | Known badge GUIDs and metadata | CSV | + +### How ReSpeak Uses Them + +The `tsclientlib` workspace consumes these via: + +- **`tsproto-structs`** — build-time code generation from TOML files into Rust structs +- **`tsproto-types`** — basic TS3 types (error codes, versions, UIDs) +- **`ts-bookkeeping`** — state tracking that maps incoming messages to Book struct updates +- **`tsproto-packets`** — command parsing/serialization + +Chanora already depends on `tsproto-structs`, `tsproto-types`, and `ts-bookkeeping` as git dependencies (via `chanora_protocol`). + +--- + +## 2. Current Chanora Usage + +| Component | Source | Status | +|-----------|--------|--------| +| `tsproto-types` | Git dependency (patched fork for P-256 coordinate padding) | Active | +| `tsproto-structs` | Git dependency (rev 04aa2491) | Active | +| `ts_bookkeeping` | Used in `chanora_protocol/src/adapter.rs` for event projection | Active | +| Error codes | Referenced from `Errors.csv` via `tsproto-types` | Active | +| Version hashes | Baked into `adapter.rs` from `Versions.csv` | Active | +| Permissions | **Not used** — no TS3 permission ID mapping exists in Chanora | +| `Messages.toml` | **Not directly used** — Chanora uses `ts_bookkeeping` which consumes it internally | +| `Book.toml` | **Not directly used** — consumed by `ts_bookkeeping` internally | +| `Enums.toml` | **Not directly used** — consumed by `tsproto-structs` internally | + +--- + +## 3. Feasibility Assessment + +### 3.1 Automating Protocol Struct Generation + +**Verdict: Already happening indirectly via tsproto-structs/ts_bookkeeping.** + +Chanora already benefits from the tsdeclarations code generation pipeline through its dependency on `tsproto-structs` and `ts_bookkeeping`. The TOML files are consumed at build time by these upstream crates, producing: + +- Typed command structs (`c2s::Clientinit`, `s2c::Initserver`, etc.) +- Event mapping logic (`Event`, `PropertyId`, `PropertyValue`) +- Book state structures + +Direct consumption of `Messages.toml`/`Book.toml` to generate *Chanora-specific* structs would be **redundant** with the existing `ts_bookkeeping` dependency. + +### 3.2 Generating Chanora-Specific DTOs from Book.toml + +**Verdict: Moderate value, moderate effort.** + +The `Book.toml` defines the canonical shape of tracked entities (Client, Channel, Server, ServerGroup, ChannelGroup). Chanora currently has its own DTO types: + +- `BridgeClient` / `BridgeChannel` / `BridgeSnapshot` (in `chanora_bridge/src/api.rs`) +- `ClientProfile` / `ServerSnapshot` (in `chanora_core`) + +A code-gen step could auto-generate these DTOs from `Book.toml`, ensuring field parity with the protocol. However: + +- Chanora's DTOs intentionally omit many protocol fields (privacy, simplicity) +- The mapping from Book fields to bridge DTOs involves business logic (e.g., `PermissionHints` gating) +- Manual DTOs are easier to evolve independently + +**Recommendation:** Keep manual DTOs. Use `Book.toml` as a *reference* when adding new fields, not as a code-gen source. + +### 3.3 Generating Event Types from Messages.toml + +**Verdict: Low value for Chanora.** + +`ts_bookkeeping` already handles the command→event mapping. Chanora's `SessionEvent` enum is a higher-level abstraction that doesn't map 1:1 to protocol commands. Auto-generating it from `Messages.toml` would require a complex mapping layer that defeats the purpose. + +### 3.4 Error Code and Permission ID Generation + +**Verdict: High value, low effort.** + +The CSV files (`Errors.csv`, `Permissions.csv`) are simple, stable, and directly useful: + +- **Errors**: Chanora already references `Errors.csv` names but hardcodes hex values. A build step could generate a `const` table. +- **Permissions**: No permission ID mapping exists yet (TODO-069). `Permissions.csv` is the canonical source. + +### 3.5 Version Hash Generation + +**Verdict: Already done manually; automation possible but low priority.** + +Version hashes from `Versions.csv` are baked into `adapter.rs` at vendor time. A build step could auto-update them, but the list changes infrequently. + +--- + +## 4. Recommended Approach + +| Priority | Action | Effort | Value | +|----------|--------|--------|-------| +| P1 | Use `Permissions.csv` to generate a Rust permission ID constants module (see TODO-069) | 1–2 days | High | +| P2 | Use `Errors.csv` to generate a typed error code enum with `From` | 0.5 days | Medium | +| P3 | Add a CI check that diffs `tsproto-structs`/`ts_bookkeeping` against upstream tsdeclarations HEAD | 0.5 days | Medium | +| P4 | Keep `Book.toml`/`Messages.toml` as reference documentation only | 0 days | — | + +### What NOT to Do + +- **Do not** fork or vendor the TOML files into Chanora's build pipeline +- **Do not** auto-generate Chanora's bridge DTOs from `Book.toml` +- **Do not** auto-generate `SessionEvent` from `Messages.toml` +- **Do not** maintain a separate TOML parser — let upstream crates handle this + +--- + +## 5. Effort Estimate + +| Task | Estimate | +|------|----------| +| Permission ID constants from `Permissions.csv` | 1–2 days | +| Error code enum from `Errors.csv` | 0.5 days | +| CI upstream diff check | 0.5 days | +| **Total** | **2–3 days** | + +--- + +## 6. Dependencies and Risks + +- **Upstream stability**: `tsdeclarations` is MIT/Apache-2.0 licensed, active (94 commits), and used by `tsclientlib`. Low risk of abandonment. +- **TS5 compatibility**: The files may need updates when TS5 protocol stabilizes (TODO-058 monitors this). +- **Patched fork**: Chanora uses a patched `tsproto-types` fork for P-256 coordinate padding. Any code-gen from upstream must account for this. + +--- + +*Created: 2026-06-11 for TODO-068*