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
@@ -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*