docs: comprehensive codebase analysis and reference documentation

Add full codebase analysis report, issue history, test environment
requirements, external research (TeaSpeak/ReSpeak/YaTQA), and offline
protocol references (ReSpeak ts3protocol, TeaSpeak, YaTQA). Add master
TODO list with 88 items across 11 categories. Add missing LICENSE files.

Branch: docs/codebase-analysis-v2
This commit is contained in:
Edison Jwa
2026-06-11 09:23:10 +09:00
parent 89bbfa1e18
commit 3b13a7edb4
10 changed files with 6173 additions and 0 deletions
+190
View File
@@ -0,0 +1,190 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to the Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by the Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
Copyright 2024-2026 Chanora Contributors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2024-2026 Chanora Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
@@ -0,0 +1,542 @@
# Chanora Codebase Analysis Report
**Date:** 2026-06-11
**Branch:** `docs/codebase-analysis-v2`
**Scope:** Full codebase analysis — functions, tests, documentation, dead code, duplication, architecture, external research
---
## Table of Contents
1. [Executive Summary](#1-executive-summary)
2. [Function Inventory](#2-function-inventory)
3. [Test Coverage](#3-test-coverage)
4. [Documentation Coverage](#4-documentation-coverage)
5. [Dead Code Analysis](#5-dead-code-analysis)
6. [Useless/Redundant Code](#6-uselessredundant-code)
7. [Duplicated Code](#7-duplicated-code)
8. [Document Link Coverage](#8-document-link-coverage)
9. [Git History & Issue Patterns](#9-git-history--issue-patterns)
10. [PR Analysis](#10-pr-analysis)
11. [API Gap Analysis](#11-api-gap-analysis)
12. [Crate Architecture Analysis](#12-crate-architecture-analysis)
13. [Document Staleness Analysis](#13-document-staleness-analysis)
14. [Test Environment Requirements](#14-test-environment-requirements)
15. [External Research](#15-external-research)
16. [Recommendations](#16-recommendations)
---
## 1. Executive Summary
### Key Metrics
| Metric | Value |
|--------|-------|
| **Total Rust public functions** | ~428 |
| **Total Flutter/Dart functions** | ~586 |
| **Rust test count** | 359 |
| **Flutter test count** | 221 |
| **Total test count** | 580 |
| **Overall test coverage** | 75% of modules |
| **Documentation coverage (Rust)** | 30% of functions have doc comments |
| **Documentation coverage (Flutter)** | 58% of classes documented |
| **Dead code items** | ~20 (5 definitely dead, 11 likely dead, 4 conditionally dead) |
| **Duplicated code patterns** | 10 major patterns |
| **Broken doc links** | 6 (all from missing LICENSE files) |
| **Orphaned docs** | 14 files |
| **Stale documents** | 5/8 major docs need updates |
| **PRs analyzed** | 42 (34 merged, 8 closed) |
| **Issues documented in history** | 45 significant issues |
### Critical Findings
1. **iOS audio is the #1 problem area** — 15+ issues, AVAudioSession lifecycle is the most recurring root cause
2. **chanora_audio has 168 public functions but only 24% documented** — largest crate, most complex
3. **chanora_bridge has 0 tests** — the Flutter-Rust boundary is completely untested
4. **53 SysRS requirements (SysRS-258310) lack SysDes allocation** — breaks traceability
5. **Several features exist without requirements** — poke, file transfer, hard-mute, cache
6. **engine.rs is 3,244 lines** — monolithic, needs splitting
7. **main.dart is 2,910 lines** — monolithic, needs splitting
8. **~39 production `unwrap()` calls in engine.rs** — crash risk on poisoned mutex
---
## 2. Function Inventory
### Summary by Component
| Component | Type | Total `pub fn` | Documented | Coverage |
|---|---|---|---|---|
| **chanora_core** | Rust lib | 68 | 65 | 96% |
| **chanora_audio** | Rust crate | 168 | ~40 | 24% |
| **chanora_bridge** | Rust crate | 65 | ~10 | 15% |
| **chanora_protocol** | Rust crate | 35 | 33 | 94% |
| **chanora_state** | Rust crate | 16 | ~8 | 50% |
| **chanora_storage** | Rust crate | 20 | ~12 | 60% |
| **chanora_cache** | Rust crate | 7 | 7 | 100% |
| **chanora_resolver** | Rust crate | 15 | ~8 | 50% |
| **chanora_diagnostics** | Rust crate | 27 | ~15 | 50% |
| **chanora_prefetch** | Rust crate | 7 | 4 | 57% |
| **Flutter app** | Dart | ~586 | ~5 | <1% |
### Potentially Unused Functions
Functions defined but never called from outside their module:
| Crate | Function | File:Line |
|---|---|---|
| chanora_core | `ChanoraSession::protocol_events_snapshot()` | lib.rs:788 |
| chanora_audio | `AudioEngine::capture_active()` | engine.rs:1621 |
| chanora_audio | `AudioEngine::frames_sent()` | engine.rs:1626 |
| chanora_audio | `AudioEngine::frames_received()` | engine.rs:1631 |
| chanora_audio | `HpfProcessor::process_sample()` | dsp/hpf.rs:63 |
| chanora_audio | `CoreMlWorker::reset_state()` | apple_coreml.rs:140 |
| chanora_audio | `PttCapabilityLevel::is_global()` | ptt.rs:72 |
| chanora_bridge | `handle_media_services_reset_with_route()` | api.rs:696 |
| chanora_bridge | `handle_interruption_began()` | api.rs:703 |
| chanora_state | `ServerState::replace_from_snapshot()` | lib.rs:114 |
| chanora_state | `ServerState::channel_count()` | lib.rs:148 |
| chanora_state | `ServerState::client_count()` | lib.rs:153 |
| chanora_storage | `BookmarkStore::upsert_or_add()` | lib.rs:891 |
| chanora_resolver | `normalize_args()` | lib.rs:778 |
| chanora_resolver | `validate_args()` | lib.rs:785 |
---
## 3. Test Coverage
### Summary by Component
| Component | Source Modules | Modules w/ Tests | Coverage % | Test Count |
|---|---|---|---|---|
| **chanora_audio** | 43 | 35 | 81% | 221 |
| **chanora_bridge** | 5 | 0 | **0%** | 0 |
| **chanora_cache** | 1 | 1 | 100% | 7 |
| **chanora_diagnostics** | 1 | 1 | 100% | 19 |
| **chanora_prefetch** | 1 | 1 | 100% | 6 |
| **chanora_protocol** | 4 | 2 | 50% | 23 |
| **chanora_resolver** | 1 | 1 | 100% | 14 |
| **chanora_state** | 2 | 2 | 100% | 27 |
| **chanora_storage** | 1 | 1 | 100% | 15 |
| **chanora_core** | 5 | 4 | 80% | 27 |
| **Flutter (services)** | 24 | 22 | 92% | 124 |
| **Flutter (widgets)** | 25 | 14 | 56% | 97 |
| **TOTAL** | **113** | **85** | **75%** | **580** |
### Critical Untested Areas
| Component | Module | Risk |
|---|---|---|
| **chanora_bridge** | All 5 modules | **High** — FFI boundary, zero tests |
| **Flutter widgets** | `voice_bar`, `voice_settings`, `connect_widgets` | **High** — core UI |
| **chanora_protocol** | `dto` module | **Medium** — serialization bugs |
| **chanora_core** | `events` module | **Medium** — event system |
---
## 4. Documentation Coverage
### Doc Comment Coverage (Rust)
| Crate | Functions | With Doc Comments | Coverage |
|---|---|---|---|
| chanora_core | 68 | 65 | 96% |
| chanora_audio | 168 | ~40 | 24% |
| chanora_bridge | 65 | ~10 | 15% |
| chanora_protocol | 35 | 33 | 94% |
| chanora_cache | 7 | 7 | 100% |
| chanora_state | 16 | ~8 | 50% |
| chanora_storage | 20 | ~12 | 60% |
| chanora_resolver | 15 | ~8 | 50% |
| chanora_diagnostics | 27 | ~15 | 50% |
| chanora_prefetch | 7 | 4 | 57% |
### Missing README Files
| Directory | Status |
|---|---|
| crates/chanora_audio/ | **MISSING** |
| crates/chanora_bridge/ | **MISSING** |
| crates/chanora_cache/ | **MISSING** |
| crates/chanora_diagnostics/ | **MISSING** |
| crates/chanora_prefetch/ | **MISSING** |
| crates/chanora_protocol/ | **MISSING** |
| crates/chanora_state/ | **MISSING** |
| crates/chanora_storage/ | **MISSING** |
| core/chanora_core/ | **MISSING** |
Only `crates/chanora_resolver/README.md` exists.
---
## 5. Dead Code Analysis
### Definitely Dead (safe to remove)
| Item | File:Line | Evidence |
|------|-----------|----------|
| `AudioFrame10ms` struct | frame.rs:21 | Never referenced outside tests |
| `AudioFrame20ms` struct | frame.rs:28 | Never referenced outside tests |
| `AudioFrame10ms::dbfs()` | frame.rs:58 | Never called anywhere |
| `disable_failed_vad_backend()` | audio_processing.rs:216 | Only called in tests |
| `import 'package:share_plus/share_plus.dart'` | main.dart:55 | `Share` class never used |
### Likely Dead (no production callers)
| Item | File:Line |
|------|-----------|
| `AudioEngine::output_muted()` | engine.rs:1707 |
| `AudioEngine::output_gain()` | engine.rs:1720 |
| `AudioEngine::capture_active()` | engine.rs:1621 |
| `AudioEngine::transmit_gate()` | engine.rs:1614 |
| `AudioEngine::set_transmit_active()` | engine.rs:1601 |
| `AudioEngine::android_diagnostics()` | engine.rs:1694 |
| `TransmitModeSelector::gate()` | transmit_selector.rs:253 |
| `TransmitModeSelector::in_channel()` | transmit_selector.rs:198 |
| `TransmitModeSelector::ptt_held()` | transmit_selector.rs:226 |
| `ReleaseTailTimer::cancel()` | release_tail.rs:133 |
| `ReleaseTailTimer::arm()` | release_tail.rs:70 |
### `#[allow(dead_code)]` Annotated Items
| Item | Status |
|------|--------|
| `AudioCommand::RemoveClient` | TODO: "Wire to client disconnect path" |
| `android_render_ring` module | Conditionally dead (non-Android) |
| `audio_event_queue` module | Conditionally dead (non-Android) |
| `capture_accumulator` module | Conditionally dead (non-Android) |
---
## 6. Useless/Redundant Code
### TODO/FIXME/HACK Inventory (12 entries, 14 occurrences)
| File | Line | Content |
|------|------|---------|
| engine.rs | 2348 | TODO: realtime-audio callback concern |
| mobile_voice_backend.rs | 16 | TODO(SDD-117): back-fill IosVoiceUnit |
| audio_event_queue.rs | 27 | TODO: Wire to client disconnect path |
| audio_lifecycle_service.dart | 151,156 | TODO: macosDefaultDeviceChanged (×2) |
| poke_notification_service.dart | 33-168 | TODO(event-sounds) (×10) |
### Risky Code
| Risk | Location | Count |
|------|----------|-------|
| Production `unwrap()` | engine.rs | ~39 |
| `unsafe impl Send/Sync` | Various | 8 |
| `unimplemented!("")` in FRB | frb_generated.rs | 23 |
### Complexity Warnings
| File | Lines | Risk |
|------|-------|------|
| engine.rs | 3,244 | **High** — monolithic audio engine |
| main.dart | 2,910 | **High** — monolithic Flutter entry |
| adapter.rs | 2,504 | Medium |
| api.rs | 2,432 | Medium |
---
## 7. Duplicated Code
### Major Patterns
| # | Pattern | Files | Lines Saved | Priority |
|---|---------|-------|-------------|----------|
| 1 | AudioProcessingConfig 4× construction | 1 Dart | ~50 | High |
| 2 | Audio processing toggle UI duplication | 2 Dart | ~150 | High |
| 3 | `.map_err(format!)` boilerplate | 5 Rust | ~85 closures | Medium |
| 4 | PttCapability event construction | 1 Rust | ~15 | Medium |
| 5 | DnsFailed/ServerRejected error mirroring | 2 Rust | ~20 | Medium |
| 6 | Platform detection scatter | 6 Dart | ~35 checks | Medium |
| 7 | Host normalization `trim().to_lowercase()` | 3 Rust | ~5 sites | Low |
| 8 | `create_dir_all` pattern | 2 Rust | ~3 sites | Low |
| 9 | `Io(String)` error variant | 3 Rust | ~10 | Low |
| 10 | StateEvent ↔ Delta mirror | 1 Rust | ~5 | Low |
---
## 8. Document Link Coverage
| Metric | Value |
|--------|-------|
| Total links checked | 38 |
| Valid links | 32 |
| Broken links | 6 |
| Health rate | 84.2% |
| Orphaned docs | 14 / 65 (21.5%) |
### Broken Links
All 6 broken links stem from missing `LICENSE-APACHE` and `LICENSE-MIT` files at project root.
### Orphaned Documentation (14 files)
Mostly in `docs/superpowers/plans/` and `docs/superpowers/specs/` — not linked from any index document.
---
## 9. Git History & Issue Patterns
### Issue Categories (45 significant issues)
| Category | Count | Severity |
|----------|-------|----------|
| iOS audio (AVAudioSession/VPIO) | 15+ | Most problematic |
| Realtime thread safety (Mutex) | 5+ | Cross-platform |
| Build toolchain (Xcode Archive) | 4+ | CI-blocking |
| Platform-specific build | 5+ | Cross-compilation |
| Flutter framework bugs | 3+ | Workarounds needed |
| Protocol failures | 3+ | Silent failures |
### Key Patterns
1. **iOS AVAudioSession has 7+ interacting configuration dimensions** — each fix reveals the next layer
2. **Realtime audio callbacks must NEVER use `Mutex::lock()`** — always `try_lock()` with silence fallback
3. **Always verify with `xcodebuild archive`** — not just `flutter build`
4. **Every protocol command should surface errors to UI** — fire-and-forget hides failures
---
## 10. PR Analysis
### PR Summary (42 total)
| Type | Count | Merged |
|------|-------|--------|
| Features | 15 | 7 |
| Bug fixes | 15 | 12 |
| Refactoring | 4 | 3 |
| Documentation | 1 | 1 |
| Build/Chore | 4 | 4 |
| Performance | 1 | 1 |
### Most Active Areas
| Area | PR Count |
|------|----------|
| iOS Audio | 10+ |
| macOS Audio | 5 |
| Voice/VAD | 6 |
| Flutter UI | 8 |
| Protocol/State | 5 |
### Development Patterns
- **Self-review via "Oracle" agent** — effective quality gate
- **Local CI mirroring** — GitHub Actions billing broken
- **PR stacking complexity** — need better branch management
- **Follow-up fix pattern** — PRs stay focused
---
## 11. API Gap Analysis
### Requirements with NO or Minimal Implementation
| Requirement | ID | Status |
|---|---|---|
| UI settings persistence | SysRS-143, SRS-087 | **Missing** |
| Per-user mute persistence | SysRS-145, SRS-088 | **Missing** |
| Event replay tool | SysRS-171, SRS-098 | **Missing** |
| Audio loopback test tool | SysRS-073, SRS-083 | **Missing** | SRS-083 covers both loopback and processing test tools |
| Audio processing test tool | SysRS-074, SRS-083 | **Missing** | SRS-083 shared with SysRS-073 |
| Protocol probe tool | SysRS-128, SRS-123 | **Missing** |
| Notification permission | SysRS-166, SRS-109 | **Missing** |
| Recent server management | SysRS-141, SRS-085 | **Partial** |
| Per-user volume persistence | SysRS-144, SRS-088 | **Partial** |
| Input validation | SysRS-157, SRS-094 | **Partial** |
### Missing Bridge Functions
| Capability | Gap |
|---|---|
| `is_hard_muted()` | Missing read for hard-mute state |
| `get_output_gain()` | Missing gain read-back |
| `get_client_volume()` | Missing per-client volume read |
| `connection_state()` | UI must derive from events only |
| `reconnect()` | No manual trigger |
### Hardcoded Implementations
| Location | Issue |
|---|---|
| `adapter.rs:141` | `pick_client_version()` returns Windows version for ALL platforms |
| `api.rs:350-356` | `log_file_path()` Android returns `None` |
| `chanora_storage` | `keyring_load()` on Android returns `Ok(None)` always |
---
## 12. Crate Architecture Analysis
### Current Dependency Graph
```
chanora_bridge
└─ chanora_core
├─ chanora_audio ────── chanora_protocol ───── chanora_resolver
├─ chanora_state ────── chanora_protocol
├─ chanora_storage (standalone)
├─ chanora_cache (standalone)
├─ chanora_diagnostics (standalone)
└─ chanora_prefetch ── chanora_resolver
```
**No circular dependencies.** Max depth: 3 levels.
### Crate Size
| Crate | Source Lines | Files |
|-------|-------------|-------|
| **chanora_audio** | **18,895** | 26 |
| chanora_bridge | 7,579 | 5 |
| chanora_protocol | 3,372 | 4 |
| chanora_core | 2,716 | 5 |
| chanora_state | 1,870 | 2 |
| chanora_resolver | 1,434 | 1 |
| chanora_storage | 1,332 | 1 |
| chanora_diagnostics | 1,118 | 1 |
| chanora_cache | 359 | 1 |
| chanora_prefetch | 312 | 1 |
### chanora_audio Split Recommendation
**Option A — Extract platform backends (recommended):**
| New Crate | Contents | Lines |
|---|---|---|
| `chanora_audio` (core) | engine, frame types, transmit, VAD, DSP, PTT trait | ~8,000 |
| `chanora_audio_android` | android_voice_unit, render_ring, event_queue, Oboe | ~3,200 |
| `chanora_audio_apple` | ios_voice_unit, coreaudio-rs | ~1,400 |
| `chanora_audio_desktop` | cpal, sdl_output, Windows/Linux PTT | ~3,500 |
**Rationale:** Platform backends are 100% cfg-gated. Splitting removes heavy platform dependencies from core.
### Common Code Extraction
**Not justified at this time.** Patterns are too small for a `chanora_common` crate.
---
## 13. Document Staleness Analysis
### Freshness Scores
| Document | Score | Status |
|---|---|---|
| docs/sysrs.md | 8/10 | Mostly current |
| docs/srs.md | 7/10 | Missing newer requirements |
| docs/sysdes.md | 6/10 | Missing 53 SysRS allocations |
| docs/architecture/sdd.md | 5/10 | Missing many modules |
| docs/architecture/sad.md | 5/10 | Missing components |
| docs/verification/verification-master-plan.md | 6/10 | Stale evidence source |
| docs/governance/traceability-matrix.md | 5/10 | SRS ID mismatches |
| docs/implementation-status-2026-05-28.md | 3/10 | 14 days stale |
### Critical Staleness Issues
1. **53 SysRS requirements (SysRS-258310) lack SysDes allocation** — breaks traceability
2. **Multiple features without requirements** — poke, file transfer, hard-mute, cache
3. **SRS numbering mismatches** in traceability matrix
4. **Implementation status 14 days stale** — missing v0.3.0 features
---
## 14. Test Environment Requirements
### Current CI Coverage
| Platform | CI Status |
|----------|-----------|
| Ubuntu (Rust + Flutter) | ✅ Automated |
| macOS (iOS unsigned build) | ✅ Automated |
| Android | ❌ Not in CI |
| Windows | ❌ Not in CI |
| macOS (native) | ❌ Not in CI |
| Linux (non-Ubuntu) | ❌ Not in CI |
### Physical Devices Needed
| Device | Purpose | Est. Cost |
|---|---|---|
| iPhone 14+ | iOS audio, CoreML VAD | $600-800 |
| Android phone (arm64) | Android audio, Oboe | $200-400 |
| Windows PC | Windows PTT, audio | $500-800 |
| Linux PC | GNOME/Wayland, PipeWire | $500-800 |
| Audio peripherals | USB/BT headset testing | $100 |
| **Total** | | **$2,400-4,200** |
### Implementation Roadmap
| Phase | Timeline | Focus |
|-------|----------|-------|
| Foundation | Weeks 1-4 | Android/Windows/macOS CI builds |
| Device Integration | Weeks 5-8 | Physical devices, audio loopback |
| Full Automation | Weeks 9-12 | E2E tests, audio quality, Firebase |
---
## 15. External Research
### TeaSpeak
- **Status:** Effectively unmaintained since ~2022
- **Architecture:** Closed-source server, TypeScript web client, C++ music bot
- **Lesson for Chanora:** Open-source client + formal engineering process is the right approach
- **Market validation:** TeaSpeak's abandonment creates opportunity for Chanora
### ReSpeak
- **Status:** Active, 16 repositories, tsclientlib is the core library
- **Chanora dependency:** Uses `tsclientlib` (forked) for protocol implementation
- **Key repos:** `tsclientlib` (protocol), `tsdeclarations` (protocol spec), `quicklz` (compression)
- **Recommendation:** Continue using tsclientlib, consider upstreaming p256 fix
### yat.qa (YaTQA)
- **What it is:** Windows GUI tool for TeamSpeak 3 ServerQuery management (NOT a testing/QA site)
- **Relevance:** Low — management tool, not testing framework
- **Useful resources:** Unofficial ServerQuery docs, server error codes, permission IDs, anti-flood mechanics
---
## 16. Recommendations
### P0 — Critical (do immediately)
1. **Add `chanora_bridge` tests** — 0/5 modules tested, FFI boundary is highest risk
2. **Replace `Mutex::lock().unwrap()` in engine.rs** — ~39 calls, crash risk
3. **Update implementation-status document** — 14 days stale, primary evidence source
4. **Allocate SysRS-258310 in SysDes** — breaks traceability chain
5. **Fix traceability matrix SRS numbering** — IDs don't match actual SRS
### P1 — High Priority (next sprint)
6. **Add Android/Windows/macOS CI builds** — currently only Ubuntu
7. **Add missing bridge functions**`get_hard_mute()`, `get_connection_state()`, `reconnect()`
8. **Add README files to all 8 crates + core**
9. **Split engine.rs** (3,244 lines) into smaller modules
10. **Add requirements for implemented features** — poke, file transfer, hard-mute, cache
### P2 — Medium Priority
11. **Extract platform backends from chanora_audio** — compile-time benefit
12. **Add doc comments to chanora_audio** (24% → 80% target)
13. **Fix `pick_client_version()` hardcoded to Windows**
14. **Implement per-user volume/mute persistence**
15. **Add UI settings store**
### P3 — Low Priority
16. **Clean up dead code** (25+ items)
17. **Deduplicate code patterns** (10 major patterns)
18. **Fix broken doc links** (create LICENSE files)
19. **Link orphaned documentation**
20. **Add protocol probe tool**
---
*Generated by codebase analysis agents on 2026-06-11*
+157
View File
@@ -0,0 +1,157 @@
# Issue History Analysis
**Date:** 2026-06-11
**Scope:** All git history, PRs, and issue patterns
---
## 1. Issue Categories
### iOS Audio (15+ issues) — Most Problematic Area
| Commit | Issue | Root Cause | Fix |
|--------|-------|------------|-----|
| #42 (OPEN) | AVAudioSession not activated before connect | Auto-join spawns VPIO before session in playAndRecord mode | Activate session BEFORE rust.connect |
| #41 | iOS Debug builds blocked | Debug.xcconfig missing `-u` flags; verify script checked wrong Mach-O | Mirror Release xcconfig; check correct dylib |
| #38 | Audio session dead after "already in channel" | Server response 0x0302 treated as failure | Keep session active on already-in-channel |
| #33 | App kills other apps' audio while idle | Held `.playAndRecord` from launch | Idle baseline now `.ambient`; escalate during calls |
| #28 | False underrun counters when muted | `peak_i16 == 0` check didn't gate on muted state | Gate underrun on `!muted` |
| #26 | Silero exports stripped in Xcode Archive | `ld -dead_strip` removed unreferenced symbols | `-exported_symbol` whitelist in xcconfigs |
| #10 | Voice join stuck at "Connecting" | Audio startup blocking connect critical path | Move audio startup off connect path |
**Pattern:** iOS AVAudioSession has 7+ interacting configuration dimensions. Each fix reveals the next layer.
### Realtime Thread Safety (5+ issues)
| Commit | Issue | Root Cause | Fix |
|--------|-------|------------|-----|
| #20 | Android audio output stutter | Mutex contention in audio callback | Oboe config tuning + lock-free callback |
| #27 | macOS audio event queue | Lock contention in render path | Lock-free ArrayQueue pattern |
| engine.rs:39 | ~39 `unwrap()` calls on Mutex | Poisoned mutex will panic engine | Need `try_lock()` or `parking_lot::Mutex` |
**Pattern:** Realtime audio callbacks must NEVER use `Mutex::lock()` — always `try_lock()` with silence fallback.
### Build Toolchain (4+ issues)
| Commit | Issue | Root Cause | Fix |
|--------|-------|------------|-----|
| #41 | iOS Debug builds fail | Debug.xcconfig diverged from Release | Mirror Release settings in Debug |
| #26 | Silero exports stripped | `ld -dead_strip` + install-time `strip` | `-exported_symbol` whitelist + `STRIP_STYLE = non-global` |
| #37 | MSVC CRT mismatch | cmake linking wrong CRT | `cmake-msvc-release-crt.cmd` |
**Pattern:** Always verify with `xcodebuild archive`, not just `flutter build`.
### Protocol Issues (3+ issues)
| Commit | Issue | Root Cause | Fix |
|--------|-------|------------|-----|
| #16 | Speaking state incorrect for non-self clients | Client profiles not refreshed before mapping | Refresh non-self profiles |
| #16 | Server-query clients missing | Missing protocol DTO fields | Add ping deviation through full stack |
| #5 | UI crashes on unexpected state transitions | Missing null/mounted guards | Guard deferred side effects |
**Pattern:** Every protocol command should surface errors to UI — fire-and-forget hides failures.
---
## 2. PR Development Patterns
### PR Summary (42 total, 34 merged, 8 closed)
| Type | Count | Merged |
|------|-------|--------|
| Features | 14 | 10 |
| Bug fixes | 12 | 12 |
| Refactoring | 4 | 3 |
| Documentation | 1 | 1 |
| Build/Chore | 4 | 4 |
| Performance | 1 | 1 |
| Dependency | 1 | 0 |
| Closed (superseded) | 5 | 0 |
### Most Active Areas
| Area | PR Count | Notes |
|------|----------|-------|
| iOS Audio | 10+ | Most recurring issues |
| macOS Audio | 5 | Lock-free architecture |
| Voice/VAD | 6 | CoreML, ONNX, WebRTC |
| Flutter UI | 8 | Event-driven, responsive |
| Protocol/State | 5 | State reducers, events |
### Quality Patterns
1. **Self-review via "Oracle" agent** — catches real issues pre-merge
2. **Local CI mirroring** — GitHub Actions billing broken
3. **PR stacking** — need better branch management workflow
4. **Follow-up fix pattern** — PRs stay focused
---
## 3. Test Cases for Known Issues
### iOS Audio Session Lifecycle
```dart
// Test: Session activates before connect
test('voice_join activates AVAudioSession before starting voice', () async {
// Verify session state transitions: ambient → playAndRecord → ambient
});
// Test: Already-in-channel response keeps session active
test('voice_join keeps session active on already-in-channel response', () async {
// Mock server response code 0x0302
// Verify session remains in playAndRecord state
});
// Test: Idle app doesn't kill other audio
test('app uses ambient mode when not in voice channel', () async {
// Verify session mode is .ambient + .mixWithOthers when idle
});
```
### Realtime Thread Safety
```rust
// Test: Audio callback doesn't panic on poisoned mutex
#[test]
fn audio_callback_survives_poisoned_mutex() {
// Verify try_lock fallback produces silence, not panic
}
```
### Protocol Error Surfacing
```dart
// Test: Server errors surface to UI
test('server error messages are forwarded as UI events', () async {
// Mock protocol error
// Verify UI receives error event
});
```
### Build Verification
```bash
# Test: iOS Debug build succeeds
xcodebuild -workspace ios/Runner.xcworkspace -scheme Runner -configuration Debug build
# Test: iOS Archive build preserves Silero exports
xcodebuild archive -workspace ios/Runner.xcworkspace -scheme Runner
# Verify: nm -g archive.xcarchive/Products/Applications/Chanora.app/Chanora | grep silero
```
---
## 4. Root Cause Patterns
| Pattern | Frequency | Prevention |
|---------|-----------|------------|
| iOS AVAudioSession lifecycle | 8+ PRs | Document state machine, add integration tests |
| Mutex on realtime threads | 5+ issues | Use `try_lock()` or `parking_lot::Mutex` |
| Xcode Archive vs build divergence | 4+ issues | Always test with `xcodebuild archive` |
| Silent protocol failures | 3+ issues | Surface all errors to UI |
| Platform-specific build quirks | 5+ issues | CI on all target platforms |
---
*Generated by git history analysis agents on 2026-06-11*
@@ -0,0 +1,692 @@
# Master TODO List
**Date:** 2026-06-11
**Branch:** `docs/codebase-analysis-v2`
**Sources:**
- `docs/governance/codebase-analysis-2026-06-11.md` — main codebase analysis
- `docs/governance/issue-history-analysis.md` — git history patterns and root causes
- `docs/verification/test-environment-requirements.md` — test environment setup needs
- `docs/references/external-research-2026-06-11.md` — external research findings
---
## Summary
| Category | P0 | P1 | P2 | P3 | Total |
|---|---|---|---|---|---|
| Dead Code Removal | 0 | 0 | 0 | 5 | 5 |
| Code Quality | 2 | 2 | 3 | 2 | 9 |
| Test Coverage | 2 | 3 | 2 | 0 | 7 |
| Architecture | 0 | 2 | 2 | 1 | 5 |
| Documentation | 3 | 2 | 3 | 2 | 10 |
| Missing APIs / Requirements | 0 | 2 | 7 | 2 | 11 |
| Infrastructure | 0 | 3 | 5 | 1 | 9 |
| External Research Follow-up | 0 | 1 | 2 | 2 | 5 |
| Protocol Implementation | 0 | 2 | 8 | 3 | 13 |
| Reference Document Improvements | 0 | 0 | 9 | 1 | 10 |
| Additional Traceability Gaps | 0 | 0 | 3 | 1 | 4 |
| **Total** | **7** | **17** | **44** | **20** | **88** |
---
## 1. Dead Code Removal
### TODO-001 — Remove dead AudioFrame structs
- **Priority:** P3
- **Source:** codebase-analysis §5
- **Description:** `AudioFrame10ms` and `AudioFrame20ms` structs and `AudioFrame10ms::dbfs()` are never referenced outside tests. Safe to delete.
- **Effort:** S
- **Dependencies:** None
### TODO-002 — Remove dead `disable_failed_vad_backend()`
- **Priority:** P3
- **Source:** codebase-analysis §5
- **Description:** Function only called in tests. Remove from production code.
- **Effort:** S
- **Dependencies:** None
### TODO-003 — Remove unused `share_plus` import
- **Priority:** P3
- **Source:** codebase-analysis §5
- **Description:** `import 'package:share_plus/share_plus.dart'` in main.dart:55 — `Share` class never used.
- **Effort:** S
- **Dependencies:** None
### TODO-004 — Audit and remove likely-dead functions (16 across 5 crates)
- **Priority:** P3
- **Source:** codebase-analysis §2, §5
- **Description:** 16 functions have no production callers. From §5: 11 AudioEngine/TransmitModeSelector/ReleaseTailTimer methods (output_muted, output_gain, capture_active, transmit_gate, set_transmit_active, android_diagnostics, gate, in_channel, ptt_held, cancel, arm) + `AudioEngine::frames_sent()` and `AudioEngine::frames_received()`. From §2: `ChanoraSession::protocol_events_snapshot()` (chanora_core), `ServerState::replace_from_snapshot()/channel_count()/client_count()` (chanora_state), `BookmarkStore::upsert_or_add()` (chanora_storage), `normalize_args()/validate_args()` (chanora_resolver), `HpfProcessor::process_sample()` (chanora_audio), `CoreMlWorker::reset_state()` (chanora_audio), `PttCapabilityLevel::is_global()` (chanora_audio), `handle_media_services_reset_with_route()/handle_interruption_began()` (chanora_bridge). Confirm with call-graph then remove or wire.
- **Effort:** M
- **Dependencies:** None
### TODO-005 — Decide fate of `#[allow(dead_code)]` items
- **Priority:** P3
- **Source:** codebase-analysis §5
- **Description:** `AudioCommand::RemoveClient` has TODO to wire to client disconnect path. Three Android-only modules are conditionally dead. Decide: wire, remove, or keep annotated.
- **Effort:** M
- **Dependencies:** None
---
## 2. Code Quality
### TODO-006 — Replace ~39 `Mutex::lock().unwrap()` calls in engine.rs
- **Priority:** P0
- **Source:** codebase-analysis §6, issue-history §1 (realtime thread safety)
- **Description:** Production `unwrap()` on Mutex locks will panic on poisoned mutex. Replace with `try_lock()` + silence fallback or `parking_lot::Mutex`.
- **Effort:** L
- **Dependencies:** None
### TODO-007 — Audit 8 `unsafe impl Send/Sync` blocks
- **Priority:** P0
- **Source:** codebase-analysis §6
- **Description:** 8 unsafe Send/Sync impls across various files. Each needs safety proof comment and review.
- **Effort:** M
- **Dependencies:** None
### TODO-008 — Resolve 14 TODO/FIXME/HACK entries in codebase
- **Priority:** P1
- **Source:** codebase-analysis §6
- **Description:** 14 occurrences across engine.rs, mobile_voice_backend.rs, audio_event_queue.rs, audio_lifecycle_service.dart, poke_notification_service.dart. Address or convert to tracked issues.
- **Effort:** L
- **Dependencies:** None
### TODO-009 — Audit 23 `unimplemented!("")` in frb_generated.rs
- **Priority:** P1
- **Source:** codebase-analysis §6
- **Description:** Flutter-Rust Bridge generated stubs contain 23 `unimplemented!("")` calls that will panic at runtime if hit. Audit and implement or guard each one.
- **Effort:** M
- **Dependencies:** None
### TODO-010 — Fix `pick_client_version()` hardcoded to Windows
- **Priority:** P2
- **Source:** codebase-analysis §11
- **Description:** `adapter.rs:141` returns Windows client version for ALL platforms. Must return platform-appropriate version strings.
- **Effort:** S
- **Dependencies:** None
### TODO-011 — Fix Android stubs returning None/Ok(None)
- **Priority:** P2
- **Source:** codebase-analysis §11
- **Description:** `log_file_path()` on Android returns `None` (api.rs:350-356), `keyring_load()` on Android returns `Ok(None)` always. These silently hide functionality gaps.
- **Effort:** S
- **Dependencies:** None
### TODO-012 — Deduplicate AudioProcessingConfig construction (4x)
- **Priority:** P2
- **Source:** codebase-analysis §7
- **Description:** AudioProcessingConfig is constructed identically in 4 places in Dart. Extract to factory or shared config.
- **Effort:** S
- **Dependencies:** None
### TODO-013 — Deduplicate audio processing toggle UI
- **Priority:** P3
- **Source:** codebase-analysis §7
- **Description:** Audio processing toggle UI duplicated across 2 Dart files (~150 lines). Extract shared widget.
- **Effort:** S
- **Dependencies:** None
### TODO-014 — Deduplicate low-priority code patterns (7 patterns)
- **Priority:** P3
- **Source:** codebase-analysis §7
- **Description:** PttCapability event construction (1 Rust, ~15 lines), DnsFailed/ServerRejected error mirroring (2 Rust, ~20 lines), host normalization (3 Rust files), create_dir_all (2 Rust files), Io(String) variant (3 crates), StateEvent/Delta mirror (1 Rust file), platform detection scatter (6 Dart, ~35 checks).
- **Effort:** M
- **Dependencies:** None
---
## 3. Test Coverage
### TODO-015 — Add chanora_bridge tests (0/5 modules tested)
- **Priority:** P0
- **Source:** codebase-analysis §3
- **Description:** The Flutter-Rust FFI boundary has zero tests. This is the highest-risk untested area. Need unit tests for all 5 bridge modules.
- **Effort:** XL
- **Dependencies:** None
### TODO-016 — Add poisoned-mutex survival test for audio callbacks
- **Priority:** P0
- **Source:** issue-history §3
- **Description:** Verify `try_lock()` fallback produces silence rather than panic when mutex is poisoned. Directly tests the fix for TODO-006.
- **Effort:** M
- **Dependencies:** TODO-006
### TODO-017 — Add Flutter widget tests for untested core UI
- **Priority:** P1
- **Source:** codebase-analysis §3
- **Description:** `voice_bar`, `voice_settings`, `connect_widgets` modules have no tests. These are core UI components at 56% widget coverage.
- **Effort:** L
- **Dependencies:** None
### TODO-018 — Add chanora_protocol dto module tests
- **Priority:** P1
- **Source:** codebase-analysis §3
- **Description:** Protocol dto module is untested. Serialization bugs here cause silent protocol failures.
- **Effort:** M
- **Dependencies:** None
### TODO-019 — Add chanora_core events module tests
- **Priority:** P1
- **Source:** codebase-analysis §3
- **Description:** Events module is untested (80% coverage overall, but events gap). Event system is central to app behavior.
- **Effort:** M
- **Dependencies:** None
### TODO-020 — Add iOS audio session lifecycle integration tests
- **Priority:** P2
- **Source:** issue-history §3
- **Description:** Test session transitions (ambient → playAndRecord → ambient), already-in-channel response handling, idle audio mode. 15+ historical issues justify this.
- **Effort:** L
- **Dependencies:** TODO-030 (device test infrastructure)
### TODO-021 — Add protocol error surfacing tests
- **Priority:** P2
- **Source:** issue-history §3
- **Description:** Verify server errors are forwarded as UI events, not silently swallowed. Fire-and-forget hides failures.
- **Effort:** M
- **Dependencies:** None
---
## 4. Architecture
### TODO-022 — Split engine.rs (3,244 lines) into smaller modules
- **Priority:** P1
- **Source:** codebase-analysis §6, §12
- **Description:** Monolithic audio engine file. Split into engine core, capture, render, transmit, diagnostics modules.
- **Effort:** L
- **Dependencies:** None
### TODO-023 — Split main.dart (2,910 lines) into smaller modules
- **Priority:** P1
- **Source:** codebase-analysis §6
- **Description:** Monolithic Flutter entry point. Extract into feature-based modules/screens.
- **Effort:** L
- **Dependencies:** None
### TODO-024 — Extract platform backends from chanora_audio into separate crates
- **Priority:** P2
- **Source:** codebase-analysis §12
- **Description:** Split into `chanora_audio` (core ~8K lines), `chanora_audio_android` (~3.2K), `chanora_audio_apple` (~1.4K), `chanora_audio_desktop` (~3.5K). Platform backends are already cfg-gated.
- **Effort:** XL
- **Dependencies:** TODO-022 (split engine.rs first)
### TODO-025 — Reduce `.map_err(format!)` boilerplate across 5 Rust crates
- **Priority:** P2
- **Source:** codebase-analysis §7
- **Description:** ~85 repeated closure patterns. Introduce a `WrapErr` trait or macro to reduce boilerplate.
- **Effort:** L
- **Dependencies:** None
### TODO-026 — Reduce adapter.rs (2,504 lines) and api.rs (2,432 lines)
- **Priority:** P3
- **Source:** codebase-analysis §6
- **Description:** Both files exceed 2,400 lines. Consider splitting by feature area.
- **Effort:** L
- **Dependencies:** TODO-022, TODO-023
---
## 5. Documentation
### TODO-027 — Update implementation-status document
- **Priority:** P0
- **Source:** codebase-analysis §13
- **Description:** `docs/implementation-status-2026-05-28.md` is 14 days stale, missing v0.3.0 features. This is the primary evidence source for verification.
- **Effort:** M
- **Dependencies:** None
### TODO-028 — Allocate SysRS-258310 in SysDes
- **Priority:** P0
- **Source:** codebase-analysis §13
- **Description:** 53 SysRS requirements lack SysDes allocation, breaking the traceability chain from requirements to design.
- **Effort:** L
- **Dependencies:** None
### TODO-029 — Fix traceability matrix SRS numbering mismatches
- **Priority:** P0
- **Source:** codebase-analysis §13
- **Description:** SRS IDs in traceability matrix don't match actual SRS document. Needs manual reconciliation.
- **Effort:** M
- **Dependencies:** None
### TODO-030 — Add README files to 8 crates + core
- **Priority:** P1
- **Source:** codebase-analysis §4
- **Description:** Only `chanora_resolver` has a README. The other 9 directories need one describing purpose, architecture, and public API.
- **Effort:** M
- **Dependencies:** None
### TODO-031 — Improve chanora_audio doc comments (24% → 80%)
- **Priority:** P2
- **Source:** codebase-analysis §4
- **Description:** Largest crate (168 pub fn, 18,895 lines) at only 24% documentation. Target 80% coverage.
- **Effort:** XL
- **Dependencies:** None
### TODO-032 — Fix 6 broken doc links (create LICENSE files)
- **Priority:** P3
- **Source:** codebase-analysis §8
- **Description:** All 6 broken links point to missing `LICENSE-APACHE` and `LICENSE-MIT` files at project root. LICENSE files have been created — verify links resolve.
- **Effort:** S
- **Dependencies:** None
### TODO-033 — Link 14 orphaned documentation files
- **Priority:** P3
- **Source:** codebase-analysis §8
- **Description:** 14 files in `docs/superpowers/plans/` and `docs/superpowers/specs/` are not linked from any index document.
- **Effort:** S
- **Dependencies:** None
### TODO-034 — Update SDD (docs/architecture/sdd.md)
- **Priority:** P2
- **Source:** codebase-analysis §13
- **Description:** Software Design Description scored 5/10 freshness. Missing many modules added since initial write.
- **Effort:** L
- **Dependencies:** None
### TODO-035 — Update SAD (docs/architecture/sad.md)
- **Priority:** P2
- **Source:** codebase-analysis §13
- **Description:** Software Architecture Description scored 5/10 freshness. Missing components and interfaces.
- **Effort:** L
- **Dependencies:** None
### TODO-036 — Update Verification Master Plan
- **Priority:** P1
- **Source:** codebase-analysis §13
- **Description:** Verification Master Plan scored 6/10, stale evidence sources and missing verification methods.
- **Effort:** M
- **Dependencies:** None
---
## 6. Missing APIs / Requirements
### TODO-037 — Add missing bridge read-back functions
- **Priority:** P1
- **Source:** codebase-analysis §11
- **Description:** `is_hard_muted()`, `get_output_gain()`, `get_client_volume()`, `connection_state()`, `reconnect()` are missing from bridge. UI must derive state from events only.
- **Effort:** M
- **Dependencies:** None
### TODO-038 — Write requirements for implemented features
- **Priority:** P1
- **Source:** codebase-analysis §13
- **Description:** Poke, file transfer, hard-mute, and cache features exist in code but have no SysRS/SRS requirements. Breaks traceability.
- **Effort:** L
- **Dependencies:** None
### TODO-039 — Implement UI settings persistence (SysRS-143, SRS-087)
- **Priority:** P2
- **Source:** codebase-analysis §11
- **Description:** Settings persistence is a documented requirement with no implementation.
- **Effort:** M
- **Dependencies:** None
### TODO-040 — Implement per-user mute/volume persistence (SysRS-145/144, SRS-088)
- **Priority:** P2
- **Source:** codebase-analysis §11
- **Description:** Per-user mute and volume persistence requirements are partially implemented. Needs completion.
- **Effort:** M
- **Dependencies:** None
### TODO-041 — Implement notification permission handling (SysRS-166, SRS-109)
- **Priority:** P2
- **Source:** codebase-analysis §11
- **Description:** Notification permission requirement has no implementation.
- **Effort:** M
- **Dependencies:** None
### TODO-042 — Complete recent server management (SysRS-141, SRS-085)
- **Priority:** P2
- **Source:** codebase-analysis §11
- **Description:** Recent server management is partially implemented. Needs completion per spec.
- **Effort:** M
- **Dependencies:** None
### TODO-043 — Implement event replay tool (SysRS-171, SRS-098)
- **Priority:** P2
- **Source:** codebase-analysis §11
- **Description:** Event replay tool is a documented requirement with no implementation.
- **Effort:** L
- **Dependencies:** None
### TODO-044 — Implement audio processing test tool (SysRS-074, SRS-083)
- **Priority:** P2
- **Source:** codebase-analysis §11
- **Description:** Audio processing test tool is a documented requirement with no implementation.
- **Effort:** L
- **Dependencies:** None
### TODO-045 — Complete input validation (SysRS-157, SRS-094)
- **Priority:** P2
- **Source:** codebase-analysis §11
- **Description:** Input validation is partially implemented. Needs completion per spec.
- **Effort:** M
- **Dependencies:** None
### TODO-046 — Implement audio loopback test tool (SysRS-073, SRS-083)
- **Priority:** P3
- **Source:** codebase-analysis §11
- **Description:** Audio loopback test tool is a documented requirement with no implementation.
- **Effort:** L
- **Dependencies:** TODO-054 (audio loopback harness)
### TODO-047 — Implement protocol probe tool (SysRS-128, SRS-123)
- **Priority:** P3
- **Source:** codebase-analysis §11
- **Description:** Protocol probe tool is a documented requirement with no implementation.
- **Effort:** L
- **Dependencies:** None
---
## 7. Infrastructure
### TODO-048 — Add Android CI build job
- **Priority:** P1
- **Source:** test-environment-requirements §9 Phase 1
- **Description:** No Android CI build exists. Add NDK + cargo-ndk + multi-ABI build to GitHub Actions.
- **Effort:** M
- **Dependencies:** None
### TODO-049 — Add Windows and macOS CI build jobs
- **Priority:** P1
- **Source:** test-environment-requirements §9 Phase 1
- **Description:** Windows and macOS builds are not in CI. Add windows-latest and macOS runners for build verification.
- **Effort:** M
- **Dependencies:** None
### TODO-050 — Add xcodebuild Archive verification to CI
- **Priority:** P1
- **Source:** issue-history §1
- **Description:** 4+ historical issues caused by `flutter build` passing but `xcodebuild archive` failing. Add xcodebuild archive step to CI.
- **Effort:** M
- **Dependencies:** None
### TODO-051 — Enable clippy as blocking CI check
- **Priority:** P2
- **Source:** test-environment-requirements §9 Phase 1
- **Description:** Clippy is currently advisory only. Make it a blocking PR gate.
- **Effort:** S
- **Dependencies:** None
### TODO-052 — Add Linux multi-distro build matrix
- **Priority:** P2
- **Source:** test-environment-requirements §9 Phase 1
- **Description:** Add Docker-based CI matrix for Ubuntu, Fedora, Arch to catch distro-specific PipeWire/Portal/DBus issues.
- **Effort:** M
- **Dependencies:** None
### TODO-053 — Add `cargo llvm-cov` coverage reporting
- **Priority:** P2
- **Source:** test-environment-requirements §9 Phase 1
- **Description:** No code coverage reporting exists. Add `cargo llvm-cov` to CI for trend tracking.
- **Effort:** M
- **Dependencies:** None
### TODO-054 — Implement audio loopback test harness
- **Priority:** P2
- **Source:** test-environment-requirements §9 Phase 2
- **Description:** Build virtual audio device loopback for CI audio quality testing. Use BlackHole (macOS), VB-Audio (Windows), snd-aloop (Linux).
- **Effort:** L
- **Dependencies:** TODO-048, TODO-049
### TODO-055 — Implement test environment Phase 2 (device integration)
- **Priority:** P2
- **Source:** test-environment-requirements §9 Phase 2
- **Description:** Set up self-hosted runners for device tests, Flutter integration tests with platform channels, Firebase Test Lab for Android, network condition test suite.
- **Effort:** XL
- **Dependencies:** TODO-048, TODO-049
### TODO-056 — Implement test environment Phase 3 (full automation)
- **Priority:** P3
- **Source:** test-environment-requirements §9 Phase 3
- **Description:** Benchmark regression gates, iOS TestFlight automation, signed build automation, weekly audio quality regression, Android multi-device testing.
- **Effort:** XL
- **Dependencies:** TODO-055
---
## 8. External Research Follow-up
### TODO-057 — Upstream p256 coordinate padding fix to ReSpeak
- **Priority:** P1
- **Source:** external-research §2 (ReSpeak)
- **Description:** Chanora forks `tsclientlib` for a p256 fix. Submit PR upstream to reduce fork maintenance burden.
- **Effort:** M
- **Dependencies:** None
### TODO-058 — Monitor tsdeclarations for TS5 protocol updates
- **Priority:** P2
- **Source:** external-research §2 (ReSpeak)
- **Description:** No full TS5 client protocol exists yet. Watch `tsdeclarations` repo for updates that may affect Chanora compatibility.
- **Effort:** S
- **Dependencies:** None (ongoing)
### TODO-059 — Build auto-reconnect logic internally
- **Priority:** P2
- **Source:** external-research §2 (ReSpeak)
- **Description:** tsclientlib explicitly notes auto-reconnect is "not yet there." Chanora must build this independently.
- **Effort:** L
- **Dependencies:** None
### TODO-060 — Extract server error codes from YaTQA for error handling
- **Priority:** P3
- **Source:** external-research §3 (YaTQA)
- **Description:** YaTQA's `/ressourcen/` section has comprehensive unofficial server error codes. Extract for Chanora error handling reference.
- **Effort:** S
- **Dependencies:** None
### TODO-061 — Extract anti-flood/rate-limiting reference from YaTQA
- **Priority:** P3
- **Source:** external-research §3 (YaTQA)
- **Description:** YaTQA documents anti-flood mechanics and rate limiting. Use as reference when implementing Chanora's rate limiting.
- **Effort:** S
- **Dependencies:** None
---
## 9. Protocol Implementation (from Reference Documents)
### TODO-062 — Implement DNS resolution chain (SRV→TSDNS→DNS)
- **Priority:** P1
- **Source:** yatqa-offline-reference §8.5
- **Description:** YaTQA documents the full DNS resolution order: SRV `_ts3._udp` → SRV TSDNS → TSDNS TCP port 41144 → DNS AAAA/A. First successful resolution wins, NO fallback on connection failure. Critical for connection reliability.
- **Effort:** M
- **Dependencies:** None
### TODO-063 — Handle TS character encoding quirks (UTF-8 vs UCS-2 vs CESU-8)
- **Priority:** P1
- **Source:** yatqa-offline-reference §1.3
- **Description:** TS claims UTF-8 but uses UCS-2 (BMP only). Mobile apps use CESU-8. Chanora must handle encoding conversion to avoid display bugs with nicknames, channel names, and messages containing characters outside BMP.
- **Effort:** M
- **Dependencies:** None
### TODO-064 — Implement client-side anti-flood point awareness
- **Priority:** P2
- **Source:** yatqa-offline-reference §5
- **Description:** YaTQA documents complete point costs per action (channelsubscribe=158pts, connect=80pts, etc.). Design Chanora's client-side anti-flood awareness to avoid accidental server bans. Tick-based point reduction model.
- **Effort:** M
- **Dependencies:** None
### TODO-065 — Implement badge fetching and display
- **Priority:** P2
- **Source:** yatqa-offline-reference §8.9, respeak-protocol-reference §5
- **Description:** Badges fetched from `badges-content.teamspeak.com` in Protobuf format, cached locally, refreshed every 24h. Chanora needs badge Protobuf parsing, caching, and UI display.
- **Effort:** L
- **Dependencies:** None
### TODO-066 — Implement TSDNS protocol support
- **Priority:** P2
- **Source:** yatqa-offline-reference §8.4
- **Description:** TSDNS protocol: TCP port 41144, lowercase domain + magic bytes. Required for `ts3server://` URL resolution and server bookmark handling.
- **Effort:** M
- **Dependencies:** TODO-062
### TODO-067 — Implement TS3 file transfer protocol
- **Priority:** P2
- **Source:** yatqa-offline-reference §8.3, external-research §2 (ReSpeak gap)
- **Description:** Raw file transfer: send key from `ftinitupload`/`ftinitdownload` to server IP:port, then raw data. No escaping. ReSpeak has no file transfer implementation — Chanora must build this independently.
- **Effort:** L
- **Dependencies:** None
### TODO-068 — Evaluate tsdeclarations machine-readable files for code generation
- **Priority:** P2
- **Source:** respeak-protocol-reference §9
- **Description:** Messages.toml, Book.toml, Enums.toml, MessagesToBook.toml, BookToMessages.toml could automate protocol struct and event generation. Evaluate feasibility for Chanora's build pipeline.
- **Effort:** M
- **Dependencies:** None
### TODO-069 — Extract Permission IDs into Chanora's permission system
- **Priority:** P2
- **Source:** respeak-protocol-reference §3, yatqa-offline-reference §1.2
- **Description:** Both ReSpeak (tsdeclarations) and YaTQA provide comprehensive permission ID lists with Skip/Negate/Grant logic. Map these to Chanora's permission implementation for full TS3 compatibility.
- **Effort:** L
- **Dependencies:** None
### TODO-070 — Document protocol implementation traps
- **Priority:** P2
- **Source:** yatqa-offline-reference §1.4, §1.5, §3.1
- **Description:** Several implementation traps documented in YaTQA: icon IDs signed/unsigned mismatch, avatar flag is MD5 hash not boolean, channel subscription limited to ONE at a time, line terminator is `0x0A 0x0D` (reversed Windows). Compile into Chanora developer notes.
- **Effort:** S
- **Dependencies:** None
### TODO-071 — Handle IPv6 blacklist canonicalization bug
- **Priority:** P3
- **Source:** yatqa-offline-reference §8.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
### TODO-072 — Establish connection/message performance benchmarks
- **Priority:** P3
- **Source:** respeak-protocol-reference §10
- **Description:** tsclientlib benchmarks: ~199ms connect, ~189µs/message. Use as baseline for Chanora's performance testing.
- **Effort:** S
- **Dependencies:** None
### TODO-073 — Assess web client feasibility
- **Priority:** P3
- **Source:** teaspeak-offline-reference §10, external-research §1
- **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
---
## 10. Reference Document Improvements
### TODO-074 — Fix respeak reference: malformed badge table row
- **Priority:** P2
- **Source:** respeak-protocol-reference review (line 1309)
- **Description:** MIFCOM badge row has 6 columns (5 pipes) but table header has 5 columns. "Entered Performance" is a misplaced column. Fix table formatting.
- **Effort:** S
- **Dependencies:** None
### TODO-075 — Fix respeak reference: section numbering placeholder
- **Priority:** P2
- **Source:** respeak-protocol-reference review (line 764)
- **Description:** Section "4.? Differences between Query and Full Client" has a `?` placeholder. Assign correct section number (4.9 or similar).
- **Effort:** S
- **Dependencies:** None
### TODO-076 — Fix respeak reference: duplicate section numbering
- **Priority:** P2
- **Source:** respeak-protocol-reference review
- **Description:** Both the protocol spec section and reference data sections start at `# 2.`, making "Section 2" ambiguous. Separate into Part I (Protocol) and Part II (Reference Data) or renumber.
- **Effort:** S
- **Dependencies:** None
### TODO-077 — Resolve teaspeak reference: godmode permission contradiction
- **Priority:** P2
- **Source:** teaspeak-offline-reference review (lines 401 vs 414)
- **Description:** `b_virtualserver_select_godmode` listed as active permission in "Other Permissions" table (line 401) AND as "removed" in "Removed Permissions" table (line 414). Resolve: remove from one location or clarify version-based behavior.
- **Effort:** S
- **Dependencies:** None
### TODO-078 — Resolve teaspeak reference: music bot command contradiction
- **Priority:** P2
- **Source:** teaspeak-offline-reference review (lines 499 vs 1229)
- **Description:** Music bot queue commands (`musicbotqueuelist`, `musicbotqueueadd`, etc.) listed in active Music Bot Query Commands table (lines 499-501) AND in "Removed Commands" section (lines 1229-1236). Clarify which version removed them.
- **Effort:** S
- **Dependencies:** None
### TODO-079 — Add Chanora relevance section to teaspeak reference
- **Priority:** P2
- **Source:** teaspeak-offline-reference review
- **Description:** TeaSpeak reference has no section connecting features to Chanora's needs. Add "Relevance to Chanora" section mapping TeaSpeak features to Chanora SRS requirements and identifying protocol divergence points.
- **Effort:** M
- **Dependencies:** None
### TODO-080 — Backfill YaTQA reference: complete variable parameters tables
- **Priority:** P2
- **Source:** yatqa-offline-reference review
- **Description:** Variable parameters section severely condensed: ~15 of 50+ client vars, ~15 of 35+ channel vars, ~7 of 70+ server vars. Backfill from `yat.qa/ressourcen/variablen-parameter/`.
- **Effort:** L
- **Dependencies:** None
### TODO-081 — Backfill YaTQA reference: complete anti-flood action table
- **Priority:** P2
- **Source:** yatqa-offline-reference review
- **Description:** Anti-flood section reduced ~80 individual actions to summary tiers. Replace with complete itemized table from `yat.qa/ressourcen/voice-client-anti-flood/`.
- **Effort:** M
- **Dependencies:** None
### TODO-082 — Backfill YaTQA reference: missing error codes and truncated messages
- **Priority:** P2
- **Source:** yatqa-offline-reference review
- **Description:** ~28 error codes missing, several messages truncated (errors 1030, 1035, 522). Add missing codes and fix truncated messages.
- **Effort:** S
- **Dependencies:** None
### TODO-083 — Backfill YaTQA reference: expand ServerQuery notify events
- **Priority:** P2
- **Source:** yatqa-offline-reference review
- **Description:** Missing events: `notifychanneldescriptionchanged`, `notifychannelpasswordchanged`. Most events listed by name only with no field details. Expand with full field lists and behavioral notes.
- **Effort:** M
- **Dependencies:** None
### TODO-084 — Cross-reference YaTQA and ReSpeak error codes
- **Priority:** P3
- **Source:** yatqa-offline-reference review, respeak-protocol-reference review
- **Description:** YaTQA §9 and ReSpeak Errors.csv may have discrepancies. Cross-reference and note differences.
- **Effort:** S
- **Dependencies:** None
---
## 11. Additional Traceability Gaps
### TODO-085 — Add Flutter app documentation
- **Priority:** P2
- **Source:** codebase-analysis §4
- **Description:** Flutter app has <1% documentation coverage (~586 functions, ~5 documented). Add dart doc comments to core services and widgets.
- **Effort:** XL
- **Dependencies:** None
### TODO-086 — Add chanora_bridge doc comments (15% coverage)
- **Priority:** P2
- **Source:** codebase-analysis §4
- **Description:** chanora_bridge has 65 pub fn at 15% documentation. This is the FFI boundary — every function should be documented.
- **Effort:** L
- **Dependencies:** None
### TODO-087 — Track Flutter framework upstream bugs and workarounds
- **Priority:** P2
- **Source:** codebase-analysis §9, issue-history §1
- **Description:** 3+ historical issues required Flutter framework workarounds. Create tracking document for upstream Flutter bugs that affect Chanora and document current workarounds.
- **Effort:** S
- **Dependencies:** None
### TODO-088 — Improve branch management workflow
- **Priority:** P3
- **Source:** codebase-analysis §10, issue-history §2
- **Description:** PR stacking complexity and local CI mirroring noted as development pain points. Evaluate git-worktree or branch management tooling.
- **Effort:** M
- **Dependencies:** None
---
*Generated from codebase analysis on 2026-06-11. 88 items across 11 categories.*
@@ -0,0 +1,268 @@
# External Research: TeaSpeak, ReSpeak, YaTQA
**Date:** 2026-06-11
**Purpose:** Competitive analysis, dependency analysis, protocol documentation research
---
## 1. TeaSpeak
### Overview
| Attribute | Details |
|---|---|
| **Name** | TeaSpeak |
| **Website** | teaspeak.de (currently down, archived) |
| **Repository** | github.com/TeaSpeak/TeaSpeak (issue tracker only) |
| **License** | Mixed: Web Client (MPL-2.0), Server (Proprietary), TeaMusic (Open Source C++) |
| **Status** | **Effectively unmaintained** — TeaWeb archived July 2025, last server release ~2022 |
| **Stars** | 120 (main repo), 49 (TeaWeb), 7 (TeaMusic) |
| **Languages** | TypeScript (84%), SCSS, HTML, WebAssembly (web client); C++ (music bot) |
### Architecture
```
TeaSpeak Server (closed-source binary, Linux x64 only)
├── TeaSpeak Web Client (TypeScript, open source, MPL-2.0)
├── TeaSpeak Native Client (closed-source binary, Win/Linux x64)
└── TeaMusic (C++ music bot, open source)
```
### Feature Comparison
| Feature | TeaSpeak | Chanora |
|---|---|---|
| Voice (Opus) | ✅ | ✅ |
| Text Chat | ✅ (markdown) | ✅ |
| Video/Screen Sharing | ✅ (buggy, VP8) | Not planned |
| Music Bot | ✅ (built-in) | Not in scope |
| Channels | ✅ | ✅ |
| Permissions | ✅ (advanced) | Partial |
| File Transfer | ✅ | ✅ (v0.3.0) |
| Web Client | ✅ | Not in scope |
| Native Client | ✅ (closed source) | ✅ (Flutter + Rust) |
| Cross-platform | Partial (Win/Linux) | ✅ (5 platforms) |
| Push-to-Talk | Unknown | ✅ |
| i18n | ✅ (8 languages) | ✅ |
### Lessons for Chanora
**What to learn:**
- Web client as installation-less option is compelling
- Built-in music bot is popular feature
- Hidden/private channels valued by users
- Markdown in chat is well-received
- Multi-language support is expected
**What to avoid:**
- Closed-source server prevents community maintenance
- Monolithic architecture limits extensibility
- Poor maintenance (abandoned since ~2022)
- Buggy video/screen sharing (multiple open issues)
- No ARM support (frequently requested)
- Mixed tech stack (React + jQuery) creates maintenance burden
### Market Opportunity
TeaSpeak's abandonment creates a clear opportunity for Chanora:
- Users seeking open-source TeamSpeak-compatible clients
- TeaSpeak's feature set validates market need
- Chanora's formal engineering process prevents abandonment
---
## 2. ReSpeak Organization
### Overview
| Attribute | Details |
|---|---|
| **URL** | https://github.com/ReSpeak |
| **Mission** | Reverse-engineering and reimplementing TS3 protocol in Rust |
| **Activity** | 16 public repositories, 11 contributors |
| **Language focus** | Rust (primary), C, C#, Python, Svelte/TypeScript |
| **License** | Apache-2.0 / MIT dual-license |
### Repository Inventory
| Repository | Purpose | Stars | Status |
|---|---|---|---|
| **tsclientlib** | Core TS3 protocol library | 140 | Active |
| **tsdeclarations** | Machine-readable protocol declarations | 94 | Active |
| **TS3Hook** | DLL injection for packet decryption | 70 | Archived |
| **rust-ts3plugin** | Rust bindings for TS3 plugin API | 14 | Active |
| **SimpleBot** | Chat bot with custom reactions | 14 | Maintenance |
| **quicklz** | QuickLZ compression for TS3 protocol | 7 | Stable |
| **tomcrypt-rs** | Rust bindings for libtomcrypt | 6 | Dormant |
| **ts3stats** | User statistics from server logs | 6 | Dormant |
| **t4rust** | T4-like template engine for Rust | 5 | Active |
| **Qint** | Full cross-platform TS3 client (Tauri) | 5 | Active |
| **ts3tts** | Text-to-speech plugin | 3 | Maintenance |
| **TsPressor** | Message compressor | 2 | Dormant |
| **rust-ts3plugin-sys** | FFI bindings for TS3 plugin API | 0 | Active |
| **MahTsIdentity** | Identity management | 0 | Dormant |
| **pyTSon** | Python plugin interface | 0 | Dormant |
| **TsVersionChecker** | Client version verification | 1 | Dormant |
### Key Library: tsclientlib
**Architecture (monorepo):**
| Crate | Purpose |
|---|---|
| `tsclientlib` | High-level client API |
| `tsproto` | Low-level protocol (UDP, encryption, fragmentation) |
| `ts-bookkeeping` | State tracking |
| `tsproto-packets` | Packet parsing |
| `tsproto-structs` | Auto-generated structs |
| `tsproto-types` | Basic types |
**Key capabilities:**
- Full TS3 protocol handshake (Init1 RSA puzzle, ECDH key exchange)
- Encryption: EAX mode (AES-128-CTR + OMAC)
- Compression: QuickLZ level 1
- Packet fragmentation and reassembly
- Voice/Opus audio handling
**Performance:**
- ~199ms connection time (RSA puzzle dominant)
- ~189μs per message send
### Chanora's Dependency on ReSpeak
| Dependency | How Chanora Uses It |
|---|---|
| `tsclientlib` | Protocol adapter (`chanora_protocol`) |
| `tsproto` | Network layer, encryption |
| `tsproto-types` | Basic TS3 types |
| `tsproto-packets` | Packet parsing |
| `tsproto-structs` | Command/event structs |
| `ts-bookkeeping` | Server state tracking |
| `AudioHandler` | Voice decode, jitter buffer |
**Note:** Chanora uses a **fork** (`EdisonJwa/tsclientlib`) for a p256 coordinate padding fix.
### Protocol Documentation
`tsdeclarations/ts3protocol.md` is the most comprehensive open TS3 protocol specification:
1. **Low-level packets:** 9 packet types (Voice, VoiceWhisper, Command, CommandLow, Ping, Pong, Ack, AckLow, Init1)
2. **Encryption:** EAX mode (AES-128-CTR + OMAC)
3. **Compression:** QuickLZ level 1
4. **Handshake:** 5-step Init1 (RSA puzzle), then ECDH key exchange
5. **Voice:** Opus codec at 48kHz, whisper targeting modes
6. **Identity:** EC key pairs (prime256v1), hashcash proof-of-work
### Gaps in ReSpeak
| Gap | Impact on Chanora |
|---|---|
| Server code | Not needed (client only) |
| TS5 protocol | No full TS5 client protocol |
| File transfer | No implementation |
| Auto-reconnect | "Not yet there" in README |
| IPv6 support | Not documented |
| Documentation | Sparse code comments |
### Recommendations
**Continue using:**
- `tsclientlib` as primary protocol dependency
- `tsdeclarations` for protocol understanding
**Consider contributing:**
- p256 coordinate padding fix upstream
- Auto-reconnect logic if implemented
**Build internally:**
- File transfer (no existing implementation)
- Auto-reconnect logic
- TS5 compatibility (monitor `tsdeclarations`)
---
## 3. YaTQA (yat.qa)
### Overview
| Attribute | Details |
|---|---|
| **Name** | YaTQA — Yet Another TeamSpeak³ Query App |
| **URL** | https://yat.qa/ |
| **Author** | Janni "Яedeemer" K. from northern Germany |
| **First release** | June 29, 2011 |
| **Latest version** | v3.9.9b (March 1, 2023) |
| **Language** | Delphi 2009 (~50,000+ lines) |
| **Purpose** | GUI alternative to raw ServerQuery telnet commands |
**Note:** "qa" stands for **Query App**, not "Quality Assurance."
### What It Is
YaTQA is a Windows GUI tool for managing TeamSpeak 3 servers via the ServerQuery interface. It is NOT a testing framework.
### Useful Resources
The `/ressourcen/` section contains valuable unofficial documentation:
| Resource | Value for Chanora |
|---|---|
| Server error codes | Comprehensive error handling reference |
| Permission IDs | Permission feature implementation |
| Client versions | Protocol compatibility reference |
| DNS resolver behavior | Server resolution reference |
| Anti-flood mechanics | Rate limiting design |
| Codec configuration | Audio codec handling reference |
| Snapshot format | Server migration features |
| Voice client anti-flood | Rate limiting implementation |
| Other protocols | File transfer, TSDNS, blacklist, weblist, badges |
### Relevance to Chanora
**Low direct relevance** — management tool, not testing framework.
**What to extract:**
1. Unofficial ServerQuery documentation (mostly German)
2. Server error codes for comprehensive error handling
3. Permission IDs for permission features
4. Anti-flood mechanics for rate limiting design
### Codec Reference
YaTQA documents TeamSpeak's codec configuration:
- Six codecs: Speex 8kHz, Speex 16kHz, Speex 32kHz, CELT 48kHz, Opus Voice, Opus Music
- 11 quality levels per codec (010)
- Latency settings for Speex/CELT (2060ms)
- Opus is VBR (variable bitrate)
---
## 4. Summary: What Chanora Can Learn
### From TeaSpeak
- ✅ Open-source client is the right approach
- ✅ Cross-platform support is expected
- ✅ i18n is important
- ❌ Avoid closed-source components
- ❌ Avoid monolithic architecture
- ❌ Avoid mixed tech stacks
### From ReSpeak
-`tsclientlib` is the right protocol foundation
- ✅ Protocol declarations are valuable reference
- ⚠️ Keep fork in sync with upstream
- ⚠️ Monitor for TS5 protocol updates
- 🔨 Need to build file transfer internally
- 🔨 Need to build auto-reconnect internally
### From YaTQA
- 📚 Unofficial protocol docs are valuable reference
- 📚 Server error codes for error handling
- 📚 Permission IDs for permission features
- 📚 Anti-flood mechanics for rate limiting
- ❌ Not a testing framework — don't try to use it as one
---
*Generated by external research agents on 2026-06-11*
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+746
View File
@@ -0,0 +1,746 @@
# YaTQA Offline Reference — TeamSpeak 3 Protocol Documentation
**Source:** https://yat.qa/ressourcen/ (German pages)
**Author:** Janni "Яedeemer" K.
**Fetched:** 2026-06-11
**Purpose:** Offline reference for Chanora development — protocol details, error codes, undocumented features
> **Note:** The German pages contain significantly more detail than the English pages. This document captures ALL German-only content.
---
## Table of Contents
1. [Definitions and Algorithms](#1-definitions-and-algorithms)
2. [Server Query Comments](#2-server-query-comments)
3. [Server Query Notify](#3-server-query-notify)
4. [Variable Parameters](#4-variable-parameters)
5. [Voice Client Anti-Flood](#5-voice-client-anti-flood)
6. [Security Level (Hashcash)](#6-security-level-hashcash)
7. [Snapshots](#7-snapshots)
8. [Other Protocols](#8-other-protocols)
9. [Server Error Codes](#9-server-error-codes)
10. [Permission IDs](#10-permission-ids)
11. [Client Versions](#11-client-versions)
12. [Badges](#12-badges)
---
## 1. Definitions and Algorithms
### 1.1 Codecs
**Codec bitrates (b_Raw in bytes/s):**
| Codec \ Quality | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| Speex Narrowband (8kHz) | 300 | 500 | 750 | 1000 | 1400 | 1900 | 2300 | 3100 | | | |
| Speex Wideband (16kHz) | 500 | 750 | 1000 | 1250 | 1600 | 2100 | 2600 | 3000 | 3500 | 4300 | 5300 |
| Speex Ultra-wideband (32kHz) | 550 | 950 | 1200 | 1450 | 1850 | 2350 | 2800 | 3200 | 3700 | 4500 | 5500 |
| CELT Mono (48kHz) | | | | | 4000 | 5000 | 6000 | 8000 | 12000 | | |
| Opus Voice | 550 | 1050 | 1550 | 2050 | 2600 | 3100 | 3600 | 4100 | 4650 | 5150 | 5650 |
| Opus Music | 900 | 1800 | 2700 | 3600 | 4500 | 5400 | 6300 | 7200 | 8100 | 9000 | 9900 |
**Key formulas:**
- `b_Official = floor(b_Raw + 45 byte / t)`
- `d = b_Raw * t + 45 byte ≤ d_Max`
- `d_Max ≈ 527 ± 1 byte` (MTU)
- `t_Max(Opus) = 20 ms`
- `t_Max(Speex/CELT) = floor((527±1 - 45) / (b_Raw * 50)) * 20 ms`
**MTU explanation:** 528 bytes (TS-MTU) + 40 bytes (IPv6 header) + 8 bytes (UDP header) = 576 bytes (old modem/ISDN MTU).
**Opus is VBR** — bitrate varies ±250 bytes/s at quality 6. Max deviation needed to reach d_Max is ~144% (never happens in practice).
### 1.2 Permission System
**Permission tiers (evaluated top to bottom, lowest 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 |
**Skip flag:** Skips channel and channel group permissions. Determined by:
1. If client permission set → use its skip flag
2. If no client permission → use effective server group's skip flag
3. If groups with Negate flag → only Negate groups count
4. If multiple groups remain → lowest ID wins
**Negate flag:** If ANY server group has Negate flag set, only groups WITH Negate flag count. Lowest ID among Negate groups wins. Even if non-Negate groups have lower IDs.
**Grant permission:** Tells how much `i_client_permission_modify_power` needed to change a permission. Grant permission name = replace first letter of original permission with `i_needed_permission_modify_power`.
**b_client_skip_channelgroup_permissions:** If set in first two tiers, ALL channel group AND channel permissions are ignored.
### 1.3 Query Connection
**Timeout behavior by version:**
| Versions | Timeout | Paragraph | Space+Enter | Command+Enter |
|---|---|---|---|---|
| 3.2.0 | 10 min | yes | yes | yes |
| 3.3.0-beta1 beta2 | 5 min | no | no | no |
| 3.3.0-beta3 3.3.1-steadyclock | 5 min | no | no* | yes |
| 3.3.1 | 5 min | no | yes | yes |
*Sending just a command keeps client on server forever (exploitable).
**Character encoding:** TeamSpeak claims UTF-8 but actually uses UCS-2 (BMP only). Mobile apps use CESU-8. Server 3.2.0 adds partial SIP support (emoji ranges).
**Line terminator:** `0x0A 0x0D` (Windows format, reversed).
**Max line length:** 9203 bytes (excluding line terminator). Not limited for 12 permission add/remove commands and `serversnapshotdeploy`.
### 1.4 Icons
- Max dimensions: 16×16
- Filename = CRC32 of icon data (same algorithm as PNG/ZIP)
- Cannot be animated
**Data types for icon IDs vary by context:**
| Context | Parameter | Read | Write |
|---|---|---|---|
| *permlist, *addpermsid | permsid=i_icon_id value= | signed | signed |
| clientlist -icon, clientinfo | client_icon_id= | signed | via clientaddperm only |
| serverinfo, serveredit | virtualserver_icon_id= | signed | unsigned |
| channellist -icon, channelinfo | channel_icon_id | signed | unsigned |
### 1.5 Avatars
- Max dimensions: 300×300
- Avatar flag = MD5 hash (not a boolean)
- Stored in channel ID 0
- Filename derived from Global ID (not from avatar flag)
- Algorithm: Base64-decode the Global ID → 20 bytes → display with `[a-p]` instead of `[0-9a-f]`
**Example calculation:**
- UID: `yGRWD2BOWPC6xSROXoi7U8NAljI=`
- Base64 decode → 20 bytes → hex: `C86456...` → filename: `migefg...`
### 1.6 Snapshots
- File starts with SHA1 hash of remaining UTF-8 data (excluding trailing newline)
- Internally runs normal Query commands when deploying
- If `serveradmin` is added to a server group, snapshot may fail on newer servers
### 1.7 Client Cache
- Subfolder names = Base64-encoded Server UID (double-encoded to avoid `/` in filenames)
- Avatars in `cache/clients/`, Icons in `cache/icons/`
- Private chat partners in `chats/clients/` (also Base64-encoded UIDs)
### 1.8 BBCode
- Max stack size: 20
- 10 tags can be active simultaneously
- Self-closing tag `[hr]` doesn't count toward stack but can't be used at 20
**Inline elements:** `[b]`, `[i]`, `[u]`, `[color=X]`, `[url=URL]Text[/url]`, `[url]URL[/url]`
**Block elements** (channel descriptions only): `[hr]`, `[size=X]`, `[img]URL[/img]`, `[left]`, `[center]`, `[right]`, `[list][*]Text[/list]`
**Internal links:**
- `client://{ClientID}/{ClientUID}~{Name}`
- `channelid://{ChannelID}` (0 = server)
- `ts3file://{Serveraddress}?port={Port}&serverUID={UID}&channel={ChannelID}&path={Path}&filename={Filename}&isDir={0|1}&size={Bytes}&fileDateTime={UnixTimestamp}`
- `ts3image://{Filename}?channel={ChannelID}&path={Path}`
**External links:**
- `ts3server://{Serveraddress}?port={Port}&nickname={Nickname}&password={Password}&channel={ChannelName}&cid={ChannelID}&channelpassword={ChannelPassword}&token={Token}&addbookmark={BookmarkName}`
**Colors:** W3C color names + `#123456` + `#123` + `transparent`
**Font sizes (since client 3.0.3):** Measured in points (pt). Legacy HTML sizes `[size=+X]` don't work — `+` prefix resets to default.
---
## 2. Server Query Comments
### 2.1 General
- `login` failure logs you out if already logged in
- `use` with non-existent server returns "server not running" error
- `use` does NOT auto-start stopped servers — must use `-virtual` flag
- `return_code` parameter available on every command
### 2.2 Key Command Issues
**serveredit:** `virtualserver_ask_for_privilegekey` setting gives error 1538 (invalid parameter).
**serversnapshotdeploy:**
- With `use` → overwrites selected server; without → creates new server
- Returns `sid` and `virtualserver_port` when creating new server
- Port not preserved from snapshot when creating new
- `-mapping` flag must come before snapshot data
**servernotifyregister:**
- Undocumented parameter `event=tokenused`
- Invalid `event` values require another parameter, then fail with parameter error
- `id=0` stands for all channels (gives duplicate events)
**sendtextmessage:** `targetmode=2` (channel) and `targetmode=3` (server) don't require `target` parameter.
**clientlist:** Undocumented `-badges` switch exists.
**clientedit:** Only `client_description` and `client_is_talker` can be modified.
**clientdblist:** `duration` is entry count (max 200), not a time duration. `-1` = maximum.
**clientdbfind:**
- Uses SQL `LIKE` matching: `%` = wildcard, `_` = single char
- Backslashes must be doubled
- Undocumented `-details` switch returns: unique_identifier, nickname, lastconnected, totalconnections, lastip
- Limited to 50 results
**clientdbedit:** Only `client_description` can be changed.
**clientgetnamefromuid:** Also returns `cldbid` — better than `clientgetdbidfromuid`.
**clientkick:** Clients to kick must come LAST in parameter list. QueryManual example is wrong.
**clientpoke:** Cannot poke multiple clients simultaneously (despite QueryManual claiming otherwise).
**privilegekeyadd:** `tokencustomset` is a self-parameterized string (spaces between params). Individual idents/values must be escaped before the entire string is escaped. QueryManual example is wrong.
### 2.3 Undocumented Commands
**plugincmd:** Parameters: `name`, `data`, `targetmode` (0-3), `target`. Only works on virtual servers. No longer allowed from Query clients.
**dummy_connectionlost:** Same as `logout` but doesn't fail if not logged in. If on a server, kicks you (connection lost). You remain invisible on instance.
**verifyserverpassword / verifychannelpassword:** Both return "not on a server" if not connected, or "command doesn't exist" if connected. Both non-functional.
**channelcreateprivate:** Returns error 2 (not implemented).
**cmd_custom_unknown_command:** Returns error 256 (command not found) — intentional.
---
## 3. Server Query Notify
### 3.1 Subscription Behavior
- Subscriptions disappear on logout, re-login, or server switch
- Must subscribe individually (no array parameter)
- Can only have ONE channel subscription at a time
- `id=0` = all channels (gives duplicate events)
- Existing subscriptions persist even if permissions revoked
### 3.2 Events
#### notifycliententerview (server + channel)
Fields: cfid, ctid, reasonid, clid, client_unique_identifier, client_nickname, client_input_muted, client_output_muted, client_outputonly_muted, client_input_hardware, client_output_hardware, client_meta_data, client_is_recording, client_database_id, client_channel_group_id, client_servergroups, client_away, client_away_message, client_type, client_flag_avatar, client_talk_power, client_talk_request, client_talk_request_msg, client_description, client_is_talker, client_is_priority_speaker, client_unread_messages, client_nickname_phonetic, client_needed_serverquery_view_power, client_icon_id, client_is_channel_commander, client_country, client_channel_group_inherited_channel_id, client_badges
#### notifyclientleftview (server + channel)
Fields: cfid, ctid, reasonid, invokerid, invokername, invokeruid, reasonmsg, bantime, clid
#### notifyserveredited (server)
Always reasonid=10. Reports new values for: name, codec_encryption_mode, default_server_group, default_channel_group, hostbanner_*, priority_speaker_dimm_modificator, hostbutton_*, name_phonetic, icon_id, hostbanner_mode, channel_temp_delete_delay_default
#### notifychannelchanged, notifychannelmoved, notifychanneledited, notifychannelcreated, notifychanneldeleted (channel)
#### notifyclientmoved (channel)
Fields: ctid, reasonid (0=self, 1=moved), invokerid, invokername, invokeruid, clid
#### notifytextmessage (textserver, textchannel, textprivate)
Fields: targetmode (1=private, 2=channel, 3=server), msg, target (only for private), invokerid, invokername, invokeruid
#### notifytokenused (tokenused — undocumented)
Fields: clid, cldbid, cluid, token, tokencustomset, token1 (group), token2 (0 for server token)
### 3.3 Reason IDs
| ID | Meaning |
|---|---|
| 0 | Self channel change or server join |
| 1 | User or channel moved |
| 3 | Timeout |
| 4 | Channel kick |
| 5 | Server kick |
| 6 | Ban |
| 8 | Voluntary server leave |
| 10 | Server or channel edited |
| 11 | Server shutdown |
---
## 4. Variable Parameters
### 4.1 Client Variables
**Key variables and their availability:**
| Variable | clientlist | clientinfo | notify | clientupdate | clientedit | clientdblist | clientdbinfo |
|---|---|---|---|---|---|---|---|
| cid | ✓ | ✓ | ✓(ctid) | | | | |
| clid | ✓ | ✓ | N/A | | | | |
| client_unique_identifier | ✓(uid) | ✓ | ✓ | ✗ | | ✓ | ✓ |
| client_nickname | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| client_input_muted | ✓(voice) | ✓ | ✓ | ✓(limited) | ✗ | | |
| client_output_muted | ✓(voice) | ✓ | ✓ | ✓(limited) | ✗ | | |
| client_database_id | ✓ | ✓ | ✓ | ✗ | | ✓(cldbid) | ✓ |
| client_servergroups | ✓(groups) | ✓ | ✓ | ✗ | | | |
| client_away | ✓(away) | ✓ | ✓ | ✓ | ✗ | | |
| client_type | ✓ | ✓ | ✓ | ✗ | | | |
| client_flag_avatar | ✓ | ✓ | ✓(modified) | ✗ | ✗ | ✓(limited) | |
| client_description | ✓ | ✓ | ✓ | ✓ | ✓ | ✓(limited) | ✓(limited) |
| client_icon_id | ✓(icon) | ✓ | ✓ | ✗ | ✗ | ✓ | ✓ |
| client_channel_group_id | ✓(groups) | ✓ | ✓ | ✗ | ✗ | | |
| client_channel_group_inherited_channel_id | ✓(groups) | ✓ | ✓ | | | | |
| client_base64HashClientUID | ✓ | ✓(limited) | | | | | |
**Notes:**
- `clientupdate` with `client_input_hardware=0` has 0 flood points (tab switch)
- `client_flag_avatar` is MD5 hash, not a boolean
- `client_badges` format: `overwolf=0:badges=GUID1=GUID2=...`
### 4.2 Channel Variables
**Key variables:**
| Variable | channellist | channelinfo | notify(created/edited/moved) | channeledit | channelcreate |
|---|---|---|---|---|---|
| cid | ✓ | ✓ | ✓ | N/A | |
| pid (parent) | ✓ | ✓ | ✓(cpid) | ✓(cpid) | ✓(cpid) |
| channel_name | ✓ | ✓ | ✓ | ✓ | ✓ |
| channel_codec | ✓(voice) | ✓ | ✓ | ✓ | ✓ |
| channel_codec_quality | ✓(voice) | ✓ | ✓ | ✓ | ✓ |
| channel_maxclients | ✓(limits) | ✓ | ✓ | ✓ | ✓ |
| channel_order | ✓ | ✓ | ✓ | ✓(order) | ✓(order) |
| channel_flag_password | ✓(flags) | ✓ | ✓ | ✓ | ✗ |
| channel_icon_id | ✓(icon) | ✓ | ✓ | ✓(limited) | ✗ |
| channel_needed_talk_power | ✓(voice) | ✓ | ✓ | ✓ | ✓ |
| channel_flag_private | ✓ | ✗ | | | |
| seconds_empty | ✓(secondsempty) | ✓ | ✗ | | |
| total_clients | ✓ | ✗ | ✗ | | |
**Notes:**
- `channel_flag_temporary` doesn't exist at all
- `channel_icon_id` changes via `channeledit` are semi-permanent (lost on restart)
- `channel_password` returns Base64(SHA1(Base64(SHA1(plaintext)) + virtualserver_keypair)) for non-Query clients
### 4.3 Server Variables
**All variables available in serverinfo. Key differences:**
| Variable | serverlist | serverinfo | serverrequestconnectioninfo | serveredit | notifyserveredited |
|---|---|---|---|---|---|
| virtualserver_name | ✓ | ✓ | | ✓ | ✓ |
| virtualserver_maxclients | ✓(limited) | ✓ | | ✓ | |
| virtualserver_port | ✓ | ✓ | | ✓ | |
| virtualserver_autostart | ✓ | ✓ | | ✓ | |
| virtualserver_icon_id | ✓ | ✓ | | ✓ | ✓ |
| virtualserver_total_packetloss_total | ✓ | ✓ | ✓(limited) | | |
| virtualserver_total_ping | ✓ | ✓ | ✓(limited) | | |
---
## 5. Voice Client Anti-Flood
### 5.1 General Rules
- Client starts with 0 points
- Every 0.5 seconds ("tick"): `virtualserver_antiflood_points_tick_reduce` points deducted (min 1)
- If `b_client_ignore_antiflood` → no points accumulated (but existing points still drain)
- Connection = 80 points (respects `b_client_ignore_antiflood`)
- `b_client_ignore_bans` bypasses IP block (but not anti-flood)
- Threshold: `virtualserver_antiflood_points_needed_command_block` blocks at EQUALITY
### 5.2 Flood Points Per Action
**High-cost actions (25 points):**
- `banadd`, `banclient`, `complainadd`, `complaindelall`, `complainlist`
- `channelcreate`, `channeldelete`, `channelmove`, `channeledit`
- `clientmove` (10), `clientkick`, `clientpoke`, `clientedit`
- `servergroupaddclient`, `servergroupdelclient`, `setclientchannelgroup`
- `clientdbdelete`, `clientdbedit`, `clientdbfind` (50!)
- `messageadd`, `messagelist`, `textmessagesend` (15)
- `logview` (50!)
**Medium-cost actions (5-15 points):**
- Most permission operations: 5 points
- Most group operations: 5 points
- File operations: 5 points (except `ftinitupload`/`ftinitdownload` = 0)
- `channelsubscribe`: 158 points!
**Zero-cost actions:**
- `clientdisconnect`, `clientgetvariables`, `clientinit`, `clientinitiv`
- `setwhisperlist`, `ftgetfilelist`, `ftinitupload`, `ftinitdownload`
- `clientmute`/`clientunmute` (0 with specific conditions)
- Internal client operations
### 5.3 Connection Flow
1. `clientinitiv`
2. `clientinit`
3. Set default channel (10 points)
4. Set badges (15 points)
5. `permissionlist` (5 points, if not cached)
6. `clientgetvariables` (0 points)
7. Subscribe channels (15-20 points)
---
## 6. Security Level (Hashcash)
### 6.1 How It Works
- Hashcash variant using SHA1
- Input: Public Key + unsigned 64-bit number (as string)
- Security level = number of leading zeros in 160-bit binary SHA1 hash
- Byte order: Big Endian, Bit order: Little Endian
### 6.2 Growth Rate
- Average 2^k hashes needed to reach level k from level 0
- Doubles for each additional level
**Time estimates (2009, modern CPUs ~4x faster):**
- Level 0-23: seconds
- Level 23-29: minutes
- Level 29-34: hours
- Level 35-39: days
- Level 40-43: months
- Level 44+: years
### 6.3 Optimization
- TeamSpeak uses single-threaded SHA1 (~1 MH/s on i5)
- Hashdog tool: multi-threaded, ~5 MH/s per core (~20-30x faster than TS)
- GPU (Hashcat): ~8.5 GH/s = 850,000% faster than TeamSpeak
- Level 33 on GTX 1080: ~1 second
---
## 7. Snapshots
### 7.1 What's Included
- Virtual server settings (except port) including keypair
- Channels
- Client database
- Permissions for local groups (both types), clients (both types), and channels
- Group assignments
### 7.2 What's NOT Included
- Server port (auto-assigned on deploy)
- Files
- Bans
- Complaints
- Offline messages (but unread count preserved)
### 7.3 Format
```
hash=Base64(SHA1(remaining_data))|snapshot_data
```
**Sections:**
1. `virtualserver_*` settings
2. `end_virtualserver|begin_channels` → channel list (tree order)
3. `end_channels|begin_clients` → client database (creation order)
4. `end_clients|begin_permissions|server_groups` → server group permissions
5. `end_groups|iid=0` → server group memberships (by cldbid, then sgid)
6. `end_relations|channel_groups` → channel group permissions
7. `end_groups|` → channel group memberships
8. `end_relations|client_flat` → client permissions (server level)
9. `end_flat|channel_flat` → channel permissions
10. `end_flat|channel_client_flat` → client-channel permissions
11. `end_flat|end_permissions`
---
## 8. Other Protocols
### 8.1 Protobuf Format
**Two key data types:**
**BigNum (Varint):**
```
if x < 128: write byte x
else: write (x mod 128 OR 128), recurse with x >> 7
```
**Binary data with length prefix:** BigNum length + raw data
**File format:** Pairs of (BigNum identifier, data) until EOF.
- Identifier AND 7 = data type (0=BigNum, 1=64-bit, 2=binary, 5=32-bit)
- Identifier SHR 3 = field number
### 8.2 Update Protocol
- Current: Downloads `ts3-client-2` from `versions.teamspeak.com` (Protobuf format)
- Contains: server version (3.0.10, outdated), stable/beta/alpha client versions
- Updater images: gzip compressed (despite `.compress` extension)
### 8.3 File Transfer
- Send key received from `ftinitupload`/`ftinitdownload` to server IP:port
- No escaping, nothing before/after
- Upload: send key then data
- Download: receive data from server
### 8.4 TSDNS
- Input → lowercase → UTF-8/CESU-8 → append `0x0A 0x0D 0x0D 0x0D 0x0A` → TCP to port 41144
- Returns IP or `404`
- `$PORT` = keep user's port
### 8.5 DNS Resolution Order
1. **SRV TS3:** `_ts3._udp.INPUT` — port overrides user input
2. **SRV TSDNS:** `_tsdns._tcp.DOMAIN`
3. **TSDNS:** Port 41144
4. **DNS:** AAAA, A records (CNAME implicit)
**First complete resolution wins. No fallback on connection failure.**
### 8.6 Blacklist (v1)
- UDP to `blacklist.teamspeak.com:17385`
- Send: `ip4:RESOLVED_IP`
- Response: `x,13371337133` where x = 0 (blacklisted), 1 (OK), 2 (greylisted)
- No response → connect anyway
### 8.7 Blacklist2 (v2, since 3.1.6)
- HTTPS POST to `blacklist2.teamspeak.com/check`
- Content-Type: `application/x-ts3blacklist`
- Protobuf-encoded `BlacklistInfoRequest` with: ip_address, domain_name, virtual_server_id, public_license_id, port, timestamp, valid_token_present, slots_ok
- Response: 8 bytes Protobuf with status_ip, status_domain, status_virtual_server_id, status_public_license_id (1=INVALID, 2=BLACKLISTED, 3=GREYLISTED, 4=NOT_LISTED)
**IPv6 canonicalization bug (3.1.6-3.1.7):** Missing blocks filled with `3030` instead of `0`. Fixed in 3.1.8-beta1.
### 8.8 Weblist (Server)
- UDP to `weblist.teamspeak.com:2010`
- Packet format: 1 byte version (always 1), 2 bytes sequence number, 1 byte type (1=key request, 2=data), payload
- Update cycle: request key → send data (key + port + slots + clients + flags + name)
- Server updates every 10 minutes, retries at 1.3s and 2s intervals
### 8.9 Badges
- Stored as GUIDs on server
- Binary list from `badges-content.teamspeak.com/list` (Protobuf format)
- Cached in `cache/badges`
- Refreshed every 24 hours
**Protobuf structure:**
1. BigNum: revision number
2. BigNum: Unix timestamp
3. For each badge: GUID, name, URL base, description, timestamp, unknown field (1-3)
---
## 9. Server Error Codes
**Complete error code list (from English page):**
| Hex | Dec | Message |
|---|---|---|
| 0x0000 | 0 | ok |
| 0x0001 | 1 | undefined error |
| 0x0002 | 2 | not implemented |
| 0x0100 | 256 | command not found |
| 0x0101 | 257 | unable to bind network port |
| 0x0200 | 512 | invalid clientID |
| 0x0201 | 513 | nickname is already in use |
| 0x0203 | 515 | max clients protocol limit reached |
| 0x0204 | 516 | invalid client type |
| 0x0205 | 517 | already subscribed |
| 0x0206 | 518 | not logged in |
| 0x0207 | 519 | could not validate client identity |
| 0x0208 | 520 | invalid loginname or password |
| 0x0209 | 521 | too many clones already connected |
| 0x020a | 522 | client version outdated |
| 0x020b | 523 | client is online |
| 0x020c | 524 | client is flooding |
| 0x020d | 525 | client is modified |
| 0x020e | 526 | can not verify client at this moment |
| 0x020f | 527 | client is not permitted to log in |
| 0x0210 | 528 | client is not subscribed to the channel |
| 0x0300 | 768 | invalid channelID |
| 0x0301 | 769 | max channels protocol limit reached |
| 0x0302 | 770 | already member of channel |
| 0x0303 | 771 | channel name is already in use |
| 0x0304 | 772 | channel not empty |
| 0x0305 | 773 | can not delete default channel |
| 0x0306 | 774 | default channel requires permanent |
| 0x0307 | 775 | invalid channel flags |
| 0x0308 | 776 | permanent channel can not be child of non permanent channel |
| 0x0309 | 777 | channel maxclient reached |
| 0x030a | 778 | channel maxfamily reached |
| 0x030b | 779 | invalid channel order |
| 0x030c | 780 | channel does not support filetransfers |
| 0x030d | 781 | invalid channel password |
| 0x030e | 782 | channel is private channel |
| 0x030f | 783 | invalid security hash supplied by client |
| 0x0400 | 1024 | invalid serverID |
| 0x0401 | 1025 | server is running |
| 0x0402 | 1026 | server is shutting down |
| 0x0403 | 1027 | server maxclient reached |
| 0x0404 | 1028 | invalid server password |
| 0x0405 | 1029 | deployment active |
| 0x0406 | 1030 | unable to stop own server |
| 0x0407 | 1031 | server is virtual |
| 0x0408 | 1032 | server wrong machineID |
| 0x0409 | 1033 | server is not running |
| 0x040a | 1034 | server is booting up |
| 0x040b | 1035 | server got an invalid status |
| 0x040c | 1036 | server modal quit |
| 0x040d | 1037 | server version is too old for command |
| 0x0410 | 1040 | server blacklisted |
| 0x0500 | 1280 | database error |
| 0x0501 | 1281 | database empty result set |
| 0x0502 | 1282 | database duplicate entry |
| 0x0503 | 1283 | database no modifications |
| 0x0504 | 1284 | database invalid constraint |
| 0x0505 | 1285 | database reinvoke command |
| 0x0600 | 1536 | invalid quote |
| 0x0601 | 1537 | invalid parameter count |
| 0x0602 | 1538 | invalid parameter |
| 0x0603 | 1539 | parameter not found |
| 0x0604 | 1540 | convert error |
| 0x0605 | 1541 | invalid parameter size |
| 0x0606 | 1542 | missing required parameter |
| 0x0607 | 1543 | invalid checksum |
| 0x0700 | 1792 | virtual server got a critical error |
| 0x0701 | 1793 | connection lost |
| 0x0702 | 1794 | not connected |
| 0x0703 | 1795 | no cached connection info |
| 0x0704 | 1796 | currently not possible |
| 0x0705 | 1797 | failed connection initialization |
| 0x0706 | 1798 | could not resolve hostname |
| 0x0707 | 1799 | invalid server connection handler ID |
| 0x0708 | 1800 | could not initialize Input Manager |
| 0x0709 | 1801 | client library not initialized |
| 0x070a | 1802 | server library not initialized |
| 0x070b | 1803 | too many whisper targets |
| 0x070c | 1804 | no whisper targets found |
| 0x0800 | 2048 | invalid file name |
| 0x0801 | 2049 | invalid file permissions |
| 0x0802 | 2050 | file already exists |
| 0x0803 | 2051 | file not found |
| 0x0804 | 2052 | file input/output error |
| 0x0805 | 2053 | invalid file transfer ID |
| 0x0806 | 2054 | invalid file path |
| 0x0807 | 2055 | no files available |
| 0x0808 | 2056 | overwrite excludes resume |
| 0x0809 | 2057 | invalid file size |
| 0x080a | 2058 | file already in use |
| 0x080b | 2059 | could not open file transfer connection |
| 0x080c | 2060 | no space left on device |
| 0x080d | 2061 | file exceeds file system's maximum file size |
| 0x080e | 2062 | file transfer connection timeout |
| 0x080f | 2063 | lost file transfer connection |
| 0x0810 | 2064 | file exceeds supplied file size |
| 0x0811 | 2065 | file transfer complete |
| 0x0812 | 2066 | file transfer canceled |
| 0x0813 | 2067 | file transfer interrupted |
| 0x0814 | 2068 | file transfer server quota exceeded |
| 0x0815 | 2069 | file transfer client quota exceeded |
| 0x0816 | 2070 | file transfer reset |
| 0x0817 | 2071 | file transfer limit reached |
| 0x0900 | 2304 | preprocessor disabled |
| 0x0901 | 2305 | internal preprocessor |
| 0x0902 | 2306 | internal encoder |
| 0x0903 | 2307 | internal playback |
| 0x0904 | 2308 | no capture device available |
| 0x0905 | 2309 | no playback device available |
| 0x0906 | 2310 | could not open capture device |
| 0x0907 | 2311 | could not open playback device |
| 0x090f | 2319 | device still in use |
| 0x0910 | 2320 | device already registered |
| 0x0911 | 2321 | device not registered/known |
| 0x0912 | 2322 | unsupported frequency |
| 0x0913 | 2323 | invalid channel count |
| 0x0a00 | 2560 | invalid group ID |
| 0x0a01 | 2561 | duplicate entry |
| 0x0a02 | 2562 | invalid permission ID |
| 0x0a03 | 2563 | empty result set |
| 0x0a04 | 2564 | access to default group is forbidden |
| 0x0a05 | 2565 | invalid size |
| 0x0a06 | 2566 | invalid value |
| 0x0a07 | 2567 | group is not empty |
| 0x0a08 | 2568 | insufficient client permissions |
| 0x0a09 | 2569 | insufficient group modify power |
| 0x0a0a | 2570 | insufficient permission modify power |
| 0x0a0b | 2571 | template group is currently used |
| 0x0a0c | 2572 | permission error |
| 0x0b00 | 2816 | virtualserver limit reached |
| 0x0b01 | 2817 | max slot limit reached |
| 0x0b02 | 2818 | license file not found |
| 0x0b03 | 2819 | license date not ok |
| 0x0b04 | 2820 | unable to connect to accounting server |
| 0x0b05 | 2821 | unknown accounting error |
| 0x0b06 | 2822 | accounting server error |
| 0x0b07 | 2823 | instance limit reached |
| 0x0b08 | 2824 | instance check error |
| 0x0b09 | 2825 | license file invalid |
| 0x0b0a | 2826 | virtualserver is running elsewhere |
| 0x0b0b | 2827 | virtualserver running in same instance already |
| 0x0b0c | 2828 | virtualserver already started |
| 0x0b0d | 2829 | virtualserver not started |
| 0x0c00 | 3072 | invalid message id |
| 0x0d00 | 3328 | invalid ban id |
| 0x0d01 | 3329 | connection failed, you are banned |
| 0x0d02 | 3330 | rename failed, new name is banned |
| 0x0d03 | 3331 | flood ban |
| 0x0e00 | 3584 | unable to initialize tts |
| 0x0f00 | 3840 | invalid privilege key |
| 0x1000 | 4096 | VoIP pjsua error |
| 0x1100 | 4352 | provisioning invalid password |
| 0x1101 | 4353 | provisioning invalid request |
| 0x1102 | 4354 | no (more) slots available |
| 0x1103 | 4355 | pool missing |
| 0x1104 | 4356 | pool unknown |
| 0x1105 | 4357 | unknown ip location |
| 0x1106 | 4358 | internal error (tries exceeded) |
| 0x1107 | 4359 | too many slots requested |
| 0x1108 | 4360 | too many reserved |
| 0x1109 | 4361 | could not connect to provisioning server |
| 0x1110 | 4368 | authentication server not connected |
| 0x1111 | 4369 | authentication data too large |
| 0x1112 | 4370 | already initialized |
| 0x1113 | 4371 | not initialized |
| 0x1114 | 4372 | already connecting |
| 0x1115 | 4373 | already connected |
| 0x1116 | 4374 | not connected |
| 0x1117 | 4375 | io_error |
| 0x1118 | 4376 | invalid timeout |
| 0x1119 | 4377 | ts3server not found |
| 0x111A | 4378 | unknown permissionID |
---
## 10. Permission IDs
**Source:** https://yat.qa/resources/permission-ids/ (English)
> See ReSpeak/tsdeclarations/Permissions.csv for the complete machine-readable list.
---
## 11. Client Versions
**Source:** https://yat.qa/resources/client-versions/ (English)
> See ReSpeak/tsdeclarations/Versions.csv for the complete machine-readable list with version hashes.
---
## 12. Badges
**Source:** https://yat.qa/ressourcen/abzeichen-badges/ (German)
> See ReSpeak/tsdeclarations/Badges.csv for the complete machine-readable list.
---
*Fetched and compiled on 2026-06-11*
@@ -0,0 +1,243 @@
# Automated Test Environment Requirements
**Date:** 2026-06-11
**Purpose:** Define what's needed for a fully automated test system
---
## 1. Current Test Infrastructure
### What's Automated
| Area | Status |
|---|---|
| Rust unit/integration tests | ✅ CI on Ubuntu |
| Rust static analysis (clippy) | ✅ Advisory |
| Flutter analyze + test | ✅ CI on Ubuntu |
| Supply-chain checks | ✅ CI |
| License inventories | ✅ CI |
| Audio benchmarks | ⚠️ Advisory only |
| iOS unsigned build | ✅ CI on macOS |
### What's Missing
| Gap | Impact |
|---|---|
| Android CI build or test | Android verification blocked |
| iOS device/simulator test | Audio session untested |
| Windows CI | PTT and audio untested |
| macOS CI | Native audio untested |
| Linux CI (non-Ubuntu) | Portal behavior untested |
| Audio quality metrics | No POLQA/PESQ/ViSQOL |
| Network condition simulation | No latency/packet loss testing |
| Integration test with real server | E2E excluded from CI |
| Performance regression gates | Benchmarks advisory only |
---
## 2. Platform Requirements
### iOS / iPadOS
| Requirement | Details |
|---|---|
| Minimum OS | iOS 16+ (CoreML Silero VAD) |
| Hardware | Physical iPhone (A12+), physical iPad |
| Simulator | UI/audio session mock testing |
| Platform features | AVAudioSession, CoreML VAD, haptics, push-to-talk |
### Android
| Requirement | Details |
|---|---|
| Minimum SDK | API 28 (Android 9) |
| Hardware | Physical device (arm64), emulator for CI |
| Platform features | Oboe audio, AudioManager, permissions, foreground service |
### macOS
| Requirement | Details |
|---|---|
| Minimum OS | macOS 13+ (CoreML Silero VAD) |
| Hardware | Apple Silicon Mac (primary), Intel Mac (compatibility) |
| Platform features | CoreAudio VoiceProcessingIO, Event Tap PTT, permissions |
### Windows
| Requirement | Details |
|---|---|
| Minimum OS | Windows 10+ |
| Hardware | Windows PC with audio hardware |
| Platform features | cpal audio, Raw Input PTT, Credential Manager |
### Linux
| Requirement | Details |
|---|---|
| Environment | GNOME on Wayland |
| Hardware | Linux PC with audio hardware |
| Platform features | cpal capture, SDL2 playback, D-Bus GlobalShortcuts |
---
## 3. Physical Devices Needed
| Device | Purpose | Est. Cost |
|---|---|---|
| iPhone 14+ (A15+) | iOS audio, CoreML VAD, PTT | $600-800 |
| iPad (A12+) | iPadOS layout, audio session | $350-500 |
| Android phone (arm64) | Android audio, Oboe | $200-400 |
| Android tablet | Layout testing | $200-300 |
| Apple Silicon Mac | macOS build/test, iOS Simulator | (dev machine) |
| Intel Mac | macOS x86_64 compatibility | $500-800 (used) |
| Windows PC | Windows PTT, audio | $500-800 |
| Linux PC | GNOME/Wayland, PipeWire | $500-800 |
| USB headset | Audio device switching | $30-60 |
| Bluetooth earbuds | Bluetooth audio route | $50-150 |
| **Total** | | **$2,400-4,200** |
---
## 4. Audio Testing Tools
| Tool | Purpose | Cost |
|---|---|---|
| **ViSQOL** (Google, open-source) | Speech quality metric | Free |
| **PESQ / POLQA** | ITU-T speech quality | $500-2000 (license) |
| **Virtual audio devices** | Software loopback for CI | Free (BlackHole, VB-Audio, snd-aloop) |
| **Opus test vectors** | Codec conformance | Free (IETF) |
| **Custom DSP analysis** | THD, SNR, frequency response | Build in-house |
---
## 5. Network Simulation Tools
| Tool | Purpose | Cost |
|---|---|---|
| **tc (traffic control)** | Linux latency/jitter/packet loss | Free |
| **Network Link Conditioner** | Apple's built-in network impairment | Free |
| **clumsy / NetLimiter** | Windows network impairment | Free / $30 |
| **comcast** | Cross-platform network impairment | Free |
| **Toxiproxy** | TCP proxy with configurable latency | Free |
---
## 6. Test Automation Architecture
### Test Layers
```
┌─────────────────────────────────────────────────────────────┐
│ SYS.4 System Integration │
│ Real devices, real servers, real networks, store builds │
├─────────────────────────────────────────────────────────────┤
│ SWE.6 Software Verification │
│ MVP acceptance matrix, E2E flows, audio quality │
├─────────────────────────────────────────────────────────────┤
│ SWE.5 Software Integration │
│ Flutter ↔ Bridge ↔ Rust ↔ Protocol, platform channels │
├─────────────────────────────────────────────────────────────┤
│ SWE.4 Unit Tests │
│ Rust crate tests, Flutter widget/service tests, mocks │
└─────────────────────────────────────────────────────────────┘
```
### Recommended Test Matrix
| Test Type | Runner | Frequency | Blocking? |
|---|---|---|---|
| Rust `cargo test` | Ubuntu CI | Every PR | Yes |
| Rust `cargo clippy` | Ubuntu CI | Every PR | Advisory |
| Flutter `analyze` + `test` | Ubuntu CI | Every PR | Yes |
| Supply-chain | Ubuntu CI | Every PR | Yes |
| iOS unsigned build | macOS CI | Every PR | Yes |
| Android build (multi-ABI) | Ubuntu CI + NDK | Every PR | Yes |
| Windows build + smoke | Windows runner | Every PR | Yes |
| macOS build + smoke | macOS runner | Every PR | Yes |
| Audio benchmarks | Ubuntu CI | Every PR | Advisory |
| E2E (live server) | Dedicated runner | Nightly | No |
| Audio quality (loopback) | Device runners | Weekly | Advisory |
| Network condition tests | Linux + tc | Weekly | Advisory |
---
## 7. Cloud Testing Services
| Service | Use Case | Est. Monthly Cost |
|---|---|---|
| Firebase Test Lab | Android device matrix | $0-150 (free tier) |
| BrowserStack App Live | Real iOS + Android devices | $200-400 |
| AWS Device Farm | Automated device testing | $0.17/device-minute |
| GitHub Actions | Current CI baseline | $0-100 |
| MacStadium | macOS CI for signed builds | $80-150 |
---
## 8. Cost Estimates
### Hardware (One-Time)
| Item | Cost |
|---|---|
| iPhone 14+ | $700 |
| iPad | $400 |
| Android phone | $300 |
| Windows PC | $600 |
| Linux PC | $600 |
| Audio peripherals | $100 |
| **Total hardware** | **$2,700** |
### Cloud Services (Monthly)
| Service | Cost |
|---|---|
| GitHub Actions (public) | $0 |
| GitHub Actions (private) | $0-40 |
| MacStadium macOS runner | $80-150 |
| Firebase Test Lab | $0-150 |
| **Total monthly** | **$80-740** |
### Maintenance Effort
| Area | Effort |
|---|---|
| CI workflow maintenance | 2-4 hrs/week |
| Test fixture updates | 1-2 hrs/week |
| Device OS updates | 2-4 hrs/month |
| Benchmark reviews | 1-2 hrs/month |
| **Total maintenance** | **~15-25 hrs/month** |
---
## 9. Implementation Roadmap
### Phase 1: Foundation (Weeks 1-4)
- [ ] Add Android build job to CI (NDK + cargo-ndk + multi-ABI)
- [ ] Add Windows build job to CI (windows-latest runner)
- [ ] Add macOS build + smoke job to CI
- [ ] Add Linux multi-distro build matrix (Docker)
- [ ] Enable `cargo clippy` as blocking check
- [ ] Add `cargo llvm-cov` coverage reporting
### Phase 2: Device Integration (Weeks 5-8)
- [ ] Acquire physical test devices
- [ ] Set up self-hosted runners for device-connected tests
- [ ] Implement audio loopback test harness
- [ ] Add Flutter integration tests with platform channels
- [ ] Set up Firebase Test Lab for Android device matrix
- [ ] Implement network condition test suite (tc-based)
### Phase 3: Full Automation (Weeks 9-12)
- [ ] Nightly E2E test against controlled TeamSpeak server
- [ ] Weekly audio quality regression suite on physical devices
- [ ] Automated Android multi-device testing (Firebase)
- [ ] Benchmark regression gates
- [ ] iOS TestFlight build + device smoke automation
- [ ] Windows/macOS signed build + smoke automation
---
*Generated by test environment research agents on 2026-06-11*