refactor: restructure docs as submodule, add dev-docs/ and AGENTS.md

- Move ASPICE docs to chanoraapp/docs submodule at docs/
- Move development docs to dev-docs/ (superpowers, offline-knowledge, impl-mapping)
- Add AGENTS.md with project conventions for AI agents
- Add impl-mapping.md (SAD component → source file mapping)
- Archive completed plans to dev-docs/superpowers/plans/_archived/
- Remove AGENTS.md from .gitignore (now tracked)
This commit is contained in:
Edison Jwa
2026-06-13 03:32:33 +09:00
parent 5765e9cf6f
commit bba6273af7
98 changed files with 2113 additions and 30548 deletions
-1
View File
@@ -125,7 +125,6 @@ opencode.json
/apps/chanora_flutter/macos/Frameworks/
.opencode/
.omo/
AGENTS.md
Screenshot 2026-05-17 at 22.23.07.png
# Xcode archive / export bundles (generated by Product > Archive > Distribute)
+3
View File
@@ -1,3 +1,6 @@
[submodule "silero-coreml"]
path = silero-coreml
url = git@github.com:chanoraapp/silero-coreml.git
[submodule "docs"]
path = docs
url = git@github.com:chanoraapp/docs.git
+111
View File
@@ -0,0 +1,111 @@
# AGENTS.md — Chanora Project Conventions
## Project Overview
Chanora is a cross-platform voice client (Flutter + Rust) targeting TeamSpeak-compatible servers. The project follows ASPICE engineering processes with full traceability from system requirements through verification.
## Repository Structure
```
chanora/ ← Code repo (this one)
├── docs/ → chanoraapp/docs ← Git submodule: ASPICE docs, Docusaurus doc site
├── dev-docs/ ← Local-only development docs
│ ├── superpowers/ ← AI agent specs and plans
│ │ ├── specs/ ← Feature/design specs (active)
│ │ └── plans/ ← Implementation plans (active)
│ │ └── _archived/ ← Completed plans
│ ├── offline-knowledge/ ← Doc maintenance tools, link coverage
│ ├── implementation-status-* ← Code state snapshots
│ └── release/ios-build.md ← Operational build instructions
├── apps/chanora_flutter/ ← Flutter application
├── core/chanora_core/ ← Rust core API + orchestration
├── crates/ ← Rust crates (protocol, audio, state, etc.)
└── dev-docs/impl-mapping.md ← SAD component → source file mapping
```
## Documentation Two-Repo Model
**`docs/` is a git submodule** pointing to the `chanoraapp/docs` repository. It serves a Docusaurus doc site with ASPICE traceability. It is NOT a local directory you can freely create files in.
### What lives where
| Content | Location | Reason |
|---|---|---|
| SysRS, SysDes, SRS, SAD, SDD | `docs/` (submodule) | ASPICE baselines, served on doc site |
| Verification plans (SWE.4/5/6, SYS.4) | `docs/` (submodule) | ASPICE verification evidence |
| Governance, traceability, decision register | `docs/` (submodule) | ASPICE governance |
| Security, privacy, legal | `docs/` (submodule) | Stakeholder-facing |
| UI/UX guidelines, i18n architecture | `docs/` (submodule) | Design references |
| Feature specs and implementation plans | `dev-docs/superpowers/` | Code-coupled, agent working files |
| Link coverage, doc quality analysis | `dev-docs/offline-knowledge/` | Maintenance tools |
| Implementation status snapshots | `dev-docs/` | Code state tracking |
| Source file path references | `dev-docs/impl-mapping.md` | Developer convenience, not ASPICE |
### Rules for agents
1. **Never create or edit files in `docs/`** without understanding it's a submodule. Changes there require committing in the `chanoraapp/docs` repo first, then updating the submodule pointer in this repo.
2. **ASPICE documents do not contain code file paths.** ASPICE traces requirement IDs (e.g., `SysRS-233`, `SRS-045`, `SDD-MOD-009`), not source file paths. If you need to map a component to its source, use or update `dev-docs/impl-mapping.md`.
3. **Specs and plans go in `dev-docs/superpowers/`.** Follow the naming convention: `YYYY-MM-DD-<topic>-design.md` for specs, `YYYY-MM-DD-<topic>.md` for plans.
4. **Completed plans move to `_archived/`.** Once a plan is fully implemented and verified, move it to `dev-docs/superpowers/plans/_archived/`.
5. **Doc site uses Docusaurus.** The `chanoraapp/docs` repo uses Docusaurus 3.10 (Meta-maintained). Do not add MkDocs, mdBook, or other doc site generators.
## ASPICE Traceability Chain
```text
SysRS → SysDes → SRS → SAD (SWE.2) → SDD (SWE.3) → Verification
↓ ↓
SWE.4 (unit) SWE.4/5/6/SYS.4
```
- Requirement IDs are the traceability mechanism, not file paths.
- Every downstream document must reference upstream IDs it traces from.
- Verification plans map to their upstream design/requirements level:
- SYS.4 ← SysDes, SysRS
- SWE.5 ← SAD (SWE.2)
- SWE.4 ← SDD (SWE.3)
- SWE.6 ← SRS
- Requirement IDs should be added to doc front matter `tags:` for traceability browsing.
## Code Architecture
| Component | Location | Responsibility |
|---|---|---|
| Flutter app shell | `apps/chanora_flutter/` | UI, Material 3, navigation, localization |
| Rust core | `core/chanora_core/` | Session orchestration, bridge events |
| Protocol adapter | `crates/chanora_protocol/` | TeamSpeak protocol via tsclientlib |
| State sync | `crates/chanora_state/` | Snapshots, deltas, reducers |
| Audio subsystem | `crates/chanora_audio/` | Capture, DSP, Opus, PTT |
| Storage | `crates/chanora_storage/` | Bookmarks, identity, encryption |
| Diagnostics | `crates/chanora_diagnostics/` | Redaction, logs, export |
| Resolver | `crates/chanora_resolver/` | SRV/TSDNS/DNS resolution |
| Prefetch | `crates/chanora_prefetch/` | Resolution warming, TTL cache |
| Bridge | `crates/chanora_bridge/` | Flutter/Rust typed DTO boundary |
| Cache | `crates/chanora_cache/` | Avatar/icon blob cache |
## Coding Conventions
- **Rust:** Follow workspace `Cargo.toml` structure. Run `cargo check`, `cargo clippy`, `cargo test` before committing.
- **Flutter:** Run `flutter analyze`, `flutter test` before committing.
- **No code comments** unless explicitly requested.
- **Git commits:** Follow convention in `docs/governance/git-commit-message-convention.md` (accessible via submodule).
- **Bridge boundary:** Flutter must not directly depend on protocol-library internals. All cross-boundary communication goes through `chanora_bridge` typed DTOs.
## Verification Commands
```bash
cargo check && cargo clippy && cargo test
cd apps/chanora_flutter && flutter analyze && flutter test
```
## Important References
- Traceability matrix: `docs/governance/traceability-matrix.md`
- Decision register: `docs/governance/product-decision-register.md`
- Security guidelines: `docs/security/security-privacy-legal-guideline.md`
- Release readiness: `docs/release/release-readiness-go-nogo-record.md`
- Doc site repo: `chanoraapp/docs` (Docusaurus)
- Doc site local preview: `cd docs && npm run start`
+40
View File
@@ -0,0 +1,40 @@
# SAD Component → Source File Mapping
**Purpose:** Developer convenience mapping from ASPICE architecture components to source file locations. This is NOT an ASPICE document — it's a lookup for developers.
## Component Mapping
| SAD Component | Source Location |
|---|---|
| Flutter app shell | `apps/chanora_flutter/lib/main.dart`, services, widgets |
| Flutter service layer | `apps/chanora_flutter/lib/services/` |
| Flutter widget layer | `apps/chanora_flutter/lib/widgets/` |
| Bridge layer | `crates/chanora_bridge/src/api.rs`, `apps/chanora_flutter/lib/src/rust/` |
| Rust core | `core/chanora_core/src/lib.rs`, `events.rs`, `network_diagnostics.rs`, `ptt.rs` |
| Protocol adapter | `crates/chanora_protocol/src/` |
| State sync | `crates/chanora_state/src/lib.rs`, `channel_join.rs` |
| Audio subsystem | `crates/chanora_audio/src/` |
| Storage | `crates/chanora_storage/src/lib.rs` |
| Diagnostics | `crates/chanora_diagnostics/src/lib.rs` |
| Resolution and prefetch | `crates/chanora_resolver/src/lib.rs`, `crates/chanora_prefetch/src/lib.rs`, `prefetch_debouncer.dart` |
| Build and release hooks | `.github/workflows/`, `tools/`, platform project files |
## SDD Module Mapping
| SDD Module | Source Location |
|---|---|
| SDD-MOD-001 Flutter app bootstrap | `apps/chanora_flutter/lib/services/app_bootstrap.dart`, `main.dart` |
| SDD-MOD-002 Connect UI | `apps/chanora_flutter/lib/widgets/connect_widgets.dart` |
| SDD-MOD-003 Snapshot and channel UI | `snapshot_view.dart`, `snapshot_state_mapper.dart`, `channel_spacer.dart` |
| SDD-MOD-004 Chat UI | `chat_views.dart`, `bbcode_text.dart` |
| SDD-MOD-005 Voice UI | `voice_bar.dart`, `voice_compact.dart`, `voice_settings*.dart`, `voice_level_meter.dart`, `ptt_capability_badge.dart` |
| SDD-MOD-006 Platform services | `android_permissions_service.dart`, `ios_permissions_service.dart`, `audio_lifecycle_service.dart`, `back_intent_*`, `link_trust_service.dart` |
| SDD-MOD-007 Bridge API | `crates/chanora_bridge/src/api.rs`, generated Dart/Rust bridge files |
| SDD-MOD-008 Rust core supervisor | `core/chanora_core/src/lib.rs`, `events.rs`, `network_diagnostics.rs`, `ptt.rs` |
| SDD-MOD-009 Protocol adapter | `crates/chanora_protocol/src/` |
| SDD-MOD-010 State sync | `crates/chanora_state/src/lib.rs`, `channel_join.rs` |
| SDD-MOD-011 Audio subsystem | `crates/chanora_audio/src/` |
| SDD-MOD-012 Storage | `crates/chanora_storage/src/lib.rs` |
| SDD-MOD-013 Diagnostics | `crates/chanora_diagnostics/src/lib.rs` |
| SDD-MOD-014 Resolution and prefetch | `crates/chanora_resolver/src/lib.rs`, `crates/chanora_prefetch/src/lib.rs`, `prefetch_debouncer.dart` |
| SDD-MOD-015 Build and release hooks | `.github/workflows/`, `tools/`, platform project files |
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,472 @@
# Documentation Site & ASPICE Traceability System Design
**Date:** 2026-06-13
**Status:** Approved design for implementation
**Scope:** Docusaurus doc site, git submodule separation, tag-based ASPICE traceability with custom validation plugin, Cloudflare Pages hosting with access control
## 1. Purpose
Replace the current flat markdown documentation tree with a browseable, searchable, access-controlled doc site that serves three audiences: developers, ASPICE assessors, and non-technical stakeholders. Introduce automated traceability enforcement that validates the ASPICE requirement chain on every build.
## 2. Current State
- 65+ markdown files in `docs/` with no sidebar, no search, no visual hierarchy
- ASPICE traceability maintained in manual markdown tables (`traceability-matrix.md`)
- Cross-references are backtick-quoted paths in prose, not clickable links
- Link coverage report found 2 broken links + 5 broken path references
- No CI enforcement of traceability integrity
- No access control — docs only viewable via GitHub repo browsing or local clone
## 3. Design Decisions
| Decision | Choice | Rationale |
|---|---|---|
| Repo structure | Git submodule (`docs/``chanora-docs` repo) | Cleaner separation, access control, CI independence, separate versioning |
| Doc site generator | Docusaurus | Meta-maintained, full plugin API, built-in tags and versioning, active ecosystem |
| Traceability mechanism | Tag-based + custom Docusaurus plugin | Tags for browsing, plugin for automated chain validation and coverage reports |
| Hosting | Cloudflare Pages | Free tier, global CDN, auto-deploy from CI |
| Access control | Cloudflare Access | Free for up to 50 users, email-based auth, SSO support |
| Code path references in docs | Remove from ASPICE docs, move to `impl-mapping.md` | ASPICE traces requirement IDs, not file paths. Code paths are developer convenience |
| Provenance records | Deferred | Completed ASPICE-related plans archived in `dev-docs/superpowers/plans/_archived/` for now |
## 4. Repo Structure
### 4.1 Docs submodule (`chanora-docs` repo)
```
chanora-docs/
├── mkdocs.yml
├── requirements.txt
├── pyproject.toml
├── docs/
│ ├── index.md
│ ├── .meta.yml
│ ├── requirements/
│ │ ├── .meta.yml
│ │ ├── sysrs.md
│ │ ├── sysdes.md
│ │ └── srs.md
│ ├── architecture/
│ │ ├── .meta.yml
│ │ ├── sad.md
│ │ ├── sdd.md
│ │ ├── file-transfer-design.md
│ │ ├── file-transfer-research.md
│ │ ├── file-transfer-implementation-plan.md
│ │ └── desktop-ptt-architecture.md
│ ├── verification/
│ │ ├── .meta.yml
│ │ ├── verification-master-plan.md
│ │ ├── swe4-unit-verification-plan.md
│ │ ├── swe5-software-integration-verification-plan.md
│ │ ├── swe6-software-verification-plan.md
│ │ └── sys4-system-integration-verification-plan.md
│ ├── governance/
│ │ ├── .meta.yml
│ │ ├── document-index.md
│ │ ├── traceability-matrix.md
│ │ ├── product-decision-register.md
│ │ ├── baseline-approval-record.md
│ │ ├── baseline-candidate-validation-report.md
│ │ ├── document-review-report.md
│ │ ├── document-naming-convention.md
│ │ ├── decision-impact-assessment.md
│ │ ├── git-commit-message-convention.md
│ │ ├── repo-format-validation-report.md
│ │ ├── path-migration-map.md
│ │ └── maintainability-review-2026-06-08.md
│ ├── security/
│ │ ├── .meta.yml
│ │ ├── security-privacy-legal-guideline.md
│ │ ├── threat-model.md
│ │ ├── secure-storage-audit-report.md
│ │ ├── diagnostic-redaction-audit-report.md
│ │ ├── dependency-and-supply-chain-report.md
│ │ ├── license-inventory.md
│ │ └── flutter-license-inventory.md
│ ├── privacy/
│ │ └── privacy-policy.md
│ ├── legal/
│ │ └── trademark-and-attribution-review.md
│ ├── release/
│ │ ├── platform-release-policy.md
│ │ ├── release-readiness-go-nogo-record.md
│ │ └── dv-waiver-register.md
│ ├── references/
│ │ ├── aspice-swe2-swe3-integration-note.md
│ │ ├── external-references.md
│ │ ├── yatqa-en.md (moved from offline-knowledge/external/)
│ │ ├── yatqa-de.md (moved from offline-knowledge/external/)
│ │ ├── teaspeak-overview.md (moved from offline-knowledge/external/)
│ │ └── respeak-overview.md (moved from offline-knowledge/external/)
│ ├── ui-ux/
│ │ ├── material3-guideline.md
│ │ ├── material3-design-tokens.md
│ │ ├── material3-component-catalog.md
│ │ └── adaptive-layout-platform-guide.md
│ ├── i18n/
│ │ └── localization-architecture.md
│ └── tags.md
├── plugins/
│ └── traceability/
│ ├── __init__.py
│ └── traceability.py
├── scripts/
│ └── validate_traceability.py
├── .github/
│ └── workflows/
│ └── deploy.yml
├── wrangler.toml
└── README.md
```
### 4.2 Code repo local files
```
chanora/
├── docs/ → chanora-docs (submodule)
├── dev-docs/
│ ├── superpowers/
│ │ ├── specs/
│ │ │ ├── 2026-05-28-server-resolution-prefetch-design.md
│ │ │ ├── 2026-05-28-chanora-server-prefetch-crate-design.md
│ │ │ ├── 2026-05-29-state-sync-ui-settings-validation-design.md
│ │ │ ├── 2026-06-05-adaptive-3-panel-layout-design.md
│ │ │ ├── 2026-06-08-maintainability-continuation-design.md
│ │ │ ├── 2026-06-09-poke-without-message-design.md
│ │ │ └── 2026-06-13-documentation-site-design.md
│ │ └── plans/
│ │ ├── _archived/
│ │ │ ├── 2026-05-29-finish-dv-document-tree.md
│ │ │ ├── 2026-05-29-dv-evidence-pack.md
│ │ │ ├── 2026-05-29-swe2-swe3-baselines.md
│ │ │ └── 2026-05-29-state-sync-ui-settings-validation.md
│ │ ├── 2026-05-28-server-resolution-prefetch.md
│ │ ├── 2026-05-28-chanora-server-prefetch-crate.md
│ │ ├── 2026-06-06-chat-panel-switching.md
│ │ ├── 2026-06-08-core-internal-split.md
│ │ └── 2026-06-08-maintainability-continuation.md
│ ├── offline-knowledge/
│ │ ├── coverage-analysis.md
│ │ ├── doc-quality-analysis.md
│ │ ├── link-coverage-report.md
│ │ └── reviews/
│ ├── implementation-status-2026-05-28.md
│ ├── release/ios-build.md
│ └── impl-mapping.md
├── apps/, crates/, core/
├── AGENTS.md
└── README.md
```
## 5. Docusaurus Configuration
### 5.1 Site configuration (`docusaurus.config.js`)
```js
module.exports = {
title: 'Chanora Engineering Docs',
tagline: 'ASPICE-compliant engineering documentation with automated traceability',
url: 'https://docs.chanora.dev',
baseUrl: '/',
organizationName: 'chanoraapp',
projectName: 'docs',
onBrokenLinks: 'throw',
onBrokenMarkdownLinks: 'warn',
i18n: { defaultLocale: 'en', locales: ['en'] },
themes: ['@docusaurus/theme-classic'],
plugins: [
'./plugins/traceability',
],
themeConfig: {
navbar: {
title: 'Chanora Docs',
items: [
{ type: 'doc', position: 'left', label: 'Requirements', docId: 'requirements/sysrs' },
{ type: 'doc', position: 'left', label: 'Architecture', docId: 'architecture/sad' },
{ type: 'doc', position: 'left', label: 'Verification', docId: 'verification/verification-master-plan' },
{ type: 'doc', position: 'left', label: 'Governance', docId: 'governance/document-index' },
{ type: 'doc', position: 'left', label: 'Security', docId: 'security/security-privacy-legal-guideline' },
{ type: 'doc', position: 'left', label: 'Release', docId: 'release/platform-release-policy' },
{ type: 'doc', position: 'left', label: 'References', docId: 'references/external-references' },
{ type: 'doc', position: 'left', label: 'UI/UX', docId: 'ui-ux/material3-guideline' },
{ type: 'tags' },
],
},
footer: {
style: 'dark',
links: [
{ title: 'Docs', items: [
{ label: 'Requirements', to: '/docs/requirements/sysrs' },
{ label: 'Architecture', to: '/docs/architecture/sad' },
{ label: 'Verification', to: '/docs/verification/verification-master-plan' },
]},
{ title: 'Governance', items: [
{ label: 'Traceability Matrix', to: '/docs/governance/traceability-matrix' },
{ label: 'Decision Register', to: '/docs/governance/product-decision-register' },
{ label: 'Document Index', to: '/docs/governance/document-index' },
]},
],
},
prism: { theme: prismThemes.github, darkTheme: prismThemes.dracula },
},
};
```
### 5.2 Sidebar (`sidebars.js`)
```js
module.exports = {
requirements: [
'requirements/sysrs',
'requirements/sysdes',
'requirements/srs',
],
architecture: [
'architecture/sad',
'architecture/sdd',
'architecture/file-transfer-design',
'architecture/file-transfer-research',
'architecture/file-transfer-implementation-plan',
'architecture/desktop-ptt-architecture',
],
verification: [
{
type: 'category',
label: 'System Level',
items: ['verification/sys4-system-integration-verification-plan'],
},
{
type: 'category',
label: 'Software Integration',
items: ['verification/swe5-software-integration-verification-plan'],
},
{
type: 'category',
label: 'Unit Level',
items: ['verification/swe4-unit-verification-plan'],
},
{
type: 'category',
label: 'Software Qualification',
items: ['verification/swe6-software-verification-plan'],
},
'verification/verification-master-plan',
],
governance: [
'governance/document-index',
'governance/traceability-matrix',
'governance/product-decision-register',
'governance/baseline-approval-record',
'governance/baseline-candidate-validation-report',
'governance/document-review-report',
'governance/document-naming-convention',
'governance/decision-impact-assessment',
'governance/git-commit-message-convention',
'governance/repo-format-validation-report',
'governance/path-migration-map',
'governance/maintainability-review-2026-06-08',
],
security: [
'security/security-privacy-legal-guideline',
'security/threat-model',
'security/secure-storage-audit-report',
'security/diagnostic-redaction-audit-report',
'security/dependency-and-supply-chain-report',
'security/license-inventory',
'security/flutter-license-inventory',
'privacy/privacy-policy',
'legal/trademark-and-attribution-review',
],
release: [
'release/platform-release-policy',
'release/release-readiness-go-nogo-record',
'release/dv-waiver-register',
],
references: [
'references/external-references',
'references/aspice-swe2-swe3-integration-note',
'references/yatqa-en',
'references/yatqa-de',
'references/teaspeak-overview',
'references/respeak-overview',
],
uiux: [
'ui-ux/material3-guideline',
'ui-ux/material3-design-tokens',
'ui-ux/material3-component-catalog',
'ui-ux/adaptive-layout-platform-guide',
'i18n/localization-architecture',
],
};
```
## 6. Tag-Based Traceability
### 6.1 Front matter schema
Every document includes YAML front matter:
```yaml
---
tags: [swe.2, architecture, SRS-003, SRS-008, SRS-016]
upstream: [srs, sysdes] # Custom metadata for traceability plugin
downstream: [sdd, swe4, swe5] # Custom metadata for traceability plugin
lifecycle: SWE.2 # Custom metadata for traceability plugin
status: baseline # Custom metadata for traceability plugin
---
```
The `tags` field is consumed by the MkDocs Material tags plugin for browsing. The `upstream`, `downstream`, `lifecycle`, and `status` fields are custom metadata consumed by the traceability plugin for chain validation.
### 6.2 Tag categories
| Tag pattern | Purpose | Example |
|---|---|---|
| `swe.1` through `swe.6`, `sys.4` | ASPICE lifecycle stage | Every doc gets at least one |
| `sysrs`, `sysdes`, `srs`, `sad`, `sdd` | Document type | Identifies the doc in the chain |
| `requirements`, `architecture`, `verification`, `governance` | Section category | For filtering |
| `SysRS-233`, `SRS-045`, `SDD-MOD-009` | Requirement/module IDs | Traceability links |
| `baseline`, `draft`, `candidate` | Document status | Assessor visibility |
| `dec-012`, `dec-020` | Decision register refs | Cross-ref to governance |
### 6.3 Section defaults via `.meta.yml`
```yaml
# docs/verification/.meta.yml
tags: [verification]
status: candidate
```
### 6.4 Verification page trace mappings
| Verification plan | Upstream traces | Tags |
|---|---|---|
| SYS.4 System Integration | SysDes, SysRS | `[sys.4, verification, SysDes-102, SysDes-103, ...]` |
| SWE.5 Software Integration | SAD (SWE.2) | `[swe.5, verification, sad-component-bridge, ...]` |
| SWE.4 Unit Verification | SDD (SWE.3) | `[swe.4, verification, SDD-MOD-001, ...]` |
| SWE.6 Software Verification | SRS | `[swe.6, verification, SRS-128, ...]` |
## 7. Custom Traceability Plugin
### 7.1 Location
`plugins/traceability/traceability.py` — MkDocs plugin, ~200 lines Python.
### 7.2 Behavior
On `on_page_markdown` event:
- Scan each page for requirement ID patterns: `SysRS-\d+`, `SysDes-\d+`, `SRS-\d+`, `SDD-MOD-\d+`, `DEC-\d+`
- Build an in-memory traceability graph: upstream ID → downstream document → verification plan
On `on_post_build` event:
- Validate every requirement ID referenced downstream exists in its source document
- Validate every upstream document ID has at least one downstream allocation
- Flag orphaned references (IDs mentioned but never defined)
- Verify bidirectional completeness
### 7.3 Outputs
- `traceability-coverage.json` — machine-readable coverage report with chain completeness percentages
- Console output with pass/fail summary
- Traceability dashboard page with coverage table and broken chain details
- Build failure (`sys.exit(1)`) on broken chains when `strict: true`
### 7.4 Standalone CI validator
`scripts/validate_traceability.py` — same validation logic, runnable without MkDocs build:
```
python scripts/validate_traceability.py docs/
```
Exit code 0 = all chains valid. Exit code 1 = broken chains with details on stderr.
## 8. Hosting & Deployment
### 8.1 Architecture
```
chanora-docs repo → push to main → GitHub Actions
→ validate_traceability.py
→ mkdocs build --strict
→ Cloudflare Pages (via Wrangler)
→ Cloudflare Access policy (email-based auth)
```
### 8.2 CI workflow
On pull request: build + validate only (no deploy).
On push to main: build + validate + deploy to Cloudflare Pages.
### 8.3 Cloudflare Access policy
- Free tier for up to 50 users
- Email-based authentication with optional Google/GitHub SSO
- One-time PIN for external assessors
- Access rules: allow company emails, specific assessor emails; block all others
## 9. Migration Plan
### 9.1 Code path reference cleanup
SAD and SDD currently list file paths (`crates/chanora_protocol/src/`) in component tables. These references will be:
- Replaced with component/module IDs only in the docs submodule
- Preserved in `dev-docs/impl-mapping.md` in the code repo for developer convenience
### 9.2 File moves
| From (code repo) | To | Action |
|---|---|---|
| `docs/sysrs.md` | docs submodule | Move + add front matter |
| `docs/sysdes.md` | docs submodule | Move + add front matter |
| `docs/srs.md` | docs submodule | Move + add front matter |
| `docs/requirements/*` | docs submodule | Move (path records) |
| `docs/architecture/*` | docs submodule | Move + cleanup code paths |
| `docs/verification/*` | docs submodule | Move + add front matter |
| `docs/governance/*` | docs submodule | Move + add front matter |
| `docs/security/*` | docs submodule | Move + add front matter |
| `docs/privacy/*` | docs submodule | Move |
| `docs/legal/*` | docs submodule | Move |
| `docs/release/policy+go-nogo+waiver` | docs submodule | Move |
| `docs/references/*` | docs submodule | Move |
| `docs/ui-ux/*` | docs submodule | Move |
| `docs/i18n/*` | docs submodule | Move |
| `docs/material3-guideline.md` | docs submodule | Move |
| `docs/offline-knowledge/external/*` | docs submodule `references/` (flattened) | Move + rename |
| `docs/superpowers/*` | `dev-docs/superpowers/` | Move |
| `docs/offline-knowledge/` (remaining) | `dev-docs/offline-knowledge/` | Move |
| `docs/implementation-status-*` | `dev-docs/` | Move |
| `docs/release/ios-build.md` | `dev-docs/release/` | Move |
### 9.3 Cross-reference updates
All backtick path references (`docs/srs.md`) should become markdown links (`[SRS](../srs.md)` or `[SRS](srs.md)`) for both GitHub and MkDocs rendering.
### 9.4 Post-migration
- Remove `docs/` contents from code repo
- Add `chanora-docs` as git submodule at `docs/`
- Create `dev-docs/` directory with local-only files
- Update README references to new paths
- Write `AGENTS.md` with new conventions
- Update `opencode.json` or `.opencode/` references
## 10. AGENTS.md
An `AGENTS.md` file will be written at the code repo root documenting:
- The two-repo model (docs/ as submodule, dev-docs/ as local)
- What content goes where
- ASPICE traceability chain and rules
- Code architecture overview
- Verification commands
- Agent working conventions (no edits in docs/ without submodule awareness)
## 11. Deferred Items
| Item | Reason | When |
|---|---|---|
| Document provenance records | Convert completed ASPICE plans into provenance evidence | Follow-up task |
| Custom MkDocs traceability plugin | Core feature, built during implementation | Phase 1 |
| Cloudflare Pages + Access setup | Requires account creation, domain config | During deployment |
| `impl-mapping.md` creation | Extract code paths from SAD/SDD during migration | During migration |
Submodule
+1
Submodule docs added at 44432399ed
@@ -1,43 +0,0 @@
# Chanora Desktop Push-to-Talk Architecture
**Document status:** DV meeting baseline candidate
**Date:** 2026-05-29
**Related documents:** `docs/architecture/sad.md`, `docs/architecture/sdd.md`, `docs/release/dv-waiver-register.md`
## 1. Purpose
This document records the desktop push-to-talk architecture advertised by the README and connects it to the SWE.2/SWE.3 baselines.
## 2. Architecture Summary
Desktop PTT is implemented as a platform-capability feature. The application must detect the active backend, expose the resulting `PttCapabilityLevel`, and avoid claiming global PTT support when the runtime falls back to focused-input behavior.
## 3. Platform Backends
| Platform | Backend strategy | Release claim rule |
|---|---|---|
| Windows | Raw Input first, low-level keyboard hook fallback, focused fallback if unavailable | Claim only the detected runtime capability |
| macOS | Event Tap where permission and OS policy allow; focused fallback otherwise | Claim Global PTT only with permission/backend evidence |
| Linux | Freedesktop GlobalShortcuts portal where available; focused fallback otherwise | State portal/fallback behavior clearly |
## 4. Safety Rules
| Rule | Purpose |
|---|---|
| Missed-key-up watchdog clears transmit after timeout | Prevents stuck transmit when an OS suppresses key-up |
| Capability is surfaced to UI and release record | Prevents over-claiming platform support |
| Mouse side-button support is platform-dependent | Avoids blocking release on Linux portal limitations |
| Focused fallback remains available | Preserves usable PTT when global backends are unavailable |
## 5. Verification Handoff
| Evidence | Required result |
|---|---|
| Per-platform smoke | Active backend and fallback behavior recorded |
| UI inspection | PTT capability badge matches runtime backend |
| Release readiness | Release notes mirror actual capability per platform |
| Safety test | Watchdog prevents stuck transmit after missed key-up |
## 6. DV Conclusion
The desktop PTT architecture is documented for DV navigation. Public release claims still require per-platform PTT evidence attached to the release-readiness record.
-737
View File
@@ -1,737 +0,0 @@
# File Transfer Design
**Date:** 2026-06-10
**Status:** Draft for review
**Scope:** Download files from TeamSpeak-compatible servers via the native client protocol, starting with avatars and icons.
**Direct upstream source:** `docs/architecture/sad.md` (SAD-067, SDD-MOD-009)
## 1. Goal
Chanora needs to download files stored on TeamSpeak-compatible servers. The most visible use cases are client avatars and server/channel/client icons. The file transfer mechanism is also used for channel file browser features, but this document scopes the initial design to avatar and icon retrieval only.
This document describes:
- How the TeamSpeak file transfer protocol works.
- How `tsclientlib` exposes it.
- How Chanora should integrate it following the existing protocol adapter pattern.
- How the result flows through the bridge to the Flutter UI layer.
Upload, channel file browsing, and file deletion are explicitly out of scope for the initial implementation.
## 2. Protocol Background
### 2.1 Two-Phase Transfer
TeamSpeak file transfer is a two-phase process:
1. **Command phase** — The client sends a command over the main encrypted UDP connection to request a transfer token (`ftkey`).
2. **Transfer phase** — The client opens a separate TCP connection to the server's file transfer port (default `30033`) and sends the `ftkey` to authenticate the transfer. Raw bytes flow over this TCP stream.
### 2.2 Relevant ServerQuery Commands
| Command | Direction | Purpose |
|---|---|---|
| `ftinitdownload` | Client → Server | Initialize a download. Returns `ftkey`, `port`, `size`. |
| `ftgetfileinfo` | Client → Server | Get metadata for one or more files. |
| `ftgetfilelist` | Client → Server | List files in a channel's file repository. |
| `ftinitupload` | Client → Server | Initialize an upload. |
| `ftlist` | Client → Server | List active file transfers. |
| `ftstop` | Client → Server | Stop a running transfer. |
| `ftdeletefile` | Client → Server | Delete a file. |
| `ftcreatedir` | Client → Server | Create a directory. |
| `ftrenamefile` | Client → Server | Rename or move a file. |
Initial scope uses only `ftinitdownload` and `ftgetfileinfo`.
### 2.3 File Paths
Files are addressed by a path scoped to a channel ID (`cid`):
- `cid=0` — Server-level file repository. Avatars and icons live here.
- `cid=N` (non-zero) — Channel-specific file repository.
Avatar path: `/avatar_<hex>` where `<hex>` is derived from the client's unique identifier (UID). Each byte of the base64-decoded UID is split into two nibbles, and each nibble maps to a letter `a` through `p` (0→a, 1→b, ..., 15→p).
Icon path: `/icon_<id>` where `<id>` is the icon's signed 64-bit integer ID. If negative, treat as unsigned for the path.
### 2.4 `ftinitdownload` Command
```
ftinitdownload clientftfid={id} name={path} cid={channelId} cpw={password} seekpos={seek} proto=0
```
Parameters:
| Parameter | Type | Description |
|---|---|---|
| `clientftfid` | `u16` | Arbitrary client-side transfer ID. |
| `name` | `string` | File path, e.g. `/avatar_abcdef`. |
| `cid` | `ChannelId` | Channel scope (0 = server). |
| `cpw` | `string` | Channel password. Empty for server-level. |
| `seekpos` | `u64` | Resume offset. 0 for a fresh download. |
| `proto` | `u8` | Protocol version. Always 0. |
Server response:
| Field | Type | Description |
|---|---|---|
| `clientftfid` | `u16` | Echo of the client transfer ID. |
| `serverftfid` | `u16` | Server-side transfer ID. |
| `ftkey` | `string` | One-time transfer key (hex). |
| `port` | `u16` | File transfer TCP port (usually 30033). |
| `size` | `u64` | File size in bytes. |
| `proto` | `u8` | Protocol version echo. |
| `ip` | `string` (optional) | Override IP for the TCP connection. |
### 2.5 TCP Transfer
After receiving the `ftkey`, the client:
1. Opens a TCP connection to `server_ip:port`.
2. Sends `ftkey` followed by a newline.
3. Reads exactly `size` bytes of raw file data.
4. Closes the TCP connection.
### 2.6 Permissions
File transfer requires the following permissions on the server:
| Permission | Needed for |
|---|---|
| `i_ft_file_download_power` | Downloading files. |
| `i_ft_needed_file_download_power` | Required download power on the channel/server. |
| `b_ft_ignore_password` | Bypassing channel passwords (not needed for avatars). |
Avatar downloads typically require only basic download power because avatars are in the server-level repository (`cid=0`), which is generally accessible.
### 2.7 Avatar Detection
When a client connects or updates, the server sends `client_flag_avatar` as a string (the avatar hash). If non-empty, the client has an avatar. The avatar is downloaded from `/avatar_<hex>` where `<hex>` is computed from the client's UID (not from the hash string itself — the hash is just a presence indicator).
## 3. tsclientlib Support
`tsclientlib` implements file transfer natively. The library handles the entire command + TCP flow internally:
### 3.1 Public API
```rust
// tsclientlib/src/lib.rs (relevant signatures)
impl Connection {
pub fn download_file(
&mut self,
channel_id: ChannelId,
path: &str,
channel_password: Option<&str>,
seek_position: Option<u64>,
) -> Result<FiletransferHandle>;
pub fn upload_file(
&mut self,
channel_id: ChannelId,
path: &str,
channel_password: Option<&str>,
size: u64,
overwrite: bool,
resume: bool,
) -> Result<FiletransferHandle>;
}
```
`download_file` sends the `ftinitdownload` command and returns a `FiletransferHandle(u16)` immediately. The actual transfer completes asynchronously.
### 3.2 Stream Items
The connection's event stream emits:
| StreamItem | When | Data |
|---|---|---|
| `StreamItem::FileDownload(FileDownloadResult)` | Server responds with `ftkey`; TCP connected and `ftkey` written | `{ size: u64, stream: TcpStream }` |
| `StreamItem::FileUpload(FileUploadResult)` | Upload ready | `{ seek_position: u64, stream: TcpStream }` |
| `StreamItem::FiletransferFailed(FiletransferHandle, Error)` | Transfer failed | Handle + error |
When `FileDownload` fires, tsclientlib has already:
1. Sent `ftinitdownload` over the encrypted UDP command channel.
2. Received the `ftkey`, `port`, and `size` from the server.
3. Opened a TCP connection to `server:port`.
4. Written the `ftkey` to the TCP socket.
The `TcpStream` in `FileDownloadResult` is ready to read; Chanora only needs to read exactly `size` bytes.
### 3.3 Avatar Helper
`tsproto-types` provides `Uid::as_avatar()` which computes the avatar filename from a UID. Chanora's existing `uid_to_avatar_path()` in `adapter.rs` does the same thing independently.
### 3.4 Doc-Comment Examples
tsclientlib's source contains usage examples in doc comments:
```rust
/// Download an icon:
/// con.download_file(ChannelId(0), &format!("/icon_{}", icon_id), None, None)
/// Upload an avatar:
/// con.upload_file(ChannelId(0), "/avatar", None, data.len() as u64, true, false)
```
## 4. Architecture Integration
### 4.1 Existing Pattern
The protocol adapter (`crates/chanora_protocol`) uses a single tokio task that owns the `tsclientlib::Connection`. All operations follow this pattern:
1. Define a `Request` enum variant with parameters and a `oneshot::Sender` for the reply.
2. Send the request through the `mpsc` channel to the connection task.
3. The connection task calls tsclientlib and resolves the oneshot.
File transfer fits this pattern exactly. The only difference is that the result arrives asynchronously via `StreamItem::FileDownload` rather than immediately from the command call.
### 4.2 Design
The file transfer integration adds:
1. **`Request` variants** for file download.
2. **A pending-downloads map** (`HashMap<FiletransferHandle, DownloadContext>`) in the connection task, mirroring the existing `pending_moves` pattern.
3. **`StreamItem::FileDownload` and `StreamItem::FiletransferFailed`** handling in the event loop.
4. **New DTOs** for file transfer results.
5. **Convenience methods** on `ProtocolClient` for avatar and icon downloads.
### 4.3 Layer Responsibilities
| Layer | Responsibility |
|---|---|
| `chanora_protocol` | Call `tsclientlib::download_file`, track pending transfers, read `TcpStream`, return bytes. No tsclientlib types leak. |
| `chanora_core` | Orchestrate when to download (e.g., on profile fetch or on avatar cache miss). |
| `chanora_bridge` | Expose typed `download_avatar` / `download_icon` commands to Flutter. |
| Flutter UI | Call bridge, display with `Image.memory()`. Cache in memory/image cache. |
### 4.4 Error Mapping
File transfer errors map to the existing `ProtocolError` variants:
| tsclientlib error | ProtocolError |
|---|---|
| Permission denied (TS3 error code) | `ServerRejected { code, message }` |
| File not found | `ServerRejected { code, message }` |
| Network/TCP failure | `Backend(String)` |
| Timeout | `Timeout` |
| Connection lost mid-transfer | `Lost(String)` |
## 5. Detailed Design
### 5.1 New Types in `dto.rs`
```rust
/// A downloaded file's raw content and metadata.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct DownloadedFile {
/// Raw file bytes.
pub data: Vec<u8>,
/// The server path that was requested.
pub path: String,
/// Channel ID the file was downloaded from.
pub channel_id: u64,
}
```
### 5.2 New Request Variants in `adapter.rs`
```rust
enum Request {
// ... existing variants ...
/// Download a file from the server's file repository.
DownloadFile {
/// Channel ID. 0 for server-level (avatars, icons).
channel_id: u64,
/// File path, e.g. "/avatar_abcdef" or "/icon_12345".
path: String,
/// Channel password. None for server-level files.
channel_password: Option<String>,
/// Reply channel for the result.
reply: oneshot::Sender<Result<DownloadedFile, ProtocolError>>,
},
}
```
### 5.3 Pending Downloads Map
```rust
type PendingDownloads = HashMap<tsclientlib::FiletransferHandle, PendingDownload>;
struct PendingDownload {
path: String,
channel_id: u64,
reply: oneshot::Sender<Result<DownloadedFile, ProtocolError>>,
}
```
### 5.4 Event Loop Handling
In the connection task's main loop, add handling for file transfer stream items:
```rust
// In handle_non_audio_stream_item or in the main loop:
StreamItem::FileDownload(result) => {
// result: FileDownloadResult { size, stream }
// Look up the handle in pending_downloads
// Use tokio::io::AsyncReadExt::read_exact to read 'size' bytes
// Resolve the oneshot with DownloadedFile
}
StreamItem::FiletransferFailed(handle, error) => {
// Look up the handle in pending_downloads
// Resolve the oneshot with ProtocolError::Backend
}
```
The TCP read from the `TcpStream` is an async operation. Since the connection task already runs in a tokio context, the read can be done inline. However, for large files this would block the main event loop. Two approaches:
**Option A: Read inline (simple, good for small files like avatars)**
Avatars are typically under 100 KB. Reading them inline in the event loop is acceptable and avoids complexity.
**Option B: Spawn a reader task**
For future channel-file-browser support with potentially large files, spawn a separate tokio task that reads the stream and sends the result back.
**Recommendation:** Start with Option A. The initial scope is avatars and icons (small files). Refactor to Option B when channel file browsing is implemented.
### 5.5 Request Handling
When the connection task receives `Request::DownloadFile`:
```rust
Ok(Request::DownloadFile { channel_id, path, channel_password, reply }) => {
let ts_channel_id = TsChannelId(channel_id);
match con.download_file(ts_channel_id, &path, channel_password.as_deref(), None) {
Ok(handle) => {
pending_downloads.insert(handle, PendingDownload {
path,
channel_id,
reply,
});
}
Err(e) => {
let _ = reply.send(Err(ProtocolError::Backend(
format!("download_file init: {e}")
)));
}
}
}
```
### 5.6 Public API on `ProtocolClient`
```rust
impl ProtocolClient {
/// Download a file from the server's file repository.
/// `channel_id` 0 means server-level (avatars, icons).
pub async fn download_file(
&self,
channel_id: u64,
path: String,
channel_password: Option<String>,
) -> Result<DownloadedFile, ProtocolError> {
let (tx, rx) = oneshot::channel();
self.tx
.send(Request::DownloadFile { channel_id, path, channel_password, reply: tx })
.await
.map_err(|_| ProtocolError::Lost("connection task is gone".to_string()))?;
rx.await
.map_err(|_| ProtocolError::Lost("download_file reply dropped".to_string()))?
}
/// Download a client's avatar image. Returns raw image bytes.
/// Pass the `avatar_path` from `ClientProfile`.
pub async fn download_avatar(
&self,
avatar_path: String,
) -> Result<DownloadedFile, ProtocolError> {
self.download_file(0, avatar_path, None).await
}
/// Download a server, channel, or client icon by its icon ID.
pub async fn download_icon(
&self,
icon_id: i64,
) -> Result<DownloadedFile, ProtocolError> {
let unsigned_id = icon_id as u64;
let path = format!("/icon_{}", unsigned_id);
self.download_file(0, path, None).await
}
}
```
### 5.7 Exports in `lib.rs`
```rust
pub use dto::DownloadedFile;
```
### 5.8 Bridge Layer
In `crates/chanora_bridge/src/api.rs`, add:
```rust
pub async fn download_avatar(&self, avatar_path: String) -> Result<Vec<u8>, BridgeError> {
self.protocol
.download_avatar(avatar_path)
.await
.map(|file| file.data)
.map_err(BridgeError::Protocol)
}
```
### 5.9 Flutter Integration
Flutter side:
1. Call `clientProfile()` to get `ClientProfile` (already exists).
2. Check if `avatarPath` is non-empty.
3. Call bridge `downloadAvatar(avatarPath)` to get `Uint8List`.
4. Display with `Image.memory(bytes)`.
Caching strategy:
- In-memory: Use Flutter's standard `ImageCache` or a simple `Map<String, Uint8List>` keyed by avatar path.
- Disk: Consider caching to local storage for offline display. This is a follow-up decision, not MVP scope.
- The avatar path already encodes the UID, so it can serve as a cache key.
## 6. Avatar Path Computation
Chanora already has this implemented in `adapter.rs`:
```rust
fn uid_to_avatar_path(uid_b64: &str) -> String {
let decoded = BASE64_STANDARD.decode(uid_b64).unwrap_or_default();
let mut rendered = String::with_capacity(decoded.len() * 2);
for byte in decoded {
rendered.push((b'a' + (byte >> 4)) as char);
rendered.push((b'a' + (byte & 0x0f)) as char);
}
rendered
}
```
This maps each nibble to `a` through `p` (0→a, 1→b, ..., 15→p), matching the canonical TeamSpeak implementation.
The full avatar path is constructed as:
```rust
let avatar_path = if client.avatar_hash.is_empty() || unique_id.is_empty() {
String::new()
} else {
format!("/avatar_{}", uid_to_avatar_path(&unique_id))
};
```
This is already correct and used in `ClientProfile.avatar_path`. No changes needed.
## 7. Threading and Concurrency
| Concern | Design |
|---|---|
| TCP read blocking the event loop | For avatar/icon sizes (< 100 KB typically), inline async read is acceptable. Spawn a reader task for larger files when channel file browsing is added. |
| Multiple concurrent downloads | `pending_downloads` is a HashMap keyed by `FiletransferHandle`. Multiple downloads can be in flight simultaneously. tsclientlib assigns unique handles. |
| Download timeout | Add a deadline to pending downloads (e.g., 30 seconds). Sweep expired entries similar to the existing `pending_moves` sweep. |
| Cancellation on disconnect | When the connection task exits, all pending oneshot senders are dropped, which resolves the caller's await with a `RecvError`. The caller maps this to `ProtocolError::Lost`. |
## 8. Diagnostic and Security Considerations
### 8.1 Diagnostic Redaction
- File transfer paths may contain user-identifying information (UID-derived avatar names). These should be registered for diagnostic redaction if they appear in log output.
- File contents (avatar images) must not appear in log output or diagnostic exports.
### 8.2 Security
- The `ftkey` is a one-time token and must not be logged.
- TCP file transfer connections are not encrypted. This is a TeamSpeak protocol limitation, not a Chanora design choice. Avatar data is public (visible to anyone on the server), so the risk is acceptable.
- File download does not require secrets beyond the existing authenticated connection.
### 8.3 Privacy
- Avatar downloads reveal to the server that the user is viewing a specific client's avatar. This is inherent in the protocol.
- Chanora should not download avatars proactively for all clients. Download only when the UI needs to display a specific avatar (lazy/on-demand).
## 9. Out of Scope
The following are explicitly deferred:
- File upload (avatar upload, channel file upload).
- Channel file browser (listing, creating directories, deleting, renaming).
- Resumable downloads (seek position > 0).
- File transfer progress reporting.
- myTeamSpeak avatar resolution (the `client_myteamspeak_avatar` field).
- In-memory hot cache in Rust (Flutter's `ImageCache` handles decoded image caching; add Rust-side layer only if profiling shows need).
- Upload, file browser, and channel file management.
## 10. Cache Architecture
### 10.1 Layer Ownership
| Layer | Responsibility | Storage |
|---|---|---|
| `chanora_protocol` | Download raw bytes from server. No caching logic. | None |
| `chanora_cache` | Content-addressed blob store backed by `cacache`: crash-safe writes, SSRI integrity verification, key validation, eviction, clear. Separate crate from `chanora_storage`. | Platform cache directory |
| `chanora_core` | Session-aware cache orchestration: check freshness, coalesce requests, rate-limit downloads, persist to disk via `chanora_cache`. | Delegates to `chanora_cache` |
| `chanora_bridge` | Expose typed `download_avatar` / `clear_file_cache` / `file_cache_size` to Flutter. | None |
| Flutter | Display via `Image.memory`. Standard `ImageCache` for hot memory caching. Evict from `ImageCache` when hash changes. | In-memory only |
### 10.2 Why Separate `chanora_cache` Crate
`chanora_cache` is a separate crate from `chanora_storage` for three reasons:
1. **Different durability semantics.** `chanora_storage` holds identity, bookmarks, and connection profiles — data the user explicitly created. `chanora_cache` holds downloaded blobs that are fully reconstructible from the server. Losing the cache is an inconvenience, not data loss.
2. **Different backup semantics.** Cache should be excluded from backups; persistent storage should be included. Platform conventions (iOS `Library/Caches/` vs `Library/Application Support/`) reflect this distinction.
3. **Different directory placement.** Cache lives in the platform's cache directory (OS may evict under storage pressure on mobile). Persistent storage lives in the support directory.
The cache wraps the `cacache` crate for production-tested crash safety and integrity verification. It does not share `chanora_storage`'s crate or directory, and does not reimplement cacache's atomic write or content-addressing logic.
### 10.3 Why Hybrid (Rust Disk + Flutter Memory)
- Flutter's built-in `ImageCache` is an LRU in-memory cache (default 1000 images / 100 MiB). It handles hot display caching automatically when you use `MemoryImage`.
- Flutter has no built-in disk cache. `cached_network_image` / `flutter_cache_manager` are designed for HTTP URLs, not custom binary protocol data.
- Rust already owns the protocol, the connection state, and the anti-flood budget. Putting disk cache here avoids a feedback loop across the bridge.
### 10.4 Cache Storage
`chanora_cache` wraps the `cacache` crate for its on-disk storage. The physical layout is managed by `cacache`:
```
<app_cache_dir>/chanora/
blobs/ ← cacache content store root
content-v2/ ← content-addressed by SHA-512
<sha512-hex>/
data ← raw blob bytes
tmp/ ← temp files (in-flight writes)
index-v2/ ← entry index (key → content mapping)
```
Chanora's `BlobCache` maps protocol keys to `cacache` string keys:
| Protocol key | cacache key | Example |
|---|---|---|
| Avatar MD5 | `"av_<md5hex>"` | `"av_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6"` |
| Icon CRC32 | `"ic_<crc32u>"` | `"ic_123456789"` |
**Why `cacache`:**
1. **Crash safety.** Production-tested atomic writes (temp → rename). Handles partial writes, power loss, crash mid-write. No custom crash safety code to maintain.
2. **Integrity verification.** SSRI integrity check on every `read()`. Detects corruption, bit rot, partial writes automatically. Better than custom "delete on read failure".
3. **Content dedup.** Same bytes stored once regardless of key. Same avatar on two servers = stored once automatically.
4. **Less code to maintain.** ~120 LOC wrapper vs ~200 LOC custom implementation. Crash safety and integrity are the hard parts — `cacache` owns them.
**Why no `<server_uid>` subdirectory:** The protocol uses content-addressed identifiers. `client_flag_avatar` is the MD5 of the avatar bytes — a given avatar hash always maps to the same bytes regardless of which server the user is on. Same avatar on two servers = same content = stored once by `cacache`. This is a deliberate dedup advantage over per-server namespacing.
**Why no metadata sidecars:** Content is immutable (a given hash always maps to the same bytes). `cacache` manages its own entry index with timestamps. No custom metadata files needed.
**Key validation rules:**
| Prefix | Key format | Validation |
|---|---|---|
| `av_` | `av_<32 hex chars>` | MD5 is exactly 32 hex characters |
| `ic_` | `ic_<1-10 digit number>` | CRC32 unsigned, 04294967295 |
Keys failing validation are rejected at the `BlobCache` API boundary. This prevents path traversal or malformed filenames on disk.
**Platform paths** (Flutter passes the base directory into Rust at startup, matching the existing `initStorage` pattern):
| Platform | Cache directory |
|---|---|
| Android | `context.cacheDir/chanora/` (via `getCacheDir()`) |
| iOS | `Library/Caches/chanora/` (via `getApplicationCacheDirectory()`) |
| macOS | `~/Library/Caches/chanora/` |
| Windows | `%LOCALAPPDATA%/chanora/cache/` |
| Linux | `$XDG_CACHE_HOME/chanora/` or `~/.cache/chanora/` |
Flutter already resolves platform-specific paths. The same `getApplicationCacheDirectory()` call that is available in `path_provider` across all Chanora target platforms should be used. This follows the existing pattern where `app_bootstrap.dart` calls `getApplicationSupportDirectory()` for persistent storage; avatar/icon cache uses the cache-equivalent directory instead.
The cache init call is separate from storage init:
```rust
// Bridge init (Flutter calls these at startup)
pub fn init_storage(support_dir: String) -> Result<(), BridgeError>; // existing
pub fn init_cache(cache_dir: String) -> Result<(), BridgeError>; // new
```
### 10.5 Cache Freshness Strategy
The `client_flag_avatar` field on each client is the authoritative freshness signal:
```
On connect / on client list update:
For each visible client with non-empty avatar_hash:
cache_key = "av_<avatar_hash>"
if cacache entry exists for "av_<avatar_hash>":
use cached file (zero downloads)
else:
enqueue download for avatar_path with expected hash = avatar_hash
On avatar_hash change for a client:
The new hash produces a different cacache key.
The old entry remains until eviction or manual clear.
The new file is downloaded on demand.
```
This means:
- **First connect:** No cache hits. Downloads happen lazily as the UI requests avatars.
- **Reconnect to same server:** All avatars hit cache instantly (hashes match keys). Zero downloads.
- **User changes avatar:** New hash = new cache key. Old entry becomes orphan. New file downloads on next UI request.
- **Same user on different server:** Same avatar hash = same cached file. Cross-server dedup for free.
### 10.6 Anti-Flood and Download Timing
TeamSpeak servers enforce anti-flood rate limiting. Downloading all avatars eagerly on connect would trigger it on servers with many users.
**Strategy: lazy + throttled prefetch**
| Phase | What | Rate |
|---|---|---|
| Connect settle (first 2-5 s) | Do nothing. Let the initial state snapshot and channel tree arrive. | — |
| After settle | UI requests avatars for visible clients in the current channel. These trigger downloads one at a time. | Max 1-2 concurrent downloads per server |
| Channel switch | UI requests avatars for newly visible clients. | Same throttle |
| Background prefetch (optional, future) | Low-priority downloads for clients in adjacent channels. | 1 request per 500 ms |
**Anti-flood handling:**
- If the server responds with an anti-flood error (TS3 error code `0x0701` = `client_could_not_be_banned` / flood-related), back off the download queue.
- Implement a simple semaphore in `chanora_core`: max 1-2 concurrent downloads.
- If a download gets a flood error, pause the queue for 5 seconds, then resume at reduced rate.
### 10.7 Retry on Failure
| Failure type | Strategy |
|---|---|
| Transient (network timeout, TCP reset) | Retry with exponential backoff: 5 s, 30 s, 2 min, 10 min. Cap at 10 min. |
| Server flood limit hit | Pause queue 5 s, then resume at reduced rate. Do not count as a per-file retry. |
| Permission denied (no download power) | Do not retry. Record negative cache entry. Only retry if hash changes. |
| File not found (avatar removed) | Do not retry. Record negative cache entry. Clear when hash changes or becomes empty. |
| Connection lost | All pending downloads fail. On reconnect, cache check runs fresh with current hashes. |
**Negative cache:** In-memory `HashMap<String, Instant>` with 5-minute TTL. Keys like `"av_<hash>"` or `"ic_<id>"` that received permanent errors are stored with an expiry. On lookup, expired entries are treated as absent. Cleared entirely on reconnect.
### 10.8 Request Coalescing
Multiple UI widgets may request the same avatar simultaneously (e.g., channel list + chat view + client info sheet).
**Pattern:** In `chanora_core`'s `FileTransferService`, maintain an in-flight map:
```rust
HashMap<String, tokio::task::JoinHandle<Result<Vec<u8>, FileTransferError>>>
```
- First request: start download, store handle.
- Subsequent requests for same key: await the same handle.
- When handle completes: write to cache, wake all waiters, remove from map.
### 10.9 Cache Eviction and Size Limits
**MVP approach:**
- No automatic size-based eviction in MVP. Avatars are small (typically 10-100 KB). Even 1000 avatars = ~50-100 MB.
- Rely on platform cache directory semantics (OS may evict under storage pressure on mobile).
- Old hash files accumulate but are harmless.
**Post-MVP:**
- `BlobCache::evict(max_bytes)` — walk `cacache::ls()` entries, sort by timestamp (oldest first), delete until total size < `max_bytes`. `cacache` manages timestamps internally. No metadata sidecars needed.
- Or simpler: `BlobCache::evict_older_than(duration)` — delete entries with timestamp older than N days.
- Call on startup and periodically (e.g., every 24 hours or on app resume).
### 10.10 User-Initiated Cache Clear
Add a bridge method:
```rust
pub fn clear_file_cache(&self) -> Result<(), BridgeError> {
// Delete the entire blobs/ directory contents
// Flutter evicts all avatar/icon-related entries from ImageCache
}
pub fn file_cache_size(&self) -> Result<u64, BridgeError> {
// Walk blobs/ and sum file sizes
}
```
Flutter side:
```dart
// In settings or storage management UI:
onPressed: () async {
await api.clearFileCache();
PaintingBinding.instance.imageCache.clear();
}
```
This should be exposed in the app's settings UI under a "Clear cache" or "Storage management" section.
### 10.11 Storage Clear Across Servers
Since the cache is flat with content-addressed keys (no server namespacing):
- Connecting to a different server does not conflict — same avatar hash = same file.
- Avatars unique to the old server remain cached. If a user on the new server has the same avatar (same hash), it hits cache instantly (cross-server dedup).
- Cache clear removes all cached data regardless of which server it came from.
### 10.12 Flutter Display Strategy
**Option A: Bytes across bridge (simpler, recommended for MVP)**
Rust returns `Vec<u8>` across the bridge. Flutter uses `Image.memory(bytes)`.
```dart
final bytes = await api.downloadAvatar(clientUid: uid);
if (bytes != null && bytes.isNotEmpty) {
return Image.memory(Uint8List.fromList(bytes));
} else {
return CircleAvatar(child: Text(initials)); // fallback
}
```
Flutter's `ImageCache` caches the decoded image in memory automatically. Same avatar bytes = cache hit in memory.
**Option B: File path across bridge (better for large images, future)**
Rust writes to disk and returns the file path. Flutter uses `FileImage`.
```dart
final path = await api.getAvatarPath(avatarHash: hash);
if (path != null) {
return Image.file(File(path));
} else {
return CircleAvatar(child: Text(initials));
}
```
`FileImage` does not watch for file changes. When the hash changes, the UI must evict the old entry from `ImageCache` using `PaintingBinding.instance.imageCache.evict(key)`.
**Recommendation:** Start with Option A for MVP. It avoids file-path cross-platform complications and works well for small avatar files. The bridge already returns `Vec<u8>` for the download result.
## 11. Implementation Sequence
| Phase | Scope | What |
|---|---|---|
| Phase 1 | Protocol download | `Request::DownloadFile`, `StreamItem::FileDownload` handling, `ProtocolClient::download_avatar()` / `download_icon()`. No caching. |
| Phase 2 | Bridge + Flutter display | Bridge `downloadAvatar()`, Flutter `Image.memory()`, initials fallback. Still no caching — every view re-downloads. |
| Phase 3 | Rust disk cache | New `chanora_cache` crate: `cacache`-backed content-addressed blob store (`BlobCache`), key validation, mtime-based eviction, `init_cache` bridge call. |
| Phase 4 | Session orchestration | `chanora_core` `FileTransferService`: request coalescing, rate limiter (semaphore), negative cache (5 min TTL), retry backoff. |
| Phase 5 | Cache management | Bridge `clearFileCache()` + `fileCacheSize()`, Flutter settings UI, eviction on startup. |
Phase 1 and 2 deliver visible value (avatars in the UI). Phase 3-5 add robustness.
## 12. References
| Reference | Use |
|---|---|
| `ReSpeak/tsdeclarations` `Messages.toml` lines 828-830 | `ftinitdownload` command declaration |
| `ReSpeak/tsdeclarations` `Messages.toml` lines 590 | `FileDownload` response structure |
| `ReSpeak/tsdeclarations` `ts3protocol.md` | Low-level TeamSpeak protocol specification |
| `ReSpeak/tsclientlib` `src/lib.rs` lines 956-1005 | `download_file` / `upload_file` public API |
| `ReSpeak/tsclientlib` `src/lib.rs` lines 1371-1427 | `StreamItem::FileDownload` handling |
| `ReSpeak/tsclientlib` `src/lib.rs` lines 1630-1672 | Outgoing init commands |
| `Multivit4min/TS3-NodeJS-Library` `src/transport/FileTransfer.ts` | Reference TCP transfer implementation |
| `Speckmops/ts3admin.class` `lib/ts3admin.class.php` lines 1352-1370 | Reference avatar download flow |
| `docs/architecture/sad.md` SAD-067, SDD-MOD-009 | Protocol adapter boundary rules |
| `crates/chanora_protocol/src/adapter.rs` lines 1561-1568 | Existing `uid_to_avatar_path` implementation |
File diff suppressed because it is too large Load Diff
-770
View File
@@ -1,770 +0,0 @@
# File Transfer Cache Research
**Date:** 2026-06-10
**Status:** Research complete, design implications noted (updated with TeaSpeak server findings)
**Companion to:** `docs/architecture/file-transfer-design.md`
**Purpose:** Factual findings from protocol analysis, existing client implementations, and cross-platform research that inform the cache architecture decision.
---
## 1. TS3 Protocol Identity Semantics
### 1.1 Avatar Identity
| Aspect | Value |
|---|---|
| Protocol field | `client_flag_avatar` |
| Type | `TYPE_STRING` (TeaSpeakLibrary `PropertyDefinition.h:200`) |
| Meaning | MD5 hash of the avatar file bytes |
| Scope | Per-client per-server — a user can have different avatars on different servers |
| Freshness | Automatically up-to-date for any client "in view" (`FLAG_CLIENT_VIEW`) |
| Empty value | No avatar set |
**Key fact:** Identical avatar image bytes produce the **same** `client_flag_avatar` hash on any TS3 server. The hash is a content fingerprint, not a server-assigned identifier.
**Download path on server:** `/avatar_<base64HashClientUID>` — the filename is derived from the client's unique identifier (UID), not from the content hash. The content hash is communicated separately via `client_flag_avatar`.
**Sources:**
- TeaSpeakLibrary `PropertyDefinition.h:200`: `PropertyDescription{CLIENT_FLAG_AVATAR, "client_flag_avatar", "", TYPE_STRING, FLAG_CLIENT_VIEW | FLAG_SAVE | FLAG_USER_EDITABLE}`
- TS3AudioBot avatar upload: computes MD5 of image bytes, then sets `client_flag_avatar` to that hash ([`TS3AudioBot/TSLib/TsBaseFunctions.cs:324-341`](https://github.com/Splamy/TS3AudioBot/blob/a69a38d8cba5a4d671dbe06505506f6b46f1d947/TSLib/TsBaseFunctions.cs#L324-L341))
- TS3 NodeJS Library: avatar filename is `avatar_${clientBase64HashClientUID}` ([`TS3-NodeJS-Library/src/node/Client.ts:300-313`](https://github.com/Multivit4min/TS3-NodeJS-Library/blob/0c69b7ee80fa5b74e9175cf4ae3018346f7eb300/src/node/Client.ts#L300-L313))
- TS3 PHP Framework: avatar name derivation from UID ([`ts3phpframework/src/Node/Client.php:288-307`](https://github.com/planetteamspeak/ts3phpframework/blob/87046b3d493c4d3d8064c639ea4269571192e476/src/Node/Client.php#L288-L307))
### 1.2 Icon Identity
| Aspect | Value |
|---|---|
| Protocol fields | `channel_icon_id`, `client_icon_id`, `virtualserver_icon_id` |
| Type | `TYPE_UNSIGNED_NUMBER` (TeaSpeakLibrary `PropertyDefinition.h:83,146,217`) |
| Meaning | CRC32 (unsigned) of the icon file bytes |
| Scope | Per-entity per-server — but CRC32 is content-derived |
| Download path | `/icon_<unsigned_crc32>` |
**Key fact:** Identical icon bytes produce the **same** CRC32 on any TS3 server. The icon ID is a content fingerprint. The upload process computes `crc32.unsigned(data)` and stores at `/icon_<id>`.
**CRC32 collision caveat:** CRC32 is only 32 bits. Different icon content can theoretically produce the same CRC32. Qint's `filecache.rs` explicitly notes this: "there could be collisions because only CRC-32 is used." ForChanora's purposes (small icons, not security-critical), this is acceptable.
**Sources:**
- TeaSpeakLibrary `PropertyDefinition.h:83,146,217`: all icon IDs are `TYPE_UNSIGNED_NUMBER`
- TS3 NodeJS Library `uploadIcon()`: computes `crc32.unsigned(data)`, uploads to `/icon_<id>` ([`TS3-NodeJS-Library/src/TeamSpeak.ts:2234-2241`](https://github.com/Multivit4min/TS3-NodeJS-Library/blob/0c69b7ee80fa5b74e9175cf4ae3018346f7eb300/src/TeamSpeak.ts#L2234-L2241))
- TS3 PHP Framework: icon path uses `/icon_<unsigned id>` ([`ts3phpframework/src/Node/Node.php:137-146`](https://github.com/planetteamspeak/ts3phpframework/blob/87046b3d493c4d3d8064c639ea4269571192e476/src/Node/Node.php#L137-L146))
- TS3 community forum: "The filename itself is the result of the CRC32 checksum" (TeamSpeak staff)
### 1.3 Implication for Cache Design
Both avatars and icons are **content-addressed by the protocol itself**:
| Asset | Content hash source | Same content across servers? |
|---|---|---|
| Avatar | `client_flag_avatar` = MD5 of bytes | Same bytes → same hash → same ID |
| Icon | `icon_id` = CRC32 of bytes | Same bytes → same CRC32 → same ID |
This means a **flat content-addressed blob store** can achieve zero-duplication without any per-server directories, hardlinks, or ref-counting.
---
## 2. Virtual Server Identity
### 2.1 Server UID
| Aspect | Value |
|---|---|
| Protocol field | `virtualserver_unique_identifier` |
| Type | `TYPE_STRING` (TeaSpeakLibrary `PropertyDefinition.h:22`) |
| Generated by | The server instance, on creation |
| Globally unique? | **Not guaranteed** — locally generated, no central registry |
| Stable? | Yes — persists across restarts of the same virtual server |
**Key fact:** `virtualserver_unique_identifier` is generated by each TS3 server. Two physically different servers could theoretically produce the same UID. It is **not safe as a global cache key**.
### 2.2 What Chanora Currently Tracks
| Layer | Server identity fields | Source |
|---|---|---|
| Protocol adapter (`adapter.rs:1752-1755`) | `server_name`, `welcome_message`, `platform`, `version` | `state.server.*` from tsclientlib |
| DTO (`ServerSnapshot`) | `server_name`, `welcome_message`, `platform`, `version` | No UID field |
| Bridge (`BridgeSnapshot`) | Same as DTO | Same |
| Storage (bookmarks) | Keyed by `host` (hostname:port) | SQLite `WHERE host = ?1` |
| Core (recent servers) | `cfg.address` as host | Auto-saved on connect |
**Chanora does not currently plumb `virtualserver_unique_identifier` through the DTO stack.** The field exists in tsclientlib's state but is not extracted.
### 2.3 Implication for Cache Design
Using `virtualserver_unique_identifier` as the sole cache key is risky (not globally unique). Using connection address (`host:port`) is safe but duplicates cache entries when the same server is accessed via different addresses.
**Recommendation:** For a content-addressed blob store, server identity is only needed for per-server metadata (eviction, "clear cache for this server"), not for the blob key itself. The blob key is the content hash.
---
## 3. Existing TS3 Client Cache Implementations
### 3.1 Qint (tsclientlib-based, Tauri + Rust)
**Architecture:** Per-server directory with SQLite metadata.
```
<cache>/files/<server-uid>/<channel-id>/<base64(path)>
```
**Avatar handling:**
- Avatar state stored per `(server, client)` row in SQLite
- On avatar hash change, deletes the cached `/avatar_<uid>` file for that server
- Avatar download path: `/avatar_<uid_base64>`
**Icon handling:**
- Icons path-cached with CRC32
- Code comments note CRC32 collisions and freshness by mtime
- Qint explicitly deletes and re-downloads when icon mtime changes
**Dedup:** None. Same avatar on 5 servers = 5 stored copies.
**Sources:**
- [`Qint/proxy/src/filecache.rs`](https://github.com/ReSpeak/Qint/blob/7efe949adfa1a1ecb9d185e7740e015da18cc41b/proxy/src/filecache.rs#L1-L6): "Stores files transferred via the TS3 file transfer protocol. This includes icons and avatars."
- [`Qint/proxy/src/db/mod.rs`](https://github.com/ReSpeak/Qint/blob/7efe949adfa1a1ecb9d185e7740e015da18cc41b/proxy/src/db/mod.rs#L1158-L1176): avatar hash change triggers delete
- [`Qint/src-tauri/src/cmd.rs`](https://github.com/ReSpeak/Qint/blob/7efe949adfa1a1ecb9d185e7740e015da18cc41b/src-tauri/src/cmd.rs#L524-L539): file download command
### 3.2 TS3 Official Client (closed source)
**Architecture:** Lazy cache with SDK callbacks.
- `getAvatar()` returns cached path if present; otherwise triggers download
- `onAvatarUpdated` callback fires when avatar is downloaded or deleted
- Cache paths (from community documentation):
- Windows: `%LOCALAPPDATA%\TeamSpeak\Cache\Default`
- Linux: `~/.cache/TeamSpeak/Default`
- macOS: `~/Library/Caches/TeamSpeak/Default`
- SDK also exposes `CLIENT_MYTS_AVATAR` / `client_myteamspeak_avatar` for cross-server myTeamSpeak avatars
**Sources:**
- [`ts3client-pluginsdk/src/plugin.c`](https://github.com/teamspeak/ts3client-pluginsdk/blob/4aa90a53aa150cbf81e13bc97e68c0431b26499f/src/plugin.c#L384-L396): `getAvatar()` and `onAvatarUpdated`
- [`ts3client-pluginsdk/public_rare_definitions.h`](https://github.com/teamspeak/ts3client-pluginsdk/blob/4aa90a53aa150cbf81e13bc97e68c0431b26499f/include/teamspeak/public_rare_definitions.h#L284-L313): `CLIENT_FLAG_AVATAR`, `CLIENT_MYTS_AVATAR`
- Community: [clear cache](https://community.teamspeak.com/t/clear-cache/41511), [broken icons](https://community.teamspeak.com/t/server-icons-are-displaying-a-broken-image-issues-with-local-cache/58680)
### 3.3 TeaSpeak Client (TypeScript + C++ native)
**Architecture:** Browser Cache API for images, per-server own-avatar storage.
**Key components (from `.d.ts` type declarations):**
- `AvatarManager` — per-connection (`FileManager`) avatar handler
- `cachedAvatars` (private) — in-memory cache of `ClientAvatar` objects
- `updateCache(clientAvatarId, clientAvatarHash)` — updates cache when hash changes
- `resolveAvatar(clientAvatarId, avatarHash?, cacheOnly?)` — resolves avatar by ID
- `flush_cache()` — clears cache
- `create_avatar_download(client_avatar_id)` — initiates file transfer
- `ClientAvatar` — tracks individual avatar state
- `clientAvatarId` — derived from client UID via `uniqueId2AvatarId()`
- `currentAvatarHash` — the `client_flag_avatar` value
- State machine: `unset``loading``loaded` / `errored`
- `loadingTimestamp` — when download started
- `ImageCache` — generic image cache using browser Cache API
- `resolveCached(key, maxAge?)` — check if cached
- `putCache(key, value, type?, headers?)` — store
- `cleanup(maxAge)` — evict old entries
- `reset()` — clear all
- `isPersistent()` — whether cache persists to disk
- `OwnAvatarStorage` — user's own avatar, keyed by `serverUniqueId + mode`
- `loadAvatarImage(serverUniqueId, mode)` — load own avatar for a server
- `updateAvatar(serverUniqueId, mode, target)` — update own avatar
- `avatarUploadSucceeded(serverUniqueId)` — move from "uploading" to "server" state
- Stores `LocalAvatarInfo`: fileName, fileSize, **fileHashMD5**, timestamps, contentType
- `FileManager` — per-connection file transfer manager
- `MAX_CONCURRENT_TRANSFERS` — transfer concurrency limit
- `avatars: AvatarManager` — avatar subsystem
- `initializeFileDownload(options)` — start download (path, name, channel, target)
- `deleteIcon(iconId: number)` — delete icon by ID
- `FileTransfer` — transfer state machine
- States: `PENDING → INITIALIZING → CONNECTING → RUNNING → FINISHED / ERRORED / CANCELED`
- `InitializedTransferProperties`: serverTransferId, transferKey, **addresses[]**, protocol, seekOffset, fileSize
- Multiple addresses returned by server for file transfer (failover)
- `localIconCache: ImageCache` — global icon cache (singleton)
**Sources:**
- TeaSpeak-Client `imports/shared-app/file/Avatars.d.ts` — ClientAvatar, AbstractAvatarManager
- TeaSpeak-Client `imports/shared-app/file/LocalAvatars.d.ts` — AvatarManager
- TeaSpeak-Client `imports/shared-app/file/LocalIcons.d.ts` — localIconCache
- TeaSpeak-Client `imports/shared-app/file/ImageCache.d.ts` — ImageCache (browser Cache API)
- TeaSpeak-Client `imports/shared-app/file/FileManager.d.ts` — FileManager, transfer API
- TeaSpeak-Client `imports/shared-app/file/Transfer.d.ts` — FileTransfer, state machine, error types
- TeaSpeak-Client `imports/shared-app/file/OwnAvatarStorage.d.ts` — own avatar per-server storage
- TeaSpeak-Client `native/serverconnection/test/js/ft.ts` — file transfer test (TCP + ftkey protocol)
### 3.4 TS3AudioBot (C#)
**Architecture:** No local avatar cache. Avatar upload is hash-driven.
- Uploads avatar bytes to `/avatar`, computes MD5, sets `client_flag_avatar` to that hash
- Bot avatar selection reads local files from an `avatars/` directory
- No caching of other users' avatars
**Sources:**
- [`TS3AudioBot/TSLib/TsBaseFunctions.cs:324-341`](https://github.com/Splamy/TS3AudioBot/blob/a69a38d8cba5a4d671dbe06505506f6b46f1d947/TSLib/TsBaseFunctions.cs#L324-L341)
- [`TS3AudioBot/Bot.cs:420-470`](https://github.com/Splamy/TS3AudioBot/blob/a69a38d8cba5a4d671dbe06505506f6b46f1d947/TS3AudioBot/Bot.cs#L420-L470)
### 3.5 TS3 NodeJS Library
**Architecture:** No local cache. Downloads on demand.
- Avatar filename: `avatar_${clientBase64HashClientUID}`
- `getAvatar()` downloads directly — no caching layer
- Tests assert the exact `/avatar_<base64uid>` path
**Sources:**
- [`TS3-NodeJS-Library/src/node/Client.ts:300-313`](https://github.com/Multivit4min/TS3-NodeJS-Library/blob/0c69b7ee80fa5b74e9175cf4ae3018346f7eb300/src/node/Client.ts#L300-L313)
- [`TS3-NodeJS-Library/tests/Client.spec.ts:342-358`](https://github.com/Multivit4min/TS3-NodeJS-Library/blob/0c69b7ee80fa5b74e9175cf4ae3018346f7eb300/tests/Client.spec.ts#L342-L358)
### 3.6 Summary Table
| Client | Cache Key Strategy | Dedup Across Servers? | Icon Cache |
|---|---|---|---|
| **Qint** | `<server-uid>/<channel-id>/<path>` | No | Yes (CRC32, mtime freshness) |
| **TS3 Official** | Lazy cache (path-based) | Unknown | Yes |
| **TeaSpeak** | UID-derived avatar ID + browser Cache API | Implicit (same hash = same cache) | Yes (global ImageCache) |
| **TS3AudioBot** | None | N/A | No |
| **TS3 NodeLib** | None | N/A | No |
| **Chanora (decided)** | Content hash (MD5/CRC32), flat `blobs/` in `chanora_cache` crate | **Yes** | Yes |
---
## 4. TeaSpeak Protocol Definitions (Authoritative)
From TeaSpeakLibrary `src/PropertyDefinition.h` — the most complete open-source reference for TS3 protocol property types:
### 4.1 Avatar Properties
```cpp
// Line 200
PropertyDescription{CLIENT_FLAG_AVATAR, "client_flag_avatar", "",
TYPE_STRING, FLAG_CLIENT_VIEW | FLAG_SAVE | FLAG_USER_EDITABLE}
// "automatically up-to-date for any manager 'in view', this manager got an avatar"
```
### 4.2 Icon Properties
```cpp
// Line 83 — server icon
PropertyDescription{VIRTUALSERVER_ICON_ID, "virtualserver_icon_id", "0",
TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE}
// Line 146 — channel icon
PropertyDescription{CHANNEL_ICON_ID, "channel_icon_id", "0",
TYPE_UNSIGNED_NUMBER, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE}
// Line 217 — client icon
PropertyDescription{CLIENT_ICON_ID, "client_icon_id", "0",
TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VIEW | FLAG_CLIENT_VARIABLE}
```
### 4.3 Server Identity
```cpp
// Line 22
PropertyDescription{VIRTUALSERVER_UNIQUE_IDENTIFIER,
"virtualserver_unique_identifier", "",
TYPE_STRING, FLAG_SERVER_VV | FLAG_SNAPSHOT}
```
### 4.4 File Transfer Permissions
```cpp
// From PermissionManager.cpp
PermissionType::i_client_max_avatar_filesize // "Max avatar filesize in bytes"
PermissionType::b_client_avatar_delete_other // "Allow deletion of avatars from other clients"
PermissionType::b_ft_transfer_list // "Retrieve list of running filetransfers"
```
### 4.5 File Transfer Error Codes
```cpp
// From Error.h
channel_no_filetransfer_supported = 0x30C
file_transfer_connection_timeout = 0x80E
file_transfer_complete = 0x811
file_transfer_canceled = 0x812
file_transfer_interrupted = 0x813
file_transfer_server_quota_exceeded = 0x814
file_transfer_client_quota_exceeded = 0x815
file_transfer_reset = 0x816
file_transfer_limit_reached = 0x817
```
---
## 5. Cross-Platform Filesystem Research
### 5.1 Hardlink Support
| Platform | Filesystem | Hardlinks in App-Private Storage? | Gotcha |
|---|---|---|---|
| Android (API 28+) | ext4 / f2fs | **Yes** | Rust uses `libc::link`; not FUSE-mounted; same-filesystem only |
| iOS | APFS | **Yes** (writable sandbox dirs) | App bundle is read-only; avoid hardlinks to bundle assets |
| macOS | APFS | **Yes** | — |
| Linux | ext4 / btrfs / xfs | **Yes** | — |
| Windows | NTFS | **Yes** | Rust uses `CreateHardLinkW` |
**`std::fs::hard_link` gotchas (all platforms):**
- Same filesystem required
- Destination must not exist (returns error)
- Symlink behavior is platform-specific
- All hardlinks share the same inode — modifying one modifies all
- Files must be treated as **immutable** for hardlink safety
**Sources:**
- Rust stdlib: `hard_link` maps to `libc::link` (Unix), `CreateHardLinkW` (Windows) ([Rust source](https://github.com/rust-lang/rust/blob/beae781308e9ddef13074a03faf57ca2fac59a5b/library/std/src/fs.rs#L2898-L2900))
- Android: internal storage uses ext4/f2fs, not FUSE ([Android scoped storage docs](https://source.android.com/docs/core/storage/scoped))
- iOS: APFS supports hardlinks; writable sandbox directories work ([Apple FileSystem basics](https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html))
### 5.2 Rust Cache Libraries
**`cacache`** (MIT licensed, production-ready):
- Content-addressed disk cache
- Automatic dedup, atomic writes, integrity verification
- Exposes `hard_link`, `copy`, and `reflink` paths for retrieval
- On-disk layout: `content-v2/sha512/...`
- Could replace a custom implementation, but adds a dependency
**Sources:**
- [`cacache-rs` README](https://github.com/zkat/cacache-rs/blob/105692a4daa04ce5f5ef3f8688cd3e1c1fb6a7c0/README.md#L39-L60)
- [`cacache-rs` content path](https://github.com/zkat/cacache-rs/blob/105692a4daa04ce5f5ef3f8688cd3e1c1fb6a7c0/src/content/path.rs#L6-L19)
- [`cacache-rs` hard_link impl](https://github.com/zkat/cacache-rs/blob/105692a4daa04ce5f5ef3f8688cd3e1c1fb6a7c0/src/content/read.rs#L257-L285)
### 5.3 Flutter Cache Patterns
Common Flutter packages use **cache-dir + metadata DB**, not hardlink dedup:
- `flutter_cache_manager`: files in cache dir + `sqflite` metadata
- `super_cache_disk`: file-per-entry (`.dat` + `.meta`) in app cache dir
**Sources:**
- [flutter_cache_manager on pub.dev](https://pub.dev/packages/flutter_cache_manager)
- [super_cache_disk on pub.dev](https://pub.dev/packages/super_cache_disk/versions/1.0.0)
---
## 6. Chanora Codebase Context
### 6.1 Storage Patterns
| Component | Pattern | Location |
|---|---|---|
| Identity storage | Atomic write (temp + `sync_all` + `rename`), mode 0600 on Unix | `chanora_storage/src/lib.rs:446-476` |
| Metadata | Same atomic write pattern | `chanora_storage/src/lib.rs:480-515` |
| Bookmarks | SQLite at `<storage_dir>/chanora.db`, keyed by `host` | `chanora_storage/src/lib.rs:782-928` |
| Storage root | `getApplicationSupportDirectory()` from Flutter | `app_bootstrap.dart:19-24` |
| Bridge init | `rust.initStorage(dir: dir)` | `app_bootstrap.dart:23-25,108-133` |
### 6.2 Existing Avatar Handling
| Component | What | Location |
|---|---|---|
| UID to avatar path | `uid_to_avatar_path()` — base64 decode UID, encode each byte as 2 chars (a-p) | `adapter.rs:1561-1568` |
| Client profile DTO | `avatar_path` field — set when `client.avatar_hash` and `unique_id` non-empty | `dto.rs:135-136`, `adapter.rs:1323-1332` |
| No download | Currently no file download implementation exists | — |
| No icon handling | No icon field/path in protocol DTO or adapter | — |
### 6.3 Server Identity in Chanora
Chanora currently tracks servers by **connection address** (`host:port`), not by server UID:
- Bookmarks: `WHERE host = ?1`
- Recent servers: auto-saved by `cfg.address`
- Prefetch cache: keyed by normalized host
- ServerSnapshot: has `server_name` but no `server_uid`
The `virtualserver_unique_identifier` field is available from tsclientlib's state but is **not extracted** by the adapter.
### 6.4 tsclientlib File Transfer API
| Aspect | Detail |
|---|---|
| Download method | `Connection::download_file()` |
| Stream items | `StreamItem::FileDownload(FileDownloadResult { size, stream })` |
| Failure | `StreamItem::FiletransferFailed(handle, error)` |
| TCP handling | tsclientlib handles TCP connection + ftkey writing automatically |
| Chanora's job | Read `size` bytes from the returned `TcpStream` |
| Async behavior | `StreamItem::FileDownload` fires asynchronously, not inline with the request |
### 6.5 ts-bookkeeping Generated Fields
From the generated parser in `target/debug/build/ts-bookkeeping-*/out/`:
- `virtual_server_id: u64` — numeric, per-virtual-server, may change across restarts
- `virtual_server_uid` — string, the `virtualserver_unique_identifier`
Both are available in the `InInitServer` struct from the init handshake but are not currently plumbed through.
---
## 7. TeaSpeak Server Internals (Authoritative)
Source: TeaSpeak Server at `https://git.did.science/TeaSpeak/Server/Server` (branch `new-groups`, commit `b54c6d4e`).
### 7.1 Avatar ID Derivation — Server Side
The server derives the avatar filename from the **client UID**, not from the avatar content:
```cpp
// DataClient.cpp:242-244
std::string DataClient::getAvatarId() {
return hex::hex(base64::validate(this->getUid()) ? base64::decode(this->getUid()) : this->getUid(), 'a', 'q');
}
```
The same transform produces `client_base64HashClientUID` (shown to other clients):
```cpp
// client.cpp:1113-1114
bulk.put_unchecked("client_base64HashClientUID",
hex::hex(base64::validate(info->client_unique_id) ? base64::decode(info->client_unique_id) : info->client_unique_id, 'a', 'q'));
```
**This matches Chanora's existing `uid_to_avatar_path()` in `adapter.rs:1561-1568`.**
### 7.2 Avatar Upload Path
When a client uploads an avatar, the server stores it as `/avatar_<avatarId>`:
```cpp
// file.cpp:696-702
} else if (cmd["path"].as<std::string>().empty() && cmd["name"].string() == "/avatar") {
...
info.file_path = "/avatar_" + this->getAvatarId();
transfer_response = file::server()->file_transfer().initialize_avatar_transfer(...);
}
```
The avatar file path is identity-based (from UID), not content-based.
### 7.3 `client_flag_avatar` — Who Computes the Hash?
**The CLIENT computes the MD5 and sends it to the server during upload.** The server stores it as a string property (`FLAG_USER_EDITABLE`). The server does NOT compute or verify the hash.
This means `client_flag_avatar` is:
- Set by the uploading client
- Stored verbatim by the server
- Broadcast to other clients as part of the client properties
- A reliable content fingerprint: same avatar bytes → same MD5 → same `client_flag_avatar` on any server
### 7.4 Icon IDs — Server Does NOT Compute CRC32
Icon IDs are **permission values**, not content hashes computed by the server:
```cpp
// ConnectedClient.cpp:186-210 — client icon ID from permissions
auto permission_flags = local_permissions->permission_flags(permission::i_icon_id);
new_icon_id = value.value;
updated_client_properties.emplace_back(property::CLIENT_ICON_ID);
```
```cpp
// channel.cpp:1495-1504 — channel icon ID
if(key == property::CHANNEL_ICON_ID) {
auto icon_id = converter<uint32_t>::from_string_view(value);
channel->permissions()->set_permission(permission::i_icon_id, { ... icon_id ... });
}
```
```cpp
// server.cpp:76-89 — server icon ID
SERVEREDIT_CHK_PROP_CACHED("virtualserver_icon_id", permission::b_virtualserver_modify_icon_id, int64_t)
```
**The CLIENT computes the CRC32 during upload and uses it as the filename `/icon_<crc32>`.** The server stores the file and records the ID as a permission value. No server-side CRC32 or MD5 computation exists.
### 7.5 Per-Server Storage Layout
Avatars and icons are stored **per virtual server** on the server's filesystem:
```cpp
// LocalFileSystem.cpp:39-45
fs::path LocalFileSystem::server_path(const std::shared_ptr<VirtualFileServer> &server) {
return fs::u8path(this->root_path_) / fs::u8path("server_" + std::to_string(server->server_id()));
}
// target_path = this->server_path(server) / "icons" / path;
// target_path = this->server_path(server) / "avatars" / path;
```
```
<server_root>/
server_<sid>/
avatars/
/avatar_<avatarId> ← one per client who uploaded
icons/
/icon_<id> ← one per unique icon
```
### 7.6 File Transfer Protocol (Server Side)
Upload/delete/query routing:
```cpp
// file.cpp:273-341 — delete routing
if (first_entry_name.find("/icon_") == 0 && file_path.empty()) { ... delete_icons(...); }
else if (first_entry_name.starts_with("/avatar_") && file_path.empty()) { ... delete_avatars(...); }
```
```cpp
// file.cpp:483-523 — query routing
if (first_entry_name.find("/icon_") == 0 && file_path.empty()) { ... query_icon_info(...); }
else if (first_entry_name.starts_with("/avatar_") && file_path.empty()) { ... query_avatar_info(...); }
```
Transfer initialization returns ftkey and metadata:
```cpp
// file.cpp:759-761
result.put_unchecked(0, "ftkey", transfer->transfer_key);
result.put_unchecked(0, "seekpos", transfer->file_offset);
```
```cpp
// file.cpp:887-899
result.put_unchecked(0, "ftkey", transfer->transfer_key);
result.put_unchecked(0, "proto", "1");
result.put_unchecked(0, "size", transfer->expected_file_size);
```
### 7.7 Key Takeaway for Chanora
| Who does what | Avatar | Icon |
|---|---|---|
| **Uploader (client)** computes | MD5 of avatar bytes → sets `client_flag_avatar` | CRC32 of icon bytes → filename `/icon_<crc32>` |
| **Server** does | Stores file as `/avatar_<uid>`, saves property | Stores file as `/icon_<id>`, saves permission |
| **Other clients** receive | `client_flag_avatar` (MD5) as a property update | `icon_id` (CRC32) as a property update |
| **Chanora cache key** | `av_<md5>.dat` — content fingerprint | `ic_<crc32>.dat` — content fingerprint |
The content hash is computed once (by the uploader) and then broadcast as a property. Chanora never needs to hash anything — it just uses the protocol-provided values as cache keys.
---
## 8. Design Implications
### 8.1 The Core Insight
The TS3 protocol provides content hashes as part of normal server-to-client updates:
| Event | Data provided by server | What Chanora gets for free |
|---|---|---|
| Client enters view | `client_flag_avatar` = MD5 of avatar bytes | Content key for blob store |
| Channel update | `channel_icon_id` = CRC32 of icon bytes | Content key for blob store |
| Server update | `virtualserver_icon_id` = CRC32 of icon bytes | Content key for blob store |
No hashing needed on the client side. The protocol is **already content-addressed**.
### 8.2 Recommended Cache Architecture
```
<app_cache_dir>/chanora/
blobs/ ← cacache content store root
content-v2/ ← content-addressed by SHA-512
<sha512-hex>/data ← raw blob bytes
index-v2/ ← key → content mapping
```
Where `<app_cache_dir>` is the platform cache directory (not the support directory used by `chanora_storage`). Chanora's `BlobCache` maps protocol keys (`av_<md5>`, `ic_<crc32>`) to `cacache` string keys. Physical layout is managed by `cacache`.
**Lookup flow:**
1. Server sends `client_flag_avatar = "a1b2c3d4..."` for user X
2. Check: does `blobs/av_a1b2c3d4....dat` exist?
3. Yes → use it, zero downloads (works for ANY server)
4. No → download from `/avatar_<uid_base64>` → save as `blobs/av_a1b2c3d4....dat`
**Same for icons with `ic_<crc32>.dat`.**
### 8.3 Why This Beats Alternatives
| Approach | Dedup | Globally unique key | Needs server UID plumbing | Needs hardlinks | Complexity |
|---|---|---|---|---|---|
| `<server_uid>/<hash>.dat` | No | No (UID not guaranteed unique) | Yes | Optional | Medium |
| `<host>_<port>/<hash>.dat` | No | Yes | No | Optional | Medium |
| `<host>_<port>/<hash>.dat` + hardlinks | Yes | Yes | No | Yes | Medium-High |
| **`blobs/av_<hash>.dat` (flat)** | **Yes** | **Yes (content hash)** | **No** | **No** | **Low** |
### 8.4 Trade-offs
| Pro | Con |
|---|---|
| Zero duplication across all servers | "Clear cache for server X only" requires metadata layer (Phase 3+) |
| No hardlinks needed | Orphan cleanup requires scanning for unreferenced blobs |
| No server UID plumbing needed | Cannot distinguish same-hash-different-content for icons (CRC32 collision) |
| Simplest possible implementation | — |
| Freshness = hash change = different filename (automatic) | — |
| Cross-platform (just file I/O) | — |
### 8.5 Phased Implementation
| Phase | What | Delivers |
|---|---|---|
| 1 | Protocol download (raw bytes via adapter, no cache) | Working download pipeline |
| 2 | Bridge + Flutter display (`Image.memory()`) | Visible avatars in UI |
| 3 | `chanora_cache` crate: cacache-backed blob cache, separate crate, cache dir, mtime eviction | Zero re-downloads, zero duplication |
| 4 | Session orchestration (coalescing, rate limiting, negative cache) | Anti-flood, robustness |
| 5 | Cache management (clear all, orphan cleanup, optional per-server metadata) | User control |
---
## 9. Resolved Questions
### Q1: Icon CRC32 Collisions — Accept with Size Guard
**Risk assessment:** CRC32 produces a 32-bit hash. For N unique icons, the Birthday paradox gives collision probability ≈ N² / (2 × 2³²).
| Icons (N) | Collision probability |
|---|---|
| 100 | ~0.0001% (negligible) |
| 1,000 | ~0.01% (negligible) |
| 10,000 | ~1.2% (marginal) |
| 65,536 | ~50% (likely) |
A single user typically encounters fewer than 1,000 unique icons across all servers. The practical collision risk is negligible.
**What happens on collision:** Wrong icon displayed for a channel/client/server. This is a visual glitch, not a security issue. The icon will appear incorrect until the cache is cleared.
**Existing practice:** Qint explicitly notes CRC32 collisions (`filecache.rs:4`) but does NOT guard against them — they only refresh icons by mtime. No other TS3 client guards against CRC32 collisions.
**Recommendation:** Accept CRC32 as the cache key. Add a lightweight **file size guard**: when downloading an icon, if `ic_<crc32>.dat` already exists but has a different size than the `ftinitdownload` response reported, re-download. File size is available from the protocol (`msg.size` in `InFileDownloadPart`). This catches most collisions (different content = different size with high probability) without computing a secondary hash.
**Decision:** CRC32 + file size guard. No SHA256 overhead needed.
---
### Q2: `client_myteamspeak_avatar` — Defer Indefinitely
**What it is:** A string property (`Option<String>` in ts-bookkeeping) broadcast alongside `client_flag_avatar`. It represents a myTeamSpeak cross-server avatar — a user linked to a myTeamSpeak account can set a global avatar that follows them across all servers.
**Current state in Chanora's dependency chain:**
- ts-bookkeeping exposes it: `InInitServer` has `my_team_speak_avatar: Option<String>`
- TeaSpeakLibrary tracks `client_myteamspeak_id` but not the avatar
- tsclientlib exposes it as a property on client state
**Value for Chanora:**
- myTeamSpeak is a TeamSpeak-specific cloud service (account sync, cross-server features)
- Chanora is an independent client — no myTeamSpeak account integration is planned
- The property may contain a URL or identifier that requires myTeamSpeak API access to resolve
- Without myTeamSpeak integration, the avatar cannot be fetched
**Recommendation:** Defer indefinitely. If Chanora ever integrates myTeamSpeak accounts, this can be handled as a separate avatar source (URL-based HTTP download) alongside the existing protocol-based avatar download. The cache architecture supports this — just add a different blob prefix (e.g., `mt_<hash>.dat`).
**Decision:** Out of scope for MVP and foreseeable roadmap.
---
### Q3: Cache Backing Store — `cacache` Wrapper in Separate `chanora_cache` Crate
**Decision:** Use `cacache` as the backing store inside `chanora_cache`. Not a custom flat-file implementation.
**Why cacache won over custom:**
1. **Crash safety is production-tested.** `cacache` handles partial writes, power loss, crash mid-write. A custom implementation would need to get `sync_all` + atomic rename right — one bug = corrupted cache. Even though cache data is disposable (reconstructible from server), `cacache` eliminates this entire class of bugs.
2. **Less code to maintain.** ~120 LOC wrapper vs ~200 LOC custom implementation. The hard parts (atomic writes, integrity, content dedup) are owned by `cacache`, tested by the npm ecosystem.
3. **Integrity verification on every read.** SSRI verification detects corruption, bit rot, partial writes automatically. A custom impl would need to add this separately or accept silent corruption.
4. **Content dedup by SHA-512.** Same avatar on two servers = stored once automatically. The protocol's MD5/CRC32 keys map to `cacache` string keys; content dedup happens at the SHA-512 layer underneath.
**What about the downsides:**
| Concern | Assessment |
|---|---|
| ~6 transitive deps | `sha2` already in tree via `chacha20poly1305`. `serde_json`, `tempfile`, `digest` are lightweight. Acceptable for the safety benefit. |
| SHA-512 overhead on every write/read | For <100KB avatars, SHA-512 takes ~0.1ms. Negligible. |
| Opaque on-disk format | `cacache` provides `ls()` API for enumeration and inspection. Not as simple as `ls blobs/` but adequate. |
| `cacache` has no built-in LRU eviction | We write a custom eviction pass using `cacache::ls()` + timestamp sort. ~20 lines. Same complexity as custom impl's eviction. |
**Separate crate rationale:**
- `chanora_cache` is separate from `chanora_storage` because cache data has different durability semantics (disposable vs persistent), different backup semantics (excluded vs included), and different directory placement (cache dir vs support dir).
- `chanora_cache` lives in the platform's cache directory (`getApplicationCacheDirectory()`). `chanora_storage` lives in the support directory (`getApplicationSupportDirectory()`).
- Bridge init is separate: `init_cache(cache_dir)` vs `init_storage(support_dir)`.
**API design:**
```rust
pub struct BlobCache { cache_dir: PathBuf, max_bytes: u64 }
impl BlobCache {
pub fn new(cache_dir: impl AsRef<Path>, max_bytes: u64) -> Result<Self, BlobCacheError>;
pub async fn put(&self, prefix: &str, key: &str, data: &[u8]) -> Result<(), BlobCacheError>;
pub async fn get(&self, prefix: &str, key: &str) -> Result<Option<Vec<u8>>, BlobCacheError>;
pub async fn remove(&self, prefix: &str, key: &str) -> Result<(), BlobCacheError>;
pub async fn clear(&self) -> Result<(), BlobCacheError>;
pub async fn total_size(&self) -> Result<u64, BlobCacheError>;
pub async fn evict(&self) -> Result<(), BlobCacheError>;
}
```
All methods are async (cacache is async-native). Key validation at API boundary (`av_` = 32 hex chars, `ic_` = decimal digits).
---
### Q4: Per-Blob Metadata — No Metadata Sidecars (Resolved)
**Original options:**
| Approach | Pros | Cons |
|---|---|---|
| SQLite (chanora.db) | ACID, queryable, already in use | Schema migration, couples cache to bookmark DB |
| JSON sidecar files | Simple, self-contained, easy to debug | Write amplification (2 files per blob), concurrent write risk |
| In-memory only | Simplest | Lost on restart, can't do orphan cleanup offline |
| **No metadata (mtime-based)** | **Simplest, zero write amplification, 1 file per blob** | **No per-blob metadata beyond mtime** |
**Why no metadata is sufficient:**
1. **Content is immutable.** A given hash (MD5 or CRC32) always maps to the same bytes. There is no "stale content" problem — if the hash changes, it's a new file with a new name. No invalidation needed.
2. **mtime = insertion time.** Since content is never modified after write, the filesystem mtime equals the time the blob was cached. This is sufficient for "delete oldest files first" eviction.
3. **Write amplification avoided.** One file per blob (just the data) instead of two (data + JSON sidecar). For a cache that may hold thousands of small files, this matters.
4. **Eviction is simple.** `walk dir → stat → sort by mtime → delete oldest`. No JSON parsing, no schema, no migration.
5. **Per-server metadata deferred.** "Clear cache for server X only" and orphan cleanup are post-MVP features. If needed, a refs-layer can be added later without changing the blob layout.
**Oracle consultation:** Oracle recommended this approach explicitly — no metadata files, mtime-based eviction, separate crate. The immutability guarantee makes metadata redundant.
**Decision:** No metadata sidecars. One file per blob. Mtime-based eviction. Per-server metadata deferred to post-MVP.
---
### Q5: File Transfer Address Failover — Not Needed
**What the protocol provides:**
The TeaSpeak client's `InitializedTransferProperties` returns `addresses[]` — an array of `{serverAddress, serverPort}`. The official TS3 client can try multiple addresses for failover.
**What tsclientlib provides:**
```rust
// tsclientlib/src/lib.rs:1373-1375
let ip = msg.ip.unwrap_or_else(|| self.client.address.ip());
let addr = SocketAddr::new(ip, msg.port);
TcpStream::connect(&addr).await
```
tsclientlib's `InFileDownloadPart` has `ip: Option<IpAddr>`**single IP only**, not an array. If the server provides an IP, it uses that. Otherwise, it falls back to the connection address. **No multi-address failover.**
**What ts-bookkeeping parses:**
```rust
pub struct InFileDownloadPart {
pub client_filetransfer_id: u16,
pub server_filetransfer_id: u16,
pub filetransfer_key: String,
pub port: u16,
pub size: u64,
pub protocol: u8,
pub ip: Option<IpAddr>, // ← single optional IP
}
```
**The server's `notifystartdownload` response** sends `ip` as an optional single value, not an array. The TeaSpeak client's `addresses[]` is a higher-level abstraction (likely the client's own fallback logic), not a protocol feature.
**Recommendation:** Chanora follows tsclientlib's existing behavior — use `msg.ip` or fallback to connection address. No custom failover logic needed. If the TCP connection fails, the download fails and retries follow the exponential backoff strategy from the design doc.
**Decision:** Single address (from tsclientlib). No failover needed.
-190
View File
@@ -1,190 +0,0 @@
# Chanora Software Architecture Description
**Lifecycle:** SWE.2 Software Architectural Design
**Document status:** DV meeting baseline candidate
**Date:** 2026-05-29
**Direct upstream source:** `docs/srs.md`
**Related system allocation:** `docs/sysdes.md`
## 1. Purpose
This Software Architecture Description defines Chanora's software architecture for DV review. It bridges SRS software requirements to SWE.3 detailed design and to SWE.5/SWE.6 verification planning.
This baseline captures the architecture visible in the current repository. It is sufficient for DV traceability review, while deeper per-module algorithms remain in `docs/architecture/sdd.md` and source-level design.
## 2. Architectural Scope
Chanora is a Flutter application with a Rust core. Flutter owns the user-facing shell, Material 3 widgets, localization, permission UX, and platform service presentation. Rust owns connection orchestration, protocol isolation, audio processing, storage coordination, diagnostics, server resolution, prefetch policy, and bridge DTOs.
## 3. Upstream SRS Allocation
| SRS group | Architectural allocation |
|---|---|
| SRS-003, SRS-008 through SRS-016 | Cross-platform app shell, Flutter UI, Rust core, platform adapters |
| SRS-017 through SRS-030 | Flutter UI, state presentation, connection and voice controls |
| SRS-031 through SRS-035 | Bridge layer and typed DTO boundary |
| SRS-036 through SRS-043 | Rust core connection lifecycle and state behavior |
| SRS-044 through SRS-053 | Protocol adapter and TeamSpeak-compatible server boundary |
| SRS-054 through SRS-061 | State synchronization and replay/reducer verification hooks |
| SRS-062 through SRS-083 | Audio subsystem, DSP, codec, PTT, mute/deaf, metering |
| SRS-084 through SRS-095 | Storage, secure storage, identity, diagnostics-sensitive data |
| SRS-096 through SRS-102 | Diagnostics, export, redaction, troubleshooting hooks |
| SRS-103 through SRS-123 | Platform adapters, packaging, release behavior |
| SRS-124 through SRS-143 | Verification support, analysis requirements, traceability rules |
| SRS-144 through SRS-184 | Material 3, adaptive UI, accessibility, localization, Unicode, app initialization |
| SRS-185 through SRS-218 | Platform baselines, PTT capability, transmit mode, no automatic telemetry, benchmark advisory |
## 4. Component Architecture
| Component | Repository location | Responsibility | Direct architectural dependencies |
|---|---|---|---|
| Flutter app shell | `apps/chanora_flutter/lib/main.dart`, services, widgets | App startup, screen composition, user actions, localization, Material 3 UI | Generated Rust bridge, platform plugins, Flutter services |
| Flutter service layer | `apps/chanora_flutter/lib/services/` | Permission flows, lifecycle policy, host prefetch debounce, link trust, state mapping, platform back intent | Flutter app shell, generated bridge APIs, platform plugins |
| Flutter widget layer | `apps/chanora_flutter/lib/widgets/` | Connect UI, channel tree, chat, voice controls, settings, diagnostics surfaces | Flutter services, generated DTOs, design tokens |
| Bridge layer | `crates/chanora_bridge`, `apps/chanora_flutter/lib/src/rust/` | Typed Flutter/Rust boundary and generated bindings | Rust core, Flutter generated code |
| Rust core | `core/chanora_core` | Connection lifecycle, orchestration, reconnect behavior, storage coordination, voice state, bridge-facing event DTOs | Protocol, audio, storage, diagnostics, state, resolver/prefetch |
| Protocol adapter | `crates/chanora_protocol` | Isolate `tsclientlib`, expose typed protocol DTOs/errors | Rust core, external compatible server |
| State sync | `crates/chanora_state` | Snapshot/delta model, channel join helpers, reducer behavior | Rust core, protocol DTOs |
| Audio subsystem | `crates/chanora_audio` | Capture/playback, Opus, DSP, PTT, voice activity reservation, platform units | Rust core, platform APIs, protocol audio path |
| Storage | `crates/chanora_storage` | Bookmarks, identities, encrypted local data, platform keyring integration | Rust core, platform secure storage |
| Diagnostics | `crates/chanora_diagnostics` | Redaction, log sink, export bundle, known-secret registry | Rust core, Flutter diagnostics UI |
| Server resolver | `crates/chanora_resolver` | SRV/TSDNS/DNS fallback resolution | Rust core, prefetch crate |
| Server prefetch | `crates/chanora_prefetch`, Flutter `prefetch_debouncer.dart` | Invisible host-field resolution warming, TTL cache, generation safety | Resolver, Flutter connect UI, Rust core |
## 5. Static Architecture View
```text
Flutter UI/widgets/services
-> generated Dart bridge API
-> chanora_bridge
-> chanora_core
-> chanora_protocol -> tsclientlib -> external compatible server
-> chanora_state
-> chanora_audio -> platform audio APIs / Opus / DSP
-> chanora_storage -> platform secure storage / SQLite
-> chanora_diagnostics
-> chanora_prefetch -> chanora_resolver -> network DNS/TSDNS
```
The bridge is the trust and type boundary between Flutter and Rust. Flutter must not directly depend on protocol-library internals. Rust core must not expose platform-specific storage or audio details to UI code except through stable DTOs and capability fields.
Current Core locality note: the public Core Interface remains available through `chanora_core::*` re-exports, while branch `simplify-project-review` has started moving internal Core responsibilities into focused Modules (`events.rs`, `network_diagnostics.rs`). This is an internal maintainability split, not a public Interface change.
## 6. Runtime Flow Architecture
### 6.1 Connect Flow
```text
User enters host/bookmark
-> Flutter connect widgets
-> optional prefetch debounce
-> bridge connect command
-> Rust core supervisor
-> resolver / prefetch cache
-> protocol adapter
-> external compatible server
-> state snapshot/events
-> bridge event stream
-> Flutter state mapper and widgets
```
### 6.2 Voice Flow
```text
Microphone / platform input
-> audio capture unit
-> DSP chain: HPF, NS, AEC, AGC where active
-> PTT/mute/transmit gate
-> Opus encode
-> protocol adapter
-> external compatible server
External server voice
-> protocol adapter
-> jitter/decode path
-> mixer / per-user controls
-> platform output
```
### 6.3 Diagnostics Flow
```text
Runtime event or error
-> diagnostic log sink / known-secret registry
-> redactor
-> user-initiated export bundle
-> Flutter share/export surface
```
## 7. Interface Catalogue
| Interface | Producer | Consumer | Architectural rule |
|---|---|---|---|
| Bridge command DTOs | Flutter generated API | `chanora_bridge`, Rust core | Stable typed DTOs; no raw protocol-library types cross to Flutter |
| Bridge event DTOs | Rust core / bridge | Flutter services/widgets | User-safe errors and capability fields are explicit |
| Protocol DTOs | `chanora_protocol` | Rust core, state sync | Protocol adapter isolates `tsclientlib` |
| Audio configuration | Flutter settings / Rust core | `chanora_audio` | Voice modes and processing flags are explicit; Windows/Linux desktop VAD-backed `VoiceActivity` is enabled only where runtime evidence exists, with unsupported platforms disabled/deferred |
| Storage records | Storage crate | Rust core / Flutter UI via bridge | Secrets stay behind secure-storage abstraction |
| Diagnostic bundles | Diagnostics crate | Flutter diagnostics UI | Redaction runs before export or display |
| Platform capability records | Platform adapters/audio/PTT backends | UI and release record | UI/release wording must not over-claim capability |
## 8. Dependency Rules
| Rule | Rationale |
|---|---|
| Flutter UI depends on generated bridge APIs, not Rust internals | Keeps UI stable across Rust implementation changes |
| Rust core orchestrates crates but protocol/audio/storage crates remain separately testable | Supports SWE.4 unit verification and bounded responsibilities |
| Protocol adapter is the only component that owns `tsclientlib` coupling | Protects the app from protocol-library leakage |
| Diagnostics redaction must be reusable by runtime logging and export | Prevents split redaction behavior |
| Platform-specific behavior stays in platform adapters or audio platform units | Keeps cross-platform logic testable and reduces conditional sprawl |
| Release claims consume capability records and release evidence | Prevents over-claiming PTT, signing, packaging, or secure-storage behavior |
## 9. Non-Functional Allocation
| Concern | Architectural mechanism | Verification owner |
|---|---|---|
| Real-time audio responsiveness | Rust audio subsystem, benchmark advisory, bounded callback behavior | Audio / Platform QA |
| Privacy and no automatic telemetry | User-initiated diagnostics, no automatic upload policy | Security / Privacy QA |
| Secure secret handling | Platform secure-storage abstraction and encrypted local storage | Security / QA |
| Cross-platform UI | Flutter Material 3, design tokens, responsive widgets | Software QA / UX |
| Protocol compatibility | `tsclientlib` adapter isolation and compatible-server matrix | Protocol / Integration QA |
| Release reproducibility | CI, build scripts, artifact hashes, release-readiness record | Release / Operations QA |
## 10. Architectural Decisions Captured by This Baseline
| Decision | Architectural outcome |
|---|---|
| Flutter + Rust split | Flutter owns presentation; Rust owns protocol/audio/storage/diagnostics core behavior |
| `tsclientlib` isolation | Protocol compatibility is behind `chanora_protocol` |
| Secure storage abstraction | Platform storage details do not leak into UI or unrelated crates |
| Advisory audio benchmarks | Performance regressions are surfaced without making CI a hard release gate at this stage |
| PTT capability levels | Platform PTT support is represented as capability data and must match release wording |
| VoiceActivity platform scope | Windows/Linux desktop `VoiceActivity` is implemented through the capture VAD path; unsupported platforms remain disabled/deferred until backend allocation and runtime verification exist |
| No automatic diagnostic upload in MVP | Diagnostics are local and user-initiated unless future approved requirements change policy |
## 11. Verification Handoff
| Verification plan | SAD handoff |
|---|---|
| SWE.4 | Component boundaries define unit-test ownership for Flutter services/widgets and Rust crates |
| SWE.5 | Interface catalogue and runtime flows define integration paths |
| SWE.6 | SRS allocation and acceptance flows define software acceptance evidence |
| SYS.4 | Platform capability and external-server boundaries define system integration evidence |
## 12. Traceability to SRS
This SAD derives only from `docs/srs.md`. The broad SRS group-to-component allocation in section 3 is the controlling SWE.2 trace for DV. Detailed item-level trace is represented by the SRS coverage matrix and `docs/governance/traceability-matrix.md`.
## 13. Open Architecture Risks
| Risk | Impact | Control |
|---|---|---|
| SAD item numbering from historical status references is not reconstructed in this baseline | Existing references such as `SAD-043` and `SAD-046` are not itemized here | Treat this as a DV baseline SAD; add itemized SAD IDs in a follow-up if process requires strict ID-level review |
| Some architecture views are textual rather than C4 diagrams | Reviewers may request visual C4 views | Record as documentation hardening, not a blocker for DV baseline if textual views are accepted |
| Release/platform architecture evidence is incomplete | Public release remains blocked | Controlled by release-readiness and waiver records |
| Android runtime verification is not automatic in local reviews | Android permission/audio/lifecycle regressions can pass Rust-only tests | Require `adb devices -l` with a connected device/emulator and Android smoke evidence before claiming Android runtime success |
| Protocol voice packet re-export is an intentional exception to full protocol isolation | Future changes may accidentally widen the protocol/audio Seam | Document and keep the voice wire exception narrow, or move packet construction fully into `chanora_protocol` |
## 14. DV Conclusion
This SWE.2 baseline is sufficient to remove the missing-SAD traceability gap for DV review. It does not replace candidate test evidence or final release approval.
-161
View File
@@ -1,161 +0,0 @@
# Chanora Software Detailed Design
**Lifecycle:** SWE.3 Software Detailed Design and Unit Construction Handoff
**Document status:** DV meeting baseline candidate
**Date:** 2026-05-29
**Direct upstream source:** `docs/architecture/sad.md`
**Related software requirements:** `docs/srs.md`
## 1. Purpose
This Software Detailed Design defines the module-level design details needed for SWE.4 unit verification and SWE.5 integration verification. It is based on the current repository layout and the SWE.2 architecture baseline.
## 2. Module Catalogue
| SDD module | Source location | Primary responsibility | Upstream SAD component |
|---|---|---|---|
| SDD-MOD-001 Flutter app bootstrap | `apps/chanora_flutter/lib/services/app_bootstrap.dart`, `main.dart` | Initialize Rust bridge, localization, app services, theme/design baseline | Flutter app shell |
| SDD-MOD-002 Connect UI | `apps/chanora_flutter/lib/widgets/connect_widgets.dart` | Host/bookmark inputs, connect actions, pre-request UX | Flutter widget layer |
| SDD-MOD-003 Snapshot and channel UI | `snapshot_view.dart`, `snapshot_state_mapper.dart`, `channel_spacer.dart` | Present channel tree, clients, and mapped state | Flutter widget/service layer |
| SDD-MOD-004 Chat UI | `chat_views.dart`, `bbcode_text.dart` | Channel text rendering and BBCode-safe display | Flutter widget layer |
| SDD-MOD-005 Voice UI | `voice_bar.dart`, `voice_compact.dart`, `voice_settings*.dart`, `voice_level_meter.dart`, `ptt_capability_badge.dart` | Voice controls, processing settings, metering, PTT capability | Flutter widget layer |
| SDD-MOD-006 Platform services | `android_permissions_service.dart`, `ios_permissions_service.dart`, `audio_lifecycle_service.dart`, `back_intent_*`, `link_trust_service.dart` | Permission, lifecycle, navigation, route/link trust behavior | Flutter service layer |
| SDD-MOD-007 Bridge API | `crates/chanora_bridge/src/api.rs`, generated Dart/Rust bridge files | Typed command/event boundary | Bridge layer |
| SDD-MOD-008 Rust core supervisor | `core/chanora_core/src/lib.rs`, `events.rs`, `network_diagnostics.rs`, `ptt.rs` | Connection orchestration, reconnect, bridge-facing event DTOs, network diagnostics, PTT state, storage coordination | Rust core |
| SDD-MOD-009 Protocol adapter | `crates/chanora_protocol/src/` | `tsclientlib` isolation, DTO/error mapping | Protocol adapter |
| SDD-MOD-010 State sync | `crates/chanora_state/src/lib.rs`, `channel_join.rs` | Snapshot/delta model, reducer, channel join support | State sync |
| SDD-MOD-011 Audio subsystem | `crates/chanora_audio/src/` | Audio capture/playback, DSP, Opus, PTT, mode stack, platform units | Audio subsystem |
| SDD-MOD-012 Storage | `crates/chanora_storage/src/lib.rs` | Bookmarks, identity storage, encrypted local records, keyring abstraction | Storage |
| SDD-MOD-013 Diagnostics | `crates/chanora_diagnostics/src/lib.rs` | Redaction, log sink, known-secret registry, export bundle | Diagnostics |
| SDD-MOD-014 Resolution and prefetch | `crates/chanora_resolver/src/lib.rs`, `crates/chanora_prefetch/src/lib.rs`, `prefetch_debouncer.dart` | SRV/TSDNS/DNS fallback and generation-safe resolution warming | Server resolver / prefetch |
| SDD-MOD-015 Build and release hooks | `.github/workflows/`, `tools/`, platform project files | CI, unsigned iOS build, benchmark advisory, platform smoke procedures | Release / platform architecture |
## 3. Bridge Boundary Design
The bridge boundary is the only supported Flutter-to-Rust command path. Dart code uses generated APIs under `apps/chanora_flutter/lib/src/rust/`; Rust exposes bridge functions through `crates/chanora_bridge/src/api.rs`.
Design rules:
| Rule | Detail |
|---|---|
| DTO stability | DTO fields must be explicit and serializable through Flutter Rust Bridge generation |
| Error safety | Rust errors exposed to Flutter must be user-safe or mapped before display |
| Secret handling | Secrets may cross only as command inputs or protected DTO fields and must be registered for diagnostic redaction where relevant |
| Capability reporting | Platform and PTT capability fields must reflect actual active backend state |
| Regeneration control | Generated bridge files are implementation artifacts and must be regenerated when bridge API signatures change |
## 4. Connection and State Design
| Detail | Design |
|---|---|
| Connection lifecycle | Rust core owns connect/disconnect/reconnect decisions and suppresses reconnect after user disconnect |
| Backoff | Reconnect uses exponential backoff as described in implementation status, capped at 60 seconds |
| Core internal Modules | `lib.rs` remains the public Interface and orchestration entry point; `events.rs` owns public event/bridge-facing DTOs re-exported by `lib.rs`; `network_diagnostics.rs` owns private connect/loss counters and the last-loss ring buffer |
| Server resolution | Resolver performs SRV/TSDNS/DNS fallback; prefetch cache may warm but must not be required for connect success |
| Snapshot mapping | Rust state and bridge DTOs are mapped into Flutter view models by `snapshot_state_mapper.dart` |
| Channel join | Channel join logic and errors are represented through Rust state/protocol handling and Flutter error mapper service |
| Reducers | `chanora_state` owns snapshot/delta reducer design with unit coverage for snapshot, delta, reconnect, duplicate normalization, disconnected/lost suppression, unknown-client voice activity, deterministic ordering, and channel-delete/client cleanup. Current runtime UI refresh still flows through `chanora_core` snapshot/probe paths; full live-event folding through `chanora_state::reduce` is an integration follow-up. |
## 5. Audio Detailed Design
| Audio element | Design detail |
|---|---|
| Capture/playback | Platform-specific units handle Android, iOS, desktop/fallback paths behind Rust audio abstractions |
| Codec | Opus encode/decode lives in `opus_voice.rs` and associated audio modules |
| DSP chain | High-pass filter, noise suppression, echo cancellation, and AGC are represented by audio processing modules/backends |
| Transmit control | `TransmitMode` supports `Ptt`, `Continuous`, and `VoiceActivity`; `VoiceActivity` is active for Windows/Linux desktop capture when VAD is configured, while mobile, macOS, and unverified-platform enablement remain deferred |
| VoiceActivity gate (capture-side) | `voice_activity::VoiceActivityStateMachine` is the 10 ms-cadence gate for `TransmitMode::VoiceActivity`; open-after 40 ms (debounce), hangover 500 ms (anti-chatter), min-tx 200 ms (anti-flicker), weak-hold 30-100 frames (anti-stale-VAD); live `configure()` re-clamps existing timers on settings change without resetting state; 9 unit tests cover the main paths |
| PTT | Desktop/mobile backends expose capability level and active backend; missed-key-up watchdog prevents stuck transmit |
| Release tail | Tail handling prevents abrupt cutoffs after PTT release where configured |
| Render peak limiter | `voice_render::limit_peak_inplace` is a single-pass, allocation-free per-frame peak scaler applied in both the macOS and iOS render callbacks before the i16 downmix; default threshold 0.99 prevents hard clipping on multi-client mixes that sum past 0 dBFS while remaining transparent for normal voice levels (allocation-free, lock-free, safe on the realtime audio thread) |
| macOS render cadence (producer + ring) | `ios_voice_unit.rs:851-961` runs a 20 ms tokio producer task that calls `AudioHandler::fill_buffer(1920)` and `force_push`es each sample into a `crossbeam ArrayQueue<f32>` (SPSC-effective, MPMC-but-wait-free-per-end); ring capacity 12000 samples ≈ 6.25× pull quantum; 100 ms prebuffer (`PREBUFFER_SAMPLES = 9600` stereo f32) before the VPIO render callback starts draining, matching Mumble's playout margin and WebRTC's kStartDelayMs order of magnitude |
| iOS render cadence (direct-fill) | `ios_voice_unit.rs:968-1034` does `AudioHandler::fill_buffer` directly in the VPIO render callback (VPIO on iOS requests 480-frame ≈ 10 ms slices that align with tsclientlib's 20 ms Opus frame); scratch buffer preallocated to 4096×2 f32 at setup time so the realtime callback never `resize()`s; `try_lock` (not `lock`) on the AudioHandler mutex so contention never stalls the realtime IO thread; on `WouldBlock` the callback emits silence and increments `callback_xrun` |
| VPIO ducking config (macOS 14+) | `ios_voice_unit.rs` writes an 8-byte `AuVoiceIoOtherAudioDuckingConfiguration` struct (`m_enable_advanced_ducking = 0` disables dynamic voice-activity-driven ducking; `m_ducking_level = kAUVoiceIOOtherAudioDuckingLevelMin = 10`) to selector `kAUVoiceIOProperty_OtherAudioDuckingConfiguration` (= 2108) on the VoiceProcessingIO AudioUnit at startup, minimising the ducking of other apps' audio during a voice session; on macOS 13 the property is silently ignored (VPIO returns the default ducking behaviour) and the code logs a debug message and continues |
| Benchmarks | Realtime capture, Opus, and resampler benchmarks provide advisory baseline evidence |
## 6. Storage and Secret Design
| Storage item | Design detail |
|---|---|
| Bookmarks | Stored locally through the storage crate and surfaced in Flutter connect UI |
| Identity references | Stored through `IdentityFileStore` and platform secure storage where available |
| Passwords/secrets | Encrypted at rest using the current storage design; Android Keystore-backed DEK is deferred and must be disclosed |
| CI keyring behavior | CI disables real keyring access with `CHANORA_DISABLE_KEYRING=1` to avoid headless blocking |
| Fallback behavior | Platform fallback modes must be represented as limitations in release/security evidence |
## 7. Diagnostics Detailed Design
| Diagnostic element | Design detail |
|---|---|
| Log sink | Runtime logs can be captured by diagnostic sinks for export |
| Known-secret registry | Runtime secrets are registered for redaction where applicable |
| Redactor | Redacts configured sensitive patterns before export |
| Export bundle | Diagnostic export is JSON-based and user-initiated |
| Upload policy | MVP has no automatic diagnostic, telemetry, or crash upload |
## 8. Flutter UI Detailed Design
| UI area | Design detail |
|---|---|
| Design tokens | `chanora_tokens.dart` centralizes product styling over Material 3 |
| Platform capability display | `platform_capabilities.dart` and PTT capability widgets expose platform-specific support honestly |
| Localization | Generated localization files provide English and Simplified Chinese resources |
| Responsive behavior | Current widgets support compact/mobile-oriented layouts; expanded side-pane hardening remains P1/P2 as recorded |
| Accessibility | Critical status should use text/icons/semantics and not color alone; verification remains through UI tests/audit |
| UI settings persistence | `UiPreferencesService` persists host, nickname, permission explanation state, and theme mode through `shared_preferences`; invalid stored theme values fall back to system theme |
## 9. Build and Release Detailed Design
| Build/release item | Design detail |
|---|---|
| Rust CI | `.github/workflows/ci.yml` runs cargo check/test and advisory clippy |
| Flutter CI | `.github/workflows/ci.yml` runs Flutter pub get, analyze, and tests |
| Supply chain | CI runs cargo-deny and license inventory checks |
| iOS unsigned build | CI runs `flutter build ios --release --no-codesign` |
| Audio benchmarks | `bench-advisory.yml` runs audio benchmarks and posts advisory evidence |
| Platform packages | Public binary packaging/signing/notarization remains release-gated |
## 10. Verification Hook Design
| Module | SWE.4 unit hooks | SWE.5/SWE.6 integration hooks |
|---|---|---|
| Flutter services/widgets | Dart unit/widget tests under `apps/chanora_flutter/test/` | Widget/system demos and candidate device smoke |
| Bridge | API compile/generation checks | Flutter-to-Rust command/event smoke |
| Rust core | Cargo tests | Compatible-server lifecycle demo |
| Protocol | DTO/error mapping tests | Protocol compatibility matrix and server demo |
| State sync | Reducer tests | Snapshot/delta/reconnect integration evidence |
| Audio | DSP/codec/PTT tests and benchmarks | Platform audio loopback/device demo |
| Storage | Repository/encryption/keyring-disabled tests | Platform secure-storage audit |
| Diagnostics | Redaction/export tests | User-initiated export inspection |
| Release hooks | CI workflow validation | Release readiness record and artifact evidence |
## 11. Traceability to SAD
| SAD component | SDD modules |
|---|---|
| Flutter app shell | SDD-MOD-001 |
| Flutter service layer | SDD-MOD-006, SDD-MOD-014 |
| Flutter widget layer | SDD-MOD-002 through SDD-MOD-005 |
| Bridge layer | SDD-MOD-007 |
| Rust core | SDD-MOD-008 |
| Protocol adapter | SDD-MOD-009 |
| State sync | SDD-MOD-010 |
| Audio subsystem | SDD-MOD-011 |
| Storage | SDD-MOD-012 |
| Diagnostics | SDD-MOD-013 |
| Server resolver/prefetch | SDD-MOD-014 |
| Release/platform architecture | SDD-MOD-015 |
## 12. Open Detailed-Design Risks
| Risk | Impact | Control |
|---|---|---|
| Detailed item IDs from historical SDD references are not reconstructed | Existing references such as `SDD-109` are not itemized in this baseline | Treat this as a DV baseline SDD and add strict item numbering later if required |
| Some module designs are summarized rather than API-by-API | May be insufficient for final process audit | Use this as DV baseline; deepen high-risk modules before final release gate |
| Android Keystore-backed DEK is not implemented | Limits storage/security design claims | Controlled by waiver and release-readiness records |
| Full event replay tooling and live reducer integration evidence are absent | Limits state verification design beyond reducer unit behavior | Controlled as P1 gap and runtime-integration follow-up |
| Android runtime smoke is blocked when no device/emulator is attached | Android permission/audio/lifecycle paths cannot be claimed from Rust tests alone | Require `adb devices -l` and Android smoke evidence before closing Android verification claims |
## 13. DV Conclusion
This SWE.3 baseline is sufficient to remove the missing-SDD traceability gap for DV review and to feed SWE.4/SWE.5 verification plans. It does not close release evidence gaps or replace source-level tests.
-21
View File
@@ -1,21 +0,0 @@
# System Design Specification
**Document status:** DV entry-point record
**Canonical document:** `../sysdes.md`
The canonical Chanora System Design Specification currently lives at `docs/sysdes.md`. This file preserves the README-advertised path `docs/architecture/sysdes.md` for DV navigation.
Reviewers shall use `docs/sysdes.md` as the authoritative SysDes baseline until the repository migration moves the canonical file into this directory.
## DV Review Summary
| Topic | Canonical source |
|---|---|
| System element allocation | `docs/sysdes.md` sections 4 through 8 |
| Verification handoff | `docs/sysdes.md` section 12, SysDes-102 through SysDes-107 |
| SysRS-to-SysDes allocation matrix | `docs/sysdes.md` Appendix A |
| Change-control and traceability rules | `docs/sysdes.md` SysDes-108 through SysDes-110 |
## DV Position
The SysDes baseline is reviewable for DV. SRS, SAD, SDD, and verification documents derive from or consume this allocation layer.
@@ -1,32 +0,0 @@
# Chanora Baseline Approval Record
**Document status:** DV meeting baseline candidate
**Date:** 2026-05-29
## 1. Approval Scope
This record tracks approval for documentation baselines. It does not approve public/store release.
| Baseline | Status | DV disposition |
|---|---|---|
| SysRS | Baseline available | Reviewable |
| SysDes | Baseline available | Reviewable |
| SRS | Baseline available | Reviewable |
| SAD / SWE.2 | Baseline candidate | Reviewable with depth limitation |
| SDD / SWE.3 | Baseline candidate | Reviewable with depth limitation |
| Verification plans | Baseline candidate | Reviewable with evidence limitations |
| Release readiness | Baseline candidate | No-Go for public/store release |
## 2. Required Approvers
| Area | Approver role |
|---|---|
| Requirements/design | System Engineering / Software Engineering |
| Verification | Software QA / System QA |
| Release | Product / Release Operations |
| Security/privacy | Security / Privacy owner |
| Legal/trademark/OSS | Legal / Product owner |
## 3. DV Recommendation
Approve the document baseline for DV discussion. Do not approve public/store release until release gates close.
@@ -1,38 +0,0 @@
# Chanora Baseline Candidate Validation Report
**Document status:** DV meeting baseline candidate
**Date:** 2026-05-29
## 1. Validation Summary
Validation was performed against the README-advertised document tree and the DV lifecycle chain.
| Check | Result |
|---|---|
| README document tree represented | Baseline candidate documents exist or path records point to canonical baselines |
| SysRS/SysDes/SRS chain | Available |
| SAD/SDD chain | Baseline candidates added |
| Verification plans | Available |
| Release readiness | Available; public/store release No-Go |
| Waivers | Available |
## 2. Validation Method
| Validation step | Evidence |
|---|---|
| README path coverage | Shell `test -f` command over every advertised document path |
| Sentinel-language scan | Review scan over the DV document tree returned no incomplete-marker matches |
| Lifecycle trace | Traceability matrix covers SysRS -> SysDes -> SRS -> SAD -> SDD -> Verification |
| Release posture | Release-readiness record and legal/security docs consistently keep public/store release at No-Go |
## 3. Known Validation Limits
| Limit | Control |
|---|---|
| Candidate run IDs not embedded | Release-readiness record requires run IDs before release approval |
| Legal DEC-012 open | Public/store release remains blocked |
| Some SAD/SDD details summarized | Deepen before final process audit if required |
## 4. Conclusion
The baseline candidate is suitable for DV meeting review with recorded limitations.
@@ -1,18 +0,0 @@
# Chanora Decision Impact Assessment
**Document status:** DV meeting baseline candidate
**Date:** 2026-05-29
## 1. Impact Matrix
| Decision or gap | Requirements impact | Design impact | Verification impact | Release impact |
|---|---|---|---|---|
| DEC-012 open | Public wording and OSS gates remain constrained | Legal surfaces must avoid over-claiming | Audit evidence required | Public/store release No-Go |
| Android Keystore-backed DEK deferred | Secure-storage claim limited | Storage design carries fallback limitation | Platform audit required | Waiver required |
| Full reducer tests incomplete | State verification incomplete | State design remains valid but evidence partial | SWE.4/SWE.5 partial | Blocks full state-sync claim |
| Desktop/iOS artifacts not release-ready | Platform packaging requirements partial | Release design remains source-build/unsigned | SYS.4 evidence partial | Public binary release No-Go |
| VAD platform-scoped | VoiceActivity active only for verified Windows/Linux desktop paths | UI must show disabled/unavailable on unsupported platforms | VAD pass claim must name verified platform/runtime evidence | No broad VAD marketing claim without platform scope |
## 2. Conclusion
Current impacts are controlled for DV by waivers and release No-Go status.
-36
View File
@@ -1,36 +0,0 @@
# Chanora Document Index
**Document status:** DV meeting baseline candidate
**Date:** 2026-05-29
## 1. Purpose
This index lists the documents required for DV review and identifies their current status.
## 2. Baseline Documents
| Area | Document | Status |
|---|---|---|
| Requirements | `docs/sysrs.md` | Canonical SysRS baseline |
| Requirements | `docs/srs.md` | Canonical SRS baseline |
| Requirements path | `docs/requirements/sysrs.md`, `docs/requirements/srs.md` | Path records pointing to canonical root files |
| System design | `docs/sysdes.md` | Canonical SysDes baseline |
| System design path | `docs/architecture/sysdes.md` | Path record pointing to canonical root file |
| Software architecture | `docs/architecture/sad.md` | SWE.2 baseline candidate |
| Software detailed design | `docs/architecture/sdd.md` | SWE.3 baseline candidate |
| Verification | `docs/verification/verification-master-plan.md` | Verification baseline candidate |
| Verification | `docs/verification/swe4-unit-verification-plan.md` | SWE.4 baseline candidate |
| Verification | `docs/verification/swe5-software-integration-verification-plan.md` | SWE.5 baseline candidate |
| Verification | `docs/verification/swe6-software-verification-plan.md` | SWE.6 baseline candidate |
| Verification | `docs/verification/sys4-system-integration-verification-plan.md` | SYS.4 baseline candidate |
| Release | `docs/release/release-readiness-go-nogo-record.md` | No-Go for public/store release |
| Release | `docs/release/platform-release-policy.md` | Baseline candidate |
| Governance | `docs/governance/traceability-matrix.md` | DV baseline candidate |
| Governance | `docs/governance/maintainability-review-2026-06-08.md` | Working-branch maintainability and fail-safe review |
| Security/privacy/legal | `docs/security/security-privacy-legal-guideline.md` | Baseline candidate |
| Privacy | `docs/privacy/privacy-policy.md` | Engineering baseline candidate |
| Legal | `docs/legal/trademark-and-attribution-review.md` | DEC-012 open |
## 3. DV Use
Use this index as the first navigation document in the DV meeting. Release approval remains controlled by the release-readiness record.
@@ -1,33 +0,0 @@
# Chanora Document Naming Convention
**Document status:** DV meeting baseline candidate
**Date:** 2026-05-29
## 1. Rule
Repository documentation uses lowercase kebab-case file names under topic directories.
Examples:
| Document type | Path pattern |
|---|---|
| Requirements | `docs/requirements/<name>.md` or canonical root file during migration |
| Architecture | `docs/architecture/<artifact>.md` |
| Verification | `docs/verification/<lifecycle>-verification-plan.md` |
| Release | `docs/release/<record-name>.md` |
| Governance | `docs/governance/<record-name>.md` |
## 2. Identifier Rules
| Identifier | Meaning |
|---|---|
| `SysRS-XXX` | System requirement |
| `SysDes-XXX` | System design item |
| `SRS-XXX` | Software requirement |
| `SAD` | Software Architecture Description / SWE.2 |
| `SDD` | Software Detailed Design / SWE.3 |
| `DV-WVR-XXX` | DV waiver |
## 3. Migration Rule
When canonical files move, path records must be replaced by the canonical content or by redirects that clearly identify the authoritative source.
-37
View File
@@ -1,37 +0,0 @@
# Chanora Document Review Report
**Document status:** DV meeting baseline candidate
**Date:** 2026-05-29
## 1. Review Method
Documents were reviewed for DV navigation, lifecycle coverage, explicit release gating, and absence of unsupported completion claims.
| Review attribute | Value |
|---|---|
| Review date | 2026-05-29 |
| Review scope | `docs/requirements/`, `docs/architecture/`, `docs/verification/`, `docs/release/`, `docs/security/`, `docs/privacy/`, `docs/legal/`, `docs/ui-ux/`, `docs/i18n/`, `docs/governance/`, `docs/references/` |
| Review criteria | README path coverage, lifecycle traceability, release-status consistency, waiver visibility, security/privacy/legal gate visibility, sentinel-language scan |
| Evidence commands | README path `test -f` check; sentinel-language scan over the DV document tree |
## 2. Findings
| Finding | Status | Action |
|---|---|---|
| Previous gap: verification document set was missing | Addressed | Added verification master/SWE.4/SWE.5/SWE.6/SYS.4 plans |
| Previous gap: SAD/SDD were missing from current tree | Addressed | Added SWE.2/SAD and SWE.3/SDD baselines |
| Release blockers needed explicit record | Addressed | Added release-readiness record and waiver register |
| README tree had missing documents | Addressed for DV | Added baseline candidate records and path records |
## 3. Residual Issues
| Residual issue | DV handling |
|---|---|
| Candidate commit SHA, tag, artifact hashes, and run IDs are not recorded | Blocks release approval; acceptable for document baseline review |
| SAD/SDD are baseline candidates without historical item-number reconstruction | Accept for DV baseline; deepen before strict item-level audit |
| DEC-012 legal/trademark/OSS review remains open | Public/store release remains No-Go |
| Some implementation status items require revalidation after newer commits | Controlled by waiver register and release-readiness record |
## 4. Review Conclusion
The document set is reviewable for DV. Public/store release remains blocked by the release-readiness record.
@@ -1,21 +0,0 @@
# Chanora Git Commit Message Convention
**Document status:** DV meeting baseline candidate
**Date:** 2026-05-29
Chanora uses Conventional Commits style:
```text
<type>(<scope>): <summary>
```
Examples:
```text
feat(voice): add push-to-talk state handling
fix(protocol): recover channel tree after reconnect snapshot
sec(diagnostics): redact server password from export bundle
release(android): prepare internal alpha build metadata
```
Commits that affect requirements, design, verification, release, security, privacy, or legal gates should update the relevant document in the same change set.
@@ -1,99 +0,0 @@
# Chanora Maintainability Review — 2026-06-08
**Document status:** Working-branch review record
**Branch:** `simplify-project-review`
**Scope:** Project-wide simplification, fail-safe, and verification review
## 1. Purpose
This record captures the current maintainability review so implementation, verification, and release documents do not drift behind the code. It focuses on unnecessary Modules, shallow Interfaces, duplicate Implementations, built-in replacement opportunities, and fail-safe gaps that need explicit evidence before release claims.
## 2. Changes Already Applied on the Branch
| Area | Files | Maintainability result |
|---|---|---|
| Core event DTO locality | `core/chanora_core/src/events.rs`, `core/chanora_core/src/lib.rs` | Public Core event DTOs moved out of the oversized Core integration Module while preserving the public `chanora_core::*` Interface through re-exports. |
| Core network diagnostics locality | `core/chanora_core/src/network_diagnostics.rs`, `core/chanora_core/src/lib.rs` | Private network diagnostic ring-buffer state and its regression test now live next to the Implementation they protect. |
| Bounded queues | `core/chanora_core/src/network_diagnostics.rs`, `crates/chanora_diagnostics/src/lib.rs` | Replaced `Vec + remove(0)` queue behaviour with `VecDeque`, reducing custom queue code and avoiding O(n) front removal. |
| PTT backend errors | `crates/chanora_audio/src/ptt_backends/mod.rs` | Replaced manual `Display` / `Error` Implementation with existing `thiserror::Error`; regression test keeps user-facing strings stable. |
| Render downmix | `crates/chanora_audio/src/voice_render.rs`, `crates/chanora_audio/src/ios_raw_unit.rs` | Removed duplicate mono-i16 downmix loop by using the interleaved helper with one output channel. |
| State reducer | `crates/chanora_state/src/lib.rs` | Reused the main snapshot reducer for reconnect snapshots instead of duplicating normalization and delta construction. |
| Workspace metadata | `crates/chanora_resolver/Cargo.toml`, `Cargo.lock` | Resolver inherits workspace package metadata, improving release metadata Locality. |
| Flutter voice fail-safes | `apps/chanora_flutter/lib/main.dart`, `apps/chanora_flutter/lib/widgets/voice_compact.dart`, `apps/chanora_flutter/lib/services/ios_audio_session_controller.dart` | Commit `d835394` preserves independent mute owners, releases touch PTT on disposal while held, and catches iOS audio-session `MissingPluginException` / activation failures so they do not become unhandled async errors. |
| Rust realtime callback hardening | `crates/chanora_audio/src/android_voice_unit.rs`, `crates/chanora_audio/src/ios_raw_unit.rs`, `crates/chanora_audio/src/engine.rs` | Commit `8606eb4` hardens Android/iOS realtime callback paths. The current branch also migrates the Android-only JNI paths to `jni-rs` 0.22 so the supported ARM64 Android debug build compiles. Full lock-free audio-handler/config/debug-recorder redesign remains follow-up work. |
## 3. Remaining Simplification Opportunities
| Recommendation | Candidate files | Strength | Notes |
|---|---|---|---|
| Continue splitting Core internals by responsibility | `core/chanora_core/src/lib.rs` | Strong | Next slices should be reconnect/session, voice projection, storage helpers, and diagnostics export. Keep public re-exports stable. |
| Make Bridge depend on Core rather than Audio where possible | `crates/chanora_bridge/Cargo.toml`, `crates/chanora_bridge/src/api.rs`, `core/chanora_core/src/lib.rs` | Worth exploring | The Bridge currently has a direct audio edge. Apply the deletion test before removing it. |
| Decide whether prefetch deserves a crate-level Seam | `crates/chanora_prefetch/src/lib.rs`, `crates/chanora_resolver/src/lib.rs`, `core/chanora_core/src/lib.rs` | Worth exploring | Prefetch is a small TTL cache and fire-and-forget resolver Adapter. Merge into resolver if it is resolver policy; merge into Core if it is app orchestration policy. |
| Consolidate protocol/core/bridge event catalogues | `crates/chanora_protocol/src/dto.rs`, `core/chanora_core/src/events.rs`, `crates/chanora_bridge/src/api.rs` | Worth exploring | Protocol-owned deltas and Core-owned lifecycle events are currently mirrored through multiple DTO layers. |
| Reduce bridge DTO mirror boilerplate | `crates/chanora_bridge/src/api.rs` | Worth exploring | Verify Flutter Rust Bridge support before deleting mirrors. If mirrors remain required, centralize conversion patterns and keep field order aligned with Core DTOs. |
| Clarify protocol voice packet exception | `crates/chanora_protocol/src/lib.rs`, `crates/chanora_audio/Cargo.toml` | Worth exploring | The protocol crate documents `tsclientlib` isolation but deliberately re-exports voice packet types for audio. Document this as an explicit voice wire Seam or move packet construction fully into protocol. |
| Remove shallow audio helpers only after public API check | `crates/chanora_audio/src/processor/noop.rs`, `crates/chanora_audio/src/processor/platform.rs`, `crates/chanora_audio/src/frame.rs` | Speculative | These Modules are shallow, but deletion must wait until external/public API expectations are checked. |
| Redesign remaining audio shared state outside realtime callbacks | `crates/chanora_audio/src/engine.rs`, platform voice units, debug recorder/config paths | Strong follow-up | The focused callback hardening is complete, but a full lock-free `AudioHandler` / config / debug-recorder redesign should be planned separately and verified on device. |
| Review protocol/core disconnect and control-plane bounds | `core/chanora_core/src/lib.rs`, `crates/chanora_protocol/src/adapter.rs` | Strong follow-up | Unless closed by a later code slice, sustained voice traffic and broken transport should be reviewed for bounded control request and disconnect progress. |
## 4. Fail-Safe Gaps That Need Evidence
| Gap | Risk | Required evidence before release claim |
|---|---|---|
| Android Keystore-backed DEK remains deferred | Android identity/bookmark encryption has weaker fail-safe properties than final target secure-storage design. | Android secure-storage audit or waiver; explicit release-readiness limitation. |
| Android permission/audio lifecycle needs deeper route exercise | Build/install/launch smoke now passes on the emulator, but full permission-flow and audio-route lifecycle behavior still need an interactive scenario or device test before release. | Device/emulator scenario covering permission request/denial/grant, voice controls, foreground service, audio focus, and route/SCO transitions. |
| iOS device runtime verification not executed in this review | The iOS audio-session error path is hardened, but VoiceProcessingIO/session ordering and runtime audio behavior still need device evidence. | iOS device or simulator build/run plus audio-session smoke evidence before iOS runtime success is claimed. |
| VAD / VoiceActivity wording drift | VAD assets, tests, and Windows/Linux desktop runtime wiring exist, but product-enabled `VoiceActivity` must remain platform-scoped per DEC-030. | Release, README, and verification wording must distinguish verified desktop behavior from unsupported mobile/macOS/unverified-platform behavior. |
| Protocol voice packet re-export is an intentional exception | Future maintainers may assume complete protocol isolation and accidentally widen the Seam. | Architecture note in SAD/SDD or a decision-register entry. |
| Bridge DTO mirror drift | Field additions can be missed across Core, Bridge, and Dart generated DTOs. | Bridge generation check plus Flutter analyze/test after bridge DTO changes. |
| Full live reducer integration remains separate from reducer unit coverage | State reducer tests are strong, but runtime UI still has snapshot/probe paths. | SWE.5 integration run proving live protocol events fold through the intended state path, or explicit P1 deferral. |
| Event replay tooling remains absent | Replay-based diagnosis and regression reproduction are limited. | Event replay tool implementation or waiver. |
## 5. Verification Policy for Future Code Changes
| Change type | Required verification |
|---|---|
| Rust-only change | `cargo fmt --all`, `cargo check --workspace`, `cargo test --workspace` |
| Bridge DTO/API change | Rust verification plus bridge generation check, `flutter analyze`, and `flutter test --exclude-tags e2e` in `apps/chanora_flutter` |
| Android platform/audio/permission change | Rust/Flutter verification plus NDK target compilation, `adb devices -l`, Android build/install, and a device or emulator smoke test |
| Documentation-only change | Read affected docs and ensure cross-links/document index stay current; code tests are not required unless docs describe a code change just made |
## 6. Android ADB Status for This Review
`adb devices -l` now reports an authorized emulator target:
```text
emulator-5554 device product:sdk_gphone64_arm64 model:sdk_gphone64_arm64 device:emu64a transport_id:1
```
Android default debug build still fails because SDD-118 excludes `armeabi-v7a`; use a supported ABI target. ARM64 debug build/install/launch smoke evidence from 2026-06-08:
```text
flutter build apk --debug --target-platform android-arm64
✓ Built build/app/outputs/flutter-apk/app-debug.apk
adb -s emulator-5554 install -r apps/chanora_flutter/build/app/outputs/flutter-apk/app-debug.apk
Success
adb -s emulator-5554 shell am start -W -n app.chanora.chanora_flutter/.MainActivity
Status: ok
LaunchState: COLD
Activity: app.chanora.chanora_flutter/.MainActivity
TotalTime: 6514
adb -s emulator-5554 shell pidof app.chanora.chanora_flutter
7287
```
`dumpsys window app.chanora.chanora_flutter` showed `MainActivity` visible with `isReadyForDisplay()=true`, and `dumpsys activity top` showed `app.chanora.chanora_flutter/.MainActivity` resumed with window focus. This is build/install/launch smoke evidence only; permission-flow success and audio-lifecycle success are not claimed by this review.
## 7. Release and Documentation Alignment Notes
- Android minimum runtime baseline is API 28 (Android 9.0) per SysRS-288, SRS-187, DEC-004, and the Gradle `minSdk = 28` configuration. Documents must not revive the older API 24 baseline.
- Flutter app version/build is `0.3.0+100` in `apps/chanora_flutter/pubspec.yaml`. Rust workspace package version remains `0.2.0-beta.1`. Release documents must distinguish these values instead of treating them as one candidate version.
- The v0.3.0 changelog entry may mention Windows/Linux desktop VAD-backed `VoiceActivity` only with matching runtime evidence; mobile, macOS, and unverified-platform `VoiceActivity` remain disabled/unavailable until DEC-030 is superseded and runtime verification exists.
- README wording must describe the existing Flutter/Rust workspace and app scaffold, not a future scaffold that has not been created.
## 8. Git Policy
No commit is created automatically. Commit only on explicit user demand, after reviewing `git status`, `git diff`, and recent log output.
-18
View File
@@ -1,18 +0,0 @@
# Chanora Path Migration Map
**Document status:** DV meeting baseline candidate
**Date:** 2026-05-29
## 1. Current Migration State
| README path | Current canonical or baseline path | Migration state |
|---|---|---|
| `docs/requirements/sysrs.md` | `docs/sysrs.md` | Path record points to canonical root file |
| `docs/requirements/srs.md` | `docs/srs.md` | Path record points to canonical root file |
| `docs/architecture/sysdes.md` | `docs/sysdes.md` | Canonical root file remains in use |
| `docs/architecture/sad.md` | `docs/architecture/sad.md` | Baseline candidate present |
| `docs/architecture/sdd.md` | `docs/architecture/sdd.md` | Baseline candidate present |
## 2. Migration Rule
Move canonical files only when references in README, traceability, verification, and governance documents are updated together.
@@ -1,25 +0,0 @@
# Chanora Product Decision Register
**Document status:** DV meeting baseline candidate
**Date:** 2026-05-29
## 1. Purpose
This register records product and engineering decisions referenced by the DV document set.
## 2. Decision Summary
| Decision | State | DV impact |
|---|---|---|
| DEC-004 Android minimum runtime API 28 | Accepted by requirements baseline | Android release, verification, and README wording must use API 28 rather than the earlier API 24 recommendation |
| DEC-012 legal/trademark/OSS review | Open | Blocks public/store release |
| DEC-020 dual license MIT OR Apache-2.0 | Accepted per README | Supports license posture; dependency notices still require review |
| DEC-027 desktop mouse side-button PTT | Accepted by requirements baseline | Verification must not over-claim unsupported platform input classes |
| DEC-030 VAD platform scope | Partially superseded by desktop enablement | Windows/Linux desktop `VoiceActivity` is enabled through the audio capture VAD path and must be claimed only with matching runtime evidence; mobile, macOS, and unverified-platform `VoiceActivity` remain disabled/deferred until a later baseline enables and verifies them |
| DEC-032 Android CMake patch exit path | Active tracking | Patched dependency requires reevaluation |
| DEC-033 macOS VPIO ducking configuration | Accepted | Write `kAUVoiceIOProperty_OtherAudioDuckingConfiguration` with `mEnableAdvancedDucking=0` (disables dynamic voice-activity-driven ducking) and `mDuckingLevel=Min` (= 10) to minimise the ducking of other apps' audio during a voice session; property is macOS 14+ only, the macOS 13 set fails silently (debug log) and VPIO uses its default behaviour; matches the iOS `.voiceChat` baseline on macOS 14+ |
| DEC-034 Android runtime verification gate | Active tracking | Android target compilation, install, and runtime smoke are blocked locally until `aarch64-linux-android-clang` is available and `adb devices -l` shows an authorized target; release docs must not claim Android runtime success |
## 3. DV Rule
Open decisions that affect release claims must appear in the waiver register or release-readiness record.
@@ -1,22 +0,0 @@
# Chanora Repository Format Validation Report
**Document status:** DV meeting baseline candidate
**Date:** 2026-05-29
## 1. Repository Layout Check
| Area | Status |
|---|---|
| `docs/requirements/` | Path records present |
| `docs/architecture/` | SAD and SDD present |
| `docs/verification/` | Verification plan set present |
| `docs/release/` | Release readiness and policy records present |
| `docs/security/` | Security/privacy/legal guideline and audit records present |
| `docs/privacy/` | Privacy baseline present |
| `docs/legal/` | Trademark/attribution review present |
| `docs/governance/` | Governance records present |
| `docs/references/` | Reference records present |
## 2. Validation Conclusion
The repository format is sufficient for DV document navigation. Canonical SysRS/SysDes/SRS files still live at root `docs/` paths during migration.
-73
View File
@@ -1,73 +0,0 @@
# Chanora Traceability Matrix
**Document status:** DV meeting baseline candidate
**Date:** 2026-05-29
**Primary upstream documents:** `docs/sysrs.md`, `docs/sysdes.md`, `docs/srs.md`, `docs/architecture/sad.md`, `docs/architecture/sdd.md`
## 1. Purpose
This matrix gives DV reviewers a compact trace from system requirements to design allocation, software requirements, SWE.2/SWE.3 design baselines, and verification evidence. The detailed allocation records remain in `docs/sysdes.md`, `docs/srs.md`, `docs/architecture/sad.md`, and `docs/architecture/sdd.md`.
## 2. Traceability Rule
Chanora uses this document hierarchy:
```text
SysRS -> SysDes -> SRS -> SAD -> SDD -> Verification
```
The current repository has SysRS, SysDes, SRS, SAD, and SDD baselines. The SAD and SDD are DV baseline candidates: they provide architecture and detailed-design coverage sufficient for review, while strict historical item numbering and deeper API-by-API detail remain follow-up hardening tasks.
## 3. Baseline Coverage Summary
| Layer | Coverage statement | Source |
|---|---|---|
| SysRS to SysDes | SysDes Appendix A provides allocation for every SysRS requirement | `docs/sysdes.md` Appendix A |
| SysDes to SRS | SRS reports 110 / 110 SysDes design items covered, with 95 / 110 software-impacting items represented | `docs/srs.md` section 9 |
| SRS to SAD | SAD section 3 allocates SRS groups to software architecture components | `docs/architecture/sad.md` |
| SAD to SDD | SDD section 11 maps SAD components to detailed design modules | `docs/architecture/sdd.md` |
| SDD to verification | Verification plans map SDD modules and SRS acceptance areas to SWE.4/SWE.5/SWE.6/SYS.4 evidence | `docs/verification/` |
| Release decision | Release readiness record maps evidence status to Go/No-Go decision | `docs/release/release-readiness-go-nogo-record.md` |
| Waivers | Waiver register maps known gaps to decision scope and unblock condition | `docs/release/dv-waiver-register.md` |
## 4. Verification Handoff Trace
| SysRS / SysDes source | SRS coverage | Verification plan | DV status |
|---|---|---|---|
| SysRS-233 traceability matrix | SRS-005, SRS-141 through SRS-143, SRS-180 through SRS-183 | Verification master plan and this matrix | Passed for DV baseline |
| SysRS-234 protocol compatibility | SRS-045 through SRS-053, SRS-131, SRS-134 | SWE.5, SWE.6, SYS.4 | Requires compatible-server evidence |
| SysRS-235 state synchronization verification | SRS-054 through SRS-061, SRS-124 | SWE.4, SWE.5, SWE.6 | Partial; reducer suite and event replay gaps recorded |
| SysRS-236 audio verification | SRS-062 through SRS-083, SRS-125, SRS-135 | SWE.4, SWE.5, SWE.6, SYS.4 | Partial; platform evidence required |
| SysRS-237 secure storage verification | SRS-090 through SRS-095, SRS-126, SRS-137 | SWE.4, SWE.5, SYS.4 | Partial; Android DEK waiver and platform audit required |
| SysRS-238 diagnostic redaction verification | SRS-093 through SRS-102, SRS-126 | SWE.4, SWE.5, SWE.6 | Evidence required before external tester enablement |
| SysRS-239 release packaging verification | SRS-116 through SRS-123, SRS-127, SRS-138 | SWE.5, SYS.4, release record | Partial; source-build/unsigned limitations recorded |
| SysRS-240 public wording audit | SRS-122, SRS-137 and legal review | SYS.4, legal/trademark review | Blocked by DEC-012 sign-off |
| SysDes-102 protocol verification handoff | SRS-004, SRS-015, SRS-045 through SRS-052, SRS-097, SRS-100, SRS-123, SRS-128, SRS-131, SRS-134 | SWE.5, SWE.6, SYS.4 | Requires attached candidate evidence |
| SysDes-103 state verification handoff | SRS-058 through SRS-061, SRS-097, SRS-098, SRS-124, SRS-128 | SWE.4, SWE.5 | Partial; waiver recorded |
| SysDes-104 audio verification handoff | SRS-062 through SRS-083, SRS-099, SRS-125, SRS-128, SRS-135 | SWE.4, SWE.5, SWE.6, SYS.4 | Partial; platform evidence required |
| SysDes-105 security verification handoff | SRS-090 through SRS-096, SRS-101, SRS-102, SRS-126, SRS-128, SRS-137 | SWE.4, SWE.5, SYS.4 | Partial; audits required |
| SysDes-106 deployment verification handoff | SRS-116 through SRS-123, SRS-127, SRS-128, SRS-138 | SWE.5, SYS.4, release record | Partial; release blockers recorded |
| SysDes-107 MVP acceptance verification | SRS-128 | SWE.6 | Matrix exists; candidate evidence still required |
## 5. MVP Acceptance Trace
| SysRS acceptance range | Requirement group | SRS anchor | Verification anchor |
|---|---|---|---|
| SysRS-241 through SysRS-244 | Connection, channel tree, online clients, channel join | SRS-019 through SRS-024, SRS-045 through SRS-051, SRS-128 | SWE.6 MVP acceptance matrix |
| SysRS-245 through SysRS-253 | Send/receive voice, mute/deaf, PTT, audio processing | SRS-062 through SRS-083, SRS-125, SRS-128, SRS-197 through SRS-200 | SWE.4/SWE.5 audio evidence and SWE.6 matrix |
| SysRS-254 | Channel text | SRS-019, SRS-036 through SRS-038, SRS-170 through SRS-174, SRS-128 | SWE.6 matrix |
| SysRS-255 | Bookmarks | SRS-084 through SRS-089, SRS-128 | SWE.4 storage tests and SWE.6 matrix |
| SysRS-256 | Secure storage | SRS-090 through SRS-095, SRS-126, SRS-137 | Security audit and SYS.4 platform matrix |
| SysRS-257 | Redacted diagnostics | SRS-028, SRS-093 through SRS-102, SRS-126, SRS-128 | SWE.6 diagnostics evidence and security review |
## 6. Traceability Limitations for DV
| Limitation | Impact | Control |
|---|---|---|
| SAD and SDD are baseline candidates rather than fully item-numbered historical documents | Some prior references such as `SAD-043` and `SDD-109` are not reconstructed as itemized records | Treat the new SAD/SDD as DV baselines; add strict item IDs later if the process owner requires ID-level audit |
| Candidate run IDs are not embedded in the documents | Evidence is not yet auditable to a specific build | Release-readiness record requires run IDs before release approval |
| Some implementation status items may have changed after the status report | Risk of stale blocker statements | Waiver register calls out items that need revalidation |
## 7. DV Conclusion
Traceability is sufficient for DV document review if reviewers accept the SAD/SDD baseline-candidate depth limitation and require candidate run evidence before release approval.
-44
View File
@@ -1,44 +0,0 @@
# Chanora Localization Architecture
**Document status:** DV meeting baseline candidate
**Date:** 2026-05-29
## 1. Implementation Source
Localization is enabled through Flutter generation in `apps/chanora_flutter/pubspec.yaml` and generated files under `apps/chanora_flutter/lib/l10n/generated/`.
## 2. Architecture Rules
| Rule | Requirement |
|---|---|
| Product strings | User-visible product-owned strings should be localizable |
| Server content | Server names, channel names, nicknames, and messages are displayed as content, not translated |
| Unicode | UTF-8/Unicode content must be preserved through protocol, bridge, state, UI, logs, and diagnostics unless intentionally redacted |
| Fallback | Missing localization keys must have deterministic fallback behavior |
| Diagnostics | Machine-readable diagnostic keys remain language-neutral |
## 3. Current Locale Baseline
English and Simplified Chinese generated localization files are present in the current Flutter app tree.
## 4. Ownership and Coverage Criteria
| Criterion | Required result |
|---|---|
| Product-owned strings | New user-visible product strings are added to localization resources or explicitly justified as non-product content |
| Server-owned content | Server names, channel names, nicknames, and chat messages pass through untranslated |
| Fallback behavior | Missing-key behavior is deterministic and covered by test or generated-localization behavior review |
| Unicode preservation | Multilingual content is preserved across protocol, bridge, state, UI, logs, and diagnostics except where redaction intentionally removes content |
| Diagnostic keys | Machine-readable diagnostic keys remain stable and language-neutral |
## 5. Evidence Required Before Release
| Evidence | Purpose |
|---|---|
| Localization generation check | Confirms generated bindings are current |
| UI smoke in supported locales | Confirms critical screens render in English and Simplified Chinese |
| Unicode content test or demo | Confirms server-provided multilingual content is preserved |
## 6. DV Conclusion
Localization architecture is documented and reviewable. Additional locale expansion remains outside current release scope.
@@ -1,47 +0,0 @@
# Chanora Trademark and Attribution Review
**Document status:** DV meeting baseline candidate
**Date:** 2026-05-29
**Decision state:** DEC-012 remains open; public/store release blocked
## 1. Purpose
This document records the legal/trademark/attribution checks needed before Chanora can be publicly distributed. It supports DV review by making the open DEC-012 gate explicit.
## 2. Non-Affiliation Position
Chanora must present itself as an independent client application. It may describe compatibility with TeamSpeak 3-compatible servers where accurate, but it must not imply that Chanora is official, endorsed, sponsored, or affiliated with TeamSpeak or any trademark owner.
## 3. Required Wording Controls
| Surface | Required control |
|---|---|
| App About dialog | Include independent/non-affiliation wording and OSS license pointer |
| README and documentation | Use compatibility wording rather than official-product wording |
| Store metadata | Avoid official affiliation claims and review trademark usage |
| Release notes | Match actual supported capability and platform limitations |
| Website or marketing copy | Require legal review before publication |
## 4. Attribution and OSS Controls
| Topic | Required result before public/store release |
|---|---|
| Dependency license inventory | Rust and Flutter inventories generated and reviewed |
| NOTICE file | Required third-party attributions included |
| Dual-license statement | Chanora MIT OR Apache-2.0 licensing remains visible |
| Patched/forked dependencies | Forks and pinned revisions are documented with rationale |
| Trademark references | References are nominative, accurate, and reviewed |
## 5. Current Review State
| Item | State | Release impact |
|---|---|---|
| DEC-012 legal/trademark/OSS review | Open | Blocks public/store release |
| About dialog non-affiliation statement | Reported implemented in `docs/implementation-status-2026-05-28.md` | Needs final wording review |
| NOTICE pointer | Reported implemented in About dialog | Needs inventory/legal confirmation |
| Store metadata | Not approved in current record | Blocks store release |
| Public compatibility wording | Not approved in current record | Blocks public release |
## 6. DV Conclusion
Legal/trademark/attribution requirements are identified, but DEC-012 is not closed. DV may pass the document baseline only if public/store release remains No-Go.
-93
View File
@@ -1,93 +0,0 @@
# Chanora UI/UX Guideline — Material 3 Baseline
**Version:** 0.9.2
**Status:** Baseline Candidate
**Language:** English
**Lifecycle support:** Supports SysDes, SRS, SAD, SDD, and Verification
**Design baseline:** Material 3 + Chanora Design System
**Repo path:** `docs/ui-ux/material3-guideline.md` ---
## 1. Purpose
This guideline defines the UI and UX baseline for the Chanora Flutter application. Chanora shall use Material 3 as the foundation, but product-specific voice, channel, connection, latency, diagnostics, platform, and accessibility semantics shall be expressed through Chanora Design System components and tokens.
## 2. Core UI Principles
| Principle | Requirement |
|---|---|
| Voice-first control | Mute, deaf, push-to-talk, current channel, and input status must be visible or directly reachable. |
| Connection awareness | Connected, connecting, reconnecting, disconnected, and error states must be visible. |
| Adaptive layout | Layout must adapt by window class rather than hardcoding behavior by platform name. |
| Accessibility baseline | Critical controls must have semantics, focus behavior, text scaling support, and non-color-only status expression. |
| Platform respect | Permission, safe area, keyboard, back, haptic, and audio-route behavior must follow platform expectations. |
| Localization-ready | Product-owned strings must be localized; server-provided content must be displayed as content. |
## 3. Primary Screens
| Screen | Stage | Purpose |
|---|---|---|
| Home | P0 | Recent servers, bookmarks, manual connect entry |
| Connect | P0 | Host, port, nickname, password, identity selection |
| Server | P0 | Channel tree, clients, connection status, current channel |
| Voice | P0 | Voice controls, input level, device summary |
| Chat | P1 | Channel text messages |
| Settings | P0 | Audio, UI, localization, platform behavior, shortcuts |
| Diagnostics | P0 | Status, redacted export, troubleshooting information |
## 4. Interaction Rules
| Area | Rule |
|---|---|
| Channel tree | Select, expand/collapse, join, context menu, keyboard traversal |
| Client tile | Show speaking, mute/deaf, volume, latency when available |
| Voice controls | Must be reachable with touch, mouse, and keyboard |
| Diagnostics | Export must require explicit user action and show redaction notice |
| Settings | Destructive or permission-changing actions require clear confirmation or explanation |
| Text entry | Chat input must respect IME and keyboard safe areas |
## 5. Motion Rules
| Scenario | Allowed behavior |
|---|---|
| Page transition | Minimal fade or shared-axis style transition |
| Speaking indicator | Subtle pulse, disabled or simplified under reduced motion |
| Reconnect banner | Clear state transition without disruptive animation |
| Layout change | Resize/reflow smoothly where possible |
| Error state | Immediate, clear, non-color-only feedback |
## 6. Accessibility Rules
| Rule | Baseline |
|---|---|
| Minimum target | Critical controls should meet a 48dp target where practical. |
| Semantics | Icon-only controls require labels. |
| Focus | Desktop and tablet keyboard use require visible focus. |
| State expression | Critical states require more than color. |
| Text scale | Critical controls remain reachable under increased text size. |
| Reduced motion | Non-essential animation is reduced or disabled. |
## 7. Internationalization UX
Product strings are localized. Server-provided server names, channel names, nicknames, and messages are not translated. Mixed-language and bidirectional text must be rendered as text content and preserved through diagnostics unless redacted.
## 8. Change History
| Version | Date | Description |
|---|---|---|
| 0.1.0 | 2026-05-14 | Initial UI/UX guideline for Material 3, adaptive layout, accessibility, platform behavior, and i18n. |
## Baseline Candidate 0.9.1 Update
| Version | Date | Description |
|---|---|---|
| 0.9.1 | 2026-05-14 | Updated baseline after product decision closure: Apple App Store SDK gate uses Xcode 26+ and iOS 26 / iPadOS 26 SDK+ since 2026-04-28, platform baselines and decision traceability propagated across the document set. |
## Baseline Candidate 0.9.2 Update
| Version | Date | Description |
|---|---|---|
| 0.9.2 | 2026-05-14 | Corrected Apple App Store Connect upload gate to 2026-04-28 and checked full-package naming, references, and coverage. |
-280
View File
@@ -1,280 +0,0 @@
# ReSpeak Project Knowledge Base
> **Source**: https://github.com/ReSpeak/tsclientlib
> **Last synced**: 2026-06-13
> **License**: MIT OR Apache-2.0
## Overview
ReSpeak is an open-source project that provides a Rust implementation of the **TeamSpeak 3 protocol**. The primary goal is to enable building TeamSpeak clients and bots in Rust. The project is **not** an official TeamSpeak product — it was created for fun and to gain features/bugfixes not available in the official client.
The organization maintains a single monorepo (`ReSpeak/tsclientlib`) containing multiple crates that layer from low-level protocol handling up to a high-level client library.
**Key principle**: ReSpeak does **not** publish server-side code. They earn revenue by selling servers and ReSpeak respects that business model.
## Repository Map
| Crate | Path | Purpose | Version |
|-------|------|---------|---------|
| `tsclientlib` | `tsclientlib/` | High-level client/bot library | 0.2.0 |
| `tsproto` | `tsproto/` | Low-level TeamSpeak 3 protocol implementation | 0.2.0 |
| `ts-bookkeeping` | `utils/ts-bookkeeping/` | Server state tracking (clients, channels) | 0.1.x |
| `tsproto-packets` | `utils/tsproto-packets/` | Packet and command parsing/serialization | 0.1.x |
| `tsproto-types` | `utils/tsproto-types/` | Core types, enums, crypto primitives | 0.1.x |
| `tsproto-structs` | `utils/tsproto-structs/` | Generated structs from tsdeclarations | 0.1.x |
**External dependency**: [tsdeclarations](https://github.com/ReSpeak/tsdeclarations) — machine-readable TeamSpeak protocol declarations (embedded as git submodule).
## tsclientlib
### Architecture
`tsclientlib` is the **top-level crate** — the one consumers use. It provides:
- `Connection` struct: manages a single connection to a TeamSpeak server
- Async API built on `tokio` + `futures`
- DNS SRV resolution for server discovery (`resolver.rs`)
- Audio handling via `audiopus` (Opus codec) behind the `audio` feature flag
- Sync wrapper (`sync.rs`) for non-async contexts
- Prelude module for convenient imports
### Features
| Feature | Default | Description |
|---------|---------|-------------|
| `audio` | yes | Opus encode/decode, `AudioHandler` for jitter buffer + mixing |
| `unstable` | no | Expose internal protocol API (may break on minor releases) |
| `default-tls` | yes | reqwest with default TLS for HTTP/HTTPS |
| `bundled` | no | Bundle SDL2 |
| `static-link` | no | Statically link SDL2 |
| `audiopus-unstable` | no | Extended audiopus API from Flakebi's fork |
### Key Dependencies
- `tsproto` — protocol layer
- `ts-bookkeeping` — state management
- `tsproto-packets` — packet parsing
- `tsproto-types` — types + crypto
- `tokio` — async runtime
- `hickory-proto` / `hickory-resolver` — DNS resolution
- `reqwest` — HTTP client
- `audiopus` — Opus codec (optional)
### Source Files
| File | Purpose |
|------|---------|
| `lib.rs` | Core types, re-exports, `Connection` entry point |
| `audio.rs` | Audio subsystem — Opus encode/decode, `AudioHandler` |
| `resolver.rs` | DNS SRV resolution for TeamSpeak servers |
| `sync.rs` | Synchronous wrapper API |
| `prelude.rs` | Convenience re-exports |
| `tests.rs` | Integration tests |
### Examples
- `simple.rs` — minimal async client
- `simple-sync.rs` — minimal sync client
- `audio.rs` — audio streaming client
- `audio-latency.rs` — latency measurement
- `channeltree.rs` — channel navigation
- `many.rs` / `sync.rs` — stress tests
## tsproto
### Architecture
`tsproto` implements the **low-level TeamSpeak 3 protocol**:
- Connection establishment and handshake
- UDP packet delivery with reliability (resend logic)
- Packet encryption and compression
- Command parsing
### Source Files
| File | Purpose |
|------|---------|
| `algorithms.rs` | Packet splitting, encryption/decryption, compression, hash cash |
| `client.rs` | Client-side connection logic |
| `connection.rs` | Connection state machine, packet queuing |
| `packet_codec.rs` | Packet encoding/decoding codec |
| `resend.rs` | Reliable packet delivery with retransmission |
| `license.rs` | License system implementation |
| `log.rs` | Logging utilities |
| `utils.rs` | Helper functions |
### Protocol Details
#### Packet Types
| Type | Description |
|------|-------------|
| `Command` | High-priority commands |
| `CommandLow` | Low-priority commands |
| `Voice` | Voice data |
| `VoiceWhisper` | Whisper voice data |
| `Ack` / `AckLow` | Acknowledgments |
| `Ping` / `Pong` | Keepalive |
| `Init` | Connection initialization |
#### Packet Limits
- **Max UDP packet size**: 1500 bytes (ethernet MTU)
- **Max command packet size**: 500 bytes (including header)
- **Max fragments length**: 40960 bytes
- **Max decompressed size**: 2 MiB (for large servers with 2000+ channels)
- **Max out-of-order queue**: 200 packets
#### Compression
- Uses **QuickLZ** level 1 for command packets
- Compression only applied if result is smaller than original
- Fragmentation occurs when compressed data exceeds 500 bytes
### Cryptography
#### Key Types
| Type | Curve | Usage |
|------|-------|-------|
| `EccKeyPubP256` | P-256 (secp256r1) | Public identity key |
| `EccKeyPrivP256` | P-256 | Private identity key |
| `EccKeyPubEd25519` | Ed25519 | Public ephemeral key (handshake) |
| `EccKeyPrivEd25519` | Ed25519 | Private ephemeral key (handshake) |
#### Encryption Algorithm
1. **Key derivation**: `SHA-256(packet_type || generation_id || shared_iv)` → 16-byte key + 16-byte nonce
2. **Cipher**: AES-128 in EAX mode with 8-byte MAC
3. **Key caching**: Derived keys are cached per generation to avoid recomputation
4. **Packet ID mixing**: `key[0] ^= (packet_id >> 8)`, `key[1] ^= (packet_id & 0xff)`
#### Shared IV Computation (`compute_iv_mac`)
1. ECDH shared secret via Ed25519
2. `shared_iv = SHA-512(shared_secret)`
3. XOR with `alpha` (10 bytes) and `beta` (54 bytes) from handshake
4. `shared_mac = SHA-1(shared_iv)[..8]`
#### Hash Cash (Identity Proof-of-Work)
- Identity level = number of leading zero bits in `SHA-1(public_key_string || counter)`
- `upgrade_level(target)` iterates counter until desired level is reached
- Default target level: 8
#### Identity Format
```
Format: counter || 'V' || base64(private_key)
Example: "2792354VMG8DAgeAAgEgAiEA..."
```
#### Fake Encryption
- Used for unencrypted packet types (voice, ack, ping, etc.)
- Fixed key: `c:\windows\syste` (16 bytes)
- Fixed nonce: `m\firewall32.cpl` (16 bytes)
## ts-bookkeeping
Tracks the **server state** by processing incoming commands:
- Maintains client list, channel tree, server info
- Generates events from state changes
- Provides methods to create outgoing command packets
- Main struct: `data::Connection`
## tsproto-packets
Handles **packet serialization/deserialization**:
- `packets.rs` — packet structures (`InPacket`, `OutPacket`, `OutAck`, etc.)
- `commands.rs` — TeamSpeak command parsing
- Header constants: `C2S_HEADER_LEN`, `S2C_HEADER_LEN`
## tsproto-types
Core **types and primitives**:
- `crypto.rs` — ECC key types (P-256, Ed25519), ECDH, signatures, identity obfuscation
- `versions.rs` — TeamSpeak version strings
- `errors.rs` — Protocol error codes
### Key Crypto Functions
| Function | Description |
|----------|-------------|
| `EccKeyPrivP256::create()` | Generate new P-256 keypair |
| `EccKeyPrivP256::import_str()` | Import from base64/tomcrypt/obfuscated formats |
| `EccKeyPrivP256::create_shared_secret()` | ECDH with P-256 |
| `EccKeyPrivP256::sign()` | ECDSA signature |
| `EccKeyPubP256::verify()` | ECDSA verification |
| `EccKeyPubP256::get_uid()` | `base64(SHA-1(ts_encoded_key))` |
| `encode_password()` | `base64(SHA-1(password))` |
| `EccKeyPrivEd25519::create_shared_secret()` | ECDH with Ed25519 |
### Identity Obfuscation
TeamSpeak stores identities XOR'd with a static 128-byte pattern + SHA-1 hash of trailing data. ReSpeak implements both obfuscation and deobfuscation.
## How Chanora Uses ReSpeak
Chanora depends on **four crates** from the ReSpeak monorepo, all pinned to revision `04aa2491`:
### Dependency Chain
```
chanora_protocol/
├── tsclientlib (rev 04aa2491, features=["audio"])
├── tsproto-packets (rev 04aa2491)
├── tsproto-types (rev 04aa2491)
└── ts-bookkeeping (rev 04aa2491)
chanora_audio/
└── tsclientlib (rev 04aa2491, features=["audio"])
```
### Architectural Constraint (SAD-067 / SysDes-011 / SysDes-029)
Chanora's `chanora_protocol` crate acts as an **isolation boundary**:
> No tsclientlib types may cross out of this crate.
This prevents ReSpeak API changes from cascading through Chanora's codebase.
### Patched Fork
Chanora patches `tsproto-types` to fix **P-256 short coordinate padding**:
```toml
[patch."https://github.com/ReSpeak/tsclientlib.git"]
tsproto-types = { git = "https://github.com/EdisonJwa/tsclientlib.git", branch = "fix/p256-short-coordinate-pad" }
```
This handles cases where P-256 coordinates are shorter than 32 bytes and need left-padding.
### Key Usage Points
1. **Protocol connection**: `tsclientlib::Connection` for TeamSpeak server connections
2. **Audio handling**: `AudioHandler` from tsclientlib for decode, jitter buffer, mixing
3. **Packet types**: `tsproto-packets` for `OutAudio`, `InAudioBuf`, `AudioData`, `CodecType`, `Direction`
4. **State tracking**: `ts-bookkeeping` for server state management
## External References
- **Qint** (https://github.com/ReSpeak/Qint) — Cross-platform TeamSpeak client built on tsclientlib (not yet ready)
- **SimpleBot** (https://github.com/ReSpeak/SimpleBot) — Example chat bot
- **tsdeclarations** (https://github.com/ReSpeak/tsdeclarations) — Machine-readable protocol declarations
- **TSIdentityTool** (https://github.com/landave/TSIdentityTool) — Identity deobfuscation reference (MIT)
## Performance Benchmarks
From i7-5280K @ 3.6 GHz (single-threaded):
| Operation | Time | Throughput |
|-----------|------|------------|
| Connection creation | 199 ms | 6.5 conn/sec |
| Message send | 189 µs | 5300 msg/sec |
Bottleneck: RSA puzzle solving at connection time. Use `--features rug` for efficient big integer implementation.
-392
View File
@@ -1,392 +0,0 @@
# TeaSpeak Project Knowledge Base
## Overview
TeaSpeak is an open-source, TeamSpeak-compatible voice communication platform hosted at `https://git.did.science/TeaSpeak`. It consists of two main repositories:
- **TeaSpeak-Client** — An Electron-based desktop client (329 commits, created May 2020)
- **TeaSpeakLibrary** — A C++ shared library providing core protocol, channel, and database functionality (208 commits, created May 2020)
The project is developed by WolverinDEV / TeaSpeak and targets users who need a self-hosted, TeamSpeak-compatible voice chat solution.
## Architecture
### Two-Repository Design
```
TeaSpeak/
├── TeaSpeak-Client/ # Electron desktop application
│ ├── main.ts # Entry point (Electron main process)
│ ├── modules/ # TypeScript modules (core, renderer, shared, crash_handler)
│ ├── native/ # C++ native addons (Node.js N-API)
│ │ ├── serverconnection/ # Server connection & audio engine
│ │ ├── codec/ # Opus codec bindings
│ │ ├── crash_handler/ # Native crash handling
│ │ ├── dns/ # DNS resolution
│ │ ├── ppt/ # Protocol handling
│ │ └── updater/ # Auto-updater
│ ├── imports/ # Shared TypeScript definitions & vendor libs
│ └── resources/ # Static assets
└── TeaSpeakLibrary/ # C++ static library
├── CMakeLists.txt # CMake build system
├── src/
│ ├── protocol/ # TeamSpeak protocol implementation
│ ├── channel/ # Channel tree management
│ ├── query/ # Server query protocol
│ ├── sql/ # SQLite & MySQL database layer
│ ├── ssl/ # SSL/TLS support
│ ├── bbcode/ # BBCode parsing
│ └── misc/ # Utilities (crypto, networking, etc.)
└── test/ # Unit tests
```
### Client Architecture (Electron)
The client uses a multi-process Electron architecture:
- **Main Process** (`modules/core/main.ts`) — App lifecycle, window management, crash handling
- **Renderer Process** (`modules/renderer/`) — UI rendering, audio controls, connection management
- **Shared Module** (`modules/shared/`) — IPC definitions, version info, proxy utilities
- **Native Addons** (`native/`) — C++ bindings for performance-critical operations
Key TypeScript path aliases:
- `tc-shared/*``imports/shared-app/*`
- `tc-native/connection``native/serverconnection/exports/exports.d.ts`
## Features
### Voice Communication
- Opus audio codec support (encoder/decoder)
- Audio input/output with gain control and level metering
- Audio mixing and interleaving
- Voice activity detection (VAD) via libfvad
- Audio filtering and processing pipeline
- Sound file playback capabilities
### Server Protocol
- TeamSpeak protocol compatibility
- Custom protocol handler with crypto support (ProtocolHandlerCrypto)
- Packet acknowledgement and loss calculation
- Ring buffer for reliable packet delivery
- QuickLZ compression
- Hardware ID (HWID) generation for client identification
### Channel System
- Tree-based channel hierarchy (TreeView)
- Channel properties and permissions
- BBCode formatting support
### Data & Storage
- SQLite database support
- MySQL database support
- Client storage and profiles
- File transfer capabilities
- Connection logging
### Client Features
- Auto-updater
- Crash handler with Sentry integration
- Window management and system tray
- Keyboard shortcuts
- Context menus
- i18n (internationalization)
- Music playback
- URL preview
## Technology Stack
### Client (TeaSpeak-Client)
| Component | Technology |
|-----------|-----------|
| Runtime | Electron 8.5.5 |
| Language | TypeScript 3.9, C++ |
| UI | HTML/CSS, jQuery, EJS templates |
| Styling | SASS |
| Native addons | cmake-js, Node.js N-API |
| Build | electron-packager |
| Error tracking | Sentry |
### Library (TeaSpeakLibrary)
| Component | Technology |
|-----------|-----------|
| Language | C++20 |
| Build system | CMake 3.6+ |
| Crypto | TomCrypt, TomMath, OpenSSL, Ed25519 |
| Compression | QuickLZ |
| Database | SQLite3, MySQL Connector/C++ |
| Logging | spdlog |
| Events | libevent |
| Audio | Opus |
| JSON | jsoncpp |
| Serialization | Protocol Buffers |
| Memory | jemalloc |
| Crash reporting | Breakpad |
| Terminal | CXXTerminal (server mode) |
| Threading | Custom ThreadPool |
| String templating | StringVariable |
| Networking | DataPipes (includes libnice for ICE) |
### External Dependencies (from libraries.txt)
- PortAudio — Cross-platform audio I/O
- libfvad — Voice activity detection
- SoXR — High-quality sample rate conversion
## Protocol / API
### TeamSpeak Protocol Implementation
The protocol layer (`TeaSpeakLibrary/src/protocol/`) implements:
- **Packet** — Core packet structure and serialization
- **CryptHandler** — Encryption/decryption for secure communication
- **CompressionHandler** — QuickLZ-based packet compression
- **AcknowledgeManager** — Reliable delivery with ACK tracking
- **PacketLossCalculator** — Network quality monitoring
- **RingBuffer** — Circular buffer for packet ordering
- **Generation** — Protocol version/generation handling
### Server Connection (Client Side)
The native server connection module (`native/serverconnection/`) handles:
- **ServerConnection** — Main connection state machine
- **ProtocolHandler** — Full protocol implementation split across:
- `ProtocolHandlerCommands.cpp` — Command processing
- `ProtocolHandlerCrypto.cpp` — Crypto handshake
- `ProtocolHandlerPOW.cpp` — Proof of work (anti-spam)
- `ProtocolHandlerPackets.cpp` — Packet serialization
- **Socket** — TCP/UDP socket management
- **Audio subsystem** — Codec, drivers, filters, processing
### Query Protocol
Server query support (`src/query/`) with:
- Command parsing (v2 and v3 formats)
- Escape sequence handling
## Build & Configuration
### Building TeaSpeakLibrary
```bash
# Prerequisites: CMake 3.6+, C++20 compiler, OpenSSL, MySQL, etc.
mkdir build && cd build
cmake .. -DTEASPEAK_SERVER=ON
make -j$(nproc)
# Build tests (optional)
cmake .. -DBUILD_TESTS=ON
make -j$(nproc)
```
### Building TeaSpeak-Client
```bash
# Install dependencies
npm install
# Compile TypeScript
npm run compile-tsc
# Compile SASS
npm run compile-sass
# Generate JSON validators
npm run compile-json-validator
# Build for Linux
npm run build-linux-64
npm run package-linux-64
# Build for Windows
npm run build-windows-64
npm run package-windows-64
# Development mode
npm run start-s # Connects to localhost:8080
```
### Environment Variables
- `teaclient_deploy_secret` — Deployment signing key (in `env.sh`)
### Platform-Specific Dependencies
- **Linux**: electron-installer-debian
- **Windows**: electron-installer-windows, electron-winstaller, electron-wix-msi, rcedit
## Key Concepts
### Protocol Concepts
- **HWID** (Hardware ID) — Unique machine identifier for client authentication
- **POW** (Proof of Work) — Anti-spam mechanism in connection handshake
- **Ring Buffer** — Circular buffer for managing packet ordering and retransmission
- **Acknowledge Manager** — Tracks packet delivery confirmation
- **Packet Loss Calculator** — Monitors network quality metrics
### Audio Concepts
- **Opus Converter** — Handles Opus encoding/decoding
- **Audio Gain** — Volume amplification/attenuation
- **Audio Level Meter** — Real-time audio level monitoring
- **Audio Merger** — Combines multiple audio streams
- **Audio Interleaved** — Audio frame interleaving for transmission
- **Audio Event Loop** — Async audio processing pipeline
- **VAD** (Voice Activity Detection) — Detects speech vs silence
### Channel Concepts
- **TreeView** — Hierarchical channel structure (parent/child relationships)
- **BBCode** — Text formatting markup (TeamSpeak standard)
- **Permission Manager** — Role-based access control
### Connection Concepts
- **ServerConnection** — Full connection lifecycle management
- **Command Handler** — Processes server commands/responses
- **Handshake Handler** — Initial connection negotiation
- **Voice Connection** — Audio stream management
- **Video Connection** — Video stream support
- **Dummy Voice Connection** — Placeholder/mock for testing
## Source Repository Structure
### TeaSpeak-Client Root
```
.
├── .gitignore
├── .gitmodules
├── bugs # Bug tracking
├── build_declarations.sh # Build script for type declarations
├── env.sh # Environment variables
├── generate-json-validators.sh # JSON schema validation generator
├── libraries.txt # External library references
├── main.ts # Electron entry point
├── package.json # Node.js dependencies & scripts
├── package-lock.json
├── restore.sh # Restore script
├── tsconfig.json # TypeScript configuration
├── tsconfig_render_api.json # Renderer API TypeScript config
├── imports/ # Shared TypeScript types & vendor code
│ ├── shared-app/ # Application-level shared types
│ │ ├── audio/ # Audio type definitions
│ │ ├── backend/ # Backend interfaces
│ │ ├── clientservice/ # Client service definitions
│ │ ├── connection/ # Connection type definitions
│ │ │ └── rtc/ # WebRTC-related types
│ │ ├── connectionlog/ # Connection logging
│ │ ├── conversations/ # Chat/conversation types
│ │ ├── crypto/ # Crypto interfaces
│ │ ├── entry-points/ # Module entry points
│ │ ├── events/ # Event definitions
│ │ ├── file/ # File handling types
│ │ ├── i18n/ # Internationalization
│ │ ├── ipc/ # IPC message definitions
│ │ ├── media/ # Media handling
│ │ ├── music/ # Music playback
│ │ ├── permission/ # Permission types
│ │ ├── profiles/ # User profiles
│ │ ├── text/ # Text processing
│ │ ├── tree/ # Tree data structures
│ │ ├── ui/ # UI component types
│ │ └── update/ # Update mechanism
│ ├── svg-sprites/ # SVG icon sprites
│ └── vendor/ # Third-party libraries
│ ├── TeaEventBus/ # Event bus implementation
│ └── TeaClientServices/ # Client services
├── installer/ # Build & packaging scripts
├── jenkins/ # CI/CD pipeline
├── modules/ # TypeScript source modules
│ ├── core/ # Main process
│ │ ├── app-updater/ # Auto-update logic
│ │ ├── main-window/ # Main window management
│ │ ├── render-backend/ # Renderer backend
│ │ ├── ui-loader/ # UI loading
│ │ ├── url-preview/ # URL preview
│ │ └── windows/ # Window definitions
│ ├── crash_handler/ # Crash handling
│ ├── renderer/ # Renderer process
│ │ ├── audio/ # Audio controls UI
│ │ ├── connection/ # Connection UI
│ │ ├── dns/ # DNS resolution
│ │ └── hooks/ # React-like hooks
│ ├── renderer-manifest/ # Renderer configuration
│ └── shared/ # Shared utilities
│ ├── ipc/ # IPC implementation
│ ├── process-arguments/ # CLI argument parsing
│ ├── proxy/ # Proxy utilities
│ └── version/ # Version management
├── native/ # C++ native addons
│ ├── cmake/ # CMake modules
│ ├── codec/ # Audio codec (Opus)
│ │ └── codec/ # Codec implementation
│ ├── crash_handler/ # Native crash handler
│ ├── dist/ # Distribution files
│ ├── dns/ # DNS resolver
│ ├── ppt/ # Protocol tools
│ ├── serverconnection/ # Server connection module
│ │ ├── exports/ # TypeScript declarations
│ │ ├── src/
│ │ │ ├── audio/ # Audio engine
│ │ │ │ ├── codec/ # Opus encoder/decoder
│ │ │ │ ├── driver/ # Audio drivers
│ │ │ │ ├── file/ # Audio file I/O
│ │ │ │ ├── filter/ # Audio filters
│ │ │ │ ├── js/ # JS audio bindings
│ │ │ │ ├── processing/ # Audio processing
│ │ │ │ └── sounds/ # Sound effects
│ │ │ └── connection/ # Protocol implementation
│ │ │ ├── audio/ # Audio connection
│ │ │ └── ft/ # File transfer
│ │ └── test/ # Connection tests
│ └── updater/ # Auto-updater native code
├── resources/ # Static resources
└── scripts/ # Build/utility scripts
```
### TeaSpeakLibrary Root
```
.
├── CMakeLists.txt # Build configuration
├── main.cpp # Test entry point
├── src/
│ ├── bbcode/ # BBCode parser
│ ├── channel/ # Channel tree (TreeView)
│ ├── converters/ # Data converters
│ ├── lock/ # Read-write mutex
│ ├── log/ # Logging utilities
│ ├── misc/ # Utilities
│ │ ├── base64.* # Base64 encoding
│ │ ├── digest.* # Hash digests
│ │ ├── hex.* # Hex encoding
│ │ ├── memtracker.* # Memory tracking
│ │ ├── net.* # Network utilities
│ │ └── rnd.* # Random number generation
│ ├── protocol/ # TeamSpeak protocol
│ │ ├── AcknowledgeManager.* # ACK tracking
│ │ ├── CompressionHandler.* # QuickLZ compression
│ │ ├── CryptHandler.* # Encryption
│ │ ├── Packet.* # Packet structure
│ │ ├── PacketLossCalculator.* # Loss monitoring
│ │ ├── buffers.* # Buffer management
│ │ ├── generation.* # Protocol generation
│ │ └── ringbuffer.* # Circular buffer
│ ├── qlz/ # QuickLZ compression library
│ ├── query/ # Server query protocol
│ ├── sql/ # Database layer
│ │ ├── sqlite/ # SQLite implementation
│ │ └── mysql/ # MySQL implementation
│ ├── ssl/ # SSL/TLS management
│ ├── BasicChannel.* # Base channel class
│ ├── Definitions.h # Global definitions
│ ├── Error.* # Error handling
│ ├── EventLoop.* # Event loop
│ ├── License.* # License management
│ ├── PermissionManager.* # Permission system
│ ├── Properties.* # Property system
│ └── Variable.* # Variable system
└── test/ # Unit tests
├── RingTest.cpp
├── CommandTest.cpp
├── ChannelTest.cpp
├── PermissionTest.cpp
└── ...
```
-348
View File
@@ -1,348 +0,0 @@
# YaTQA Wissensdatenbank (Deutsch)
> Quelle: https://yat.qa/ — Abgerufen: 13.06.2026
> Version: v3.9.9b (01. Mrz 2023)
## Überblick
**YaTQA** (Yet Another TeamSpeak³ Query Admin Tool) ist eine Windows-Anwendung zur Verwaltung von **TeamSpeak-3-Servern und -Instanzen** über das ServerQuery-Interface. Es bietet eine grafische Oberfläche für alle Query-Befehle und macht das Erlernen der rohen Query-Syntax überflüssig.
- **Autor:** Janni „Яedeemer" K. (Norddeutschland)
- **Sprache:** Geschrieben in Delphi 2009 (über 50.000 Zeilen Quelltext)
- **Entwicklungsbeginn:** 10. April 2011
- **Erstveröffentlichung:** 29. Juni 2011
- **Lizenz:** Kostenlos und voll funktionsfähig (keine Adware/Spyware)
- **Plattformen:** Windows XP und neuer, Linux mittels Wine
- **Größe:** ~1,3 MiB Installer
- **Enthaltene Sprachen:** Deutsch und Englisch (Auswahl während der Installation)
- **Unterstützte Server:** TeamSpeak 3.9.0 bis 3.13.7, TeaSpeak 1.4.10-beta
- **Download:** https://dl.yat.qa/stable/
- **Website:** https://yat.qa/
### Motto
*„Dinosaurier haben kein TeamSpeak benutzt und sind vor 66 Millionen Jahren ausgestorben. Zufall? Vermutlich nicht."*
---
## Funktionen
**YaTQA unterstützt alle ServerQuery-Funktionen ohne Ausnahme.** Die folgende Liste beschränkt sich auf Funktionen, die der normale TS-Client nicht bietet.
### Allgemeine Funktionen (Kein Admin erforderlich)
- **DNS-Auflösung:** Detaillierte Visualisierung der DNS-Auflösung (simuliert 10 verschiedene Client-Versionen)
- **Blacklist-Prüfung:** TeamSpeaks Blacklist auf eine IP überprüfen
- **Blacklist2:** TeamSpeaks Blacklist2 für virtuelle Server prüfen
- **Benutzerdiagramm:** Serverstatistiken von Planet TeamSpeak als Diagramm anzeigen und als PNG speichern
- **Client-Cache:** Avatare, Icons und Chatlogs im Client-Cache finden
### Konsole (Query-Interface)
- **Autovervollständigung:** Befehlsvervollständigung einschließlich undokumentierter Befehle
- **Parameterhilfe:** Zeigt alle Parameter eines Befehls basierend auf eigener Forschung
- **Werteauswahl:** Strg+Leertaste für Werteliste
- **Ergebnisanalyse:** Gruppierte Datensätze mit Erklärungen
- **Skripting:** Befehlslisten aus Dateien laden und ausführen
- **Events:** Server-Events abonnieren und in der Konsole protokollieren
### SSH-Tunnel
- **Verschlüsselung:** Vollständig verschlüsselte Verbindung (außer Dateiübertragungen)
- **Geschwindigkeit:** Auf vielen Servern merkbar schneller (ähnlich wie `tcp_nodelay`)
- **Privatsphäre:** IP wird immer verborgen (man erscheint als 127.0.0.1)
- **Flood-Umgehung:** Umgeht alle Flood-Beschränkungen (127.0.0.1 steht üblicherweise auf der Whitelist)
### Instanz-Funktionen (Erfordert serveradmin)
- Instanzstatistiken anzeigen/bearbeiten
- Lizenzdetails und IP-Bindings anzeigen
- Alle virtuellen Server anzeigen
- Lokale Notizen zu Servern erstellen (lokal gespeichert)
- Virtuelle Server starten/stoppen/erstellen/löschen/umbenennen
- Unsichtbar werden (Server-Fehler, könnte behoben werden)
- Nachricht an alle Server senden
- Snapshots erstellen/massenweise erstellen/wiederherstellen (inkl. Dateien)
- Manipulierte Snapshots einspielen
- Server mittels Snapshots kopieren
- Rechte auf Vorlagengruppen zurücksetzen
- Channel-Datei-Backups speichern/wiederherstellen (inkrementelles Backup unterstützt)
### Funktionen für virtuelle Server
- Host-Message-Modal-Quit und hohe Sicherheitsstufe ignorieren
- Sehr detaillierte Serverstatistiken
- Mehrere Server gleichzeitig bearbeiten
- Ausklappbarer Serverbaum (optional immer im Vordergrund)
- Mehrere Nutzer gleichzeitig verschieben/kicken/bannen/beschreiben
- Mehrere Channel gleichzeitig erstellen
- Channel als Vorlage für weitere verwenden
- Mehrere Channel gleichzeitig bearbeiten
- Nachrichten an mehrere Nutzer/Channel gleichzeitig senden
- Rechte mehrerer Nutzer/Channel gleichzeitig bearbeiten
- Dateien zwischen Channeln verschieben
- Bildvorschau ohne Download (bmp, gif, jpg, png, pbm, pgm, ppm, xbm, xpm)
- Upload/Download ganzer Ordnerstrukturen
- Nutzer zu Gruppen hinzufügen durch Namenseingabe
- Funktionierende Rechteübersicht mit Echtzeitbearbeitung
- Rechte zwischen Servern/Instanzen kopieren
- Rechtewerte und -powers vergleichen
- Alle Clients/Gruppen mit einem bestimmten Recht finden
- Mehrere Gruppen gleichzeitig bearbeiten
- Verbesserte Clientdatenbank mit mehr Details und Suchfunktionen
- Gesamte Clientdatenbank mit einem Klick herunterladen
- Clientdatenbank als HTML oder CSV exportieren
- Gebannte Nutzer und IP-teilende Profile hervorheben
- Log an beliebiger Stelle lesen
- User CustomInfo verwalten (suchen, anzeigen, bearbeiten, hinzufügen)
- Log als HTML oder TXT exportieren
- Avatare und Icons herunterladen
- Avatar-Besitzer auf dem Server identifizieren
- Servervorlage verwalten
- Uploads/Downloads überwachen
### Unterstützte Bildformate
| Format | Beschreibung |
|--------|-------------|
| bmp | Windows Bitmap |
| gif | Graphics Interchange Format |
| jpg/jpeg | Joint Photographic Experts Group |
| png | Portable Network Graphics |
| pbm | Portable Bitmap (ASCII und binär) |
| pgm | Portable Graymap (ASCII und binär) |
| ppm | Portable Pixmap (ASCII und binär) |
| xbm | X BitMap |
| xpm | X PixMap |
---
## Architektur / Funktionsweise
### Verbindungsmethoden
- **Raw TCP/Telnet:** Standard-Query-Verbindung (Standardport 10011)
- **YaTQA-SSH-Tunnel:** Über Plink (PuTTY-Suite) — verschlüsselt, schneller, IP verborgen
- **TeamSpeak SSH:** Natives TS3.3+-SSH (auch unterstützt, aber weniger Vorteile)
### Datenspeicherung
- **Portable Modus:** Alle Daten im Installationsverzeichnis (`yatqa.ini` vorhanden)
- **Standardmodus:** Einige Dateien in `%APPDATA%\YaTQA`
- **Icon-Cache:** 16-Bit-RES-Format (`icons.res`)
- **Befehlsverlauf:** `commandhistory.txt`
- **Debug-Log:** `RedeemerTS3.log` (erstellt mit `-debug`-Schalter)
### DNS-Auflösung
YaTQA simuliert die Auflösungsschritte des TeamSpeak-Clients und zeigt sie visuell an. Verwendet Googles DNS-Server für Zuverlässigkeit. Unterstützt:
- A- und CNAME-Einträge
- SRV-Einträge
- TSDNS-Auflösung
- Alle 10 verschiedenen Client-Version-DNS-Verhaltensweisen
### Snapshot-System
- Snapshots enthalten alle Servereinstellungen (außer Port und Server-ID)
- Snapshots enthalten KEINE Dateien, Icons oder Avatare
- Datei-Backups enthalten Dateien und Icons (keine Avatare wegen Serverbeschränkungen)
- Pseudo-Snapshots ermöglichen Serverkopien ohne Keypair
- Unterstützt Zstd-komprimierte Snapshots (3.10.0+-Format)
### Anti-Flood-Schutz
- Konfigurierbare „Befehle bis Flood"-Einstellung (empfohlen: ~20)
- Konfigurierbare Verzögerung zwischen Befehlen (empfohlen: 340ms für fremde Server)
- SSH-Verbindungen umgehen Flood-Beschränkungen (127.0.0.1 auf Whitelist)
---
## Konfiguration
### Anwendungseinstellungen
| Einstellung | Beschreibung |
|------------|-------------|
| Verbesserte XP-Unicode-Anzeige | Verwendet Arial Unicode MS für bessere CJK-Unterstützung |
| Daten bei Tabwechsel aktualisieren | Automatisch Daten aktualisieren |
| Lokale Zeit verwenden | Lokale Zeit statt UTC |
| Verbesserte Channel-Dropdowns | Baumansicht für Unterchannel |
| In den Tray minimieren | Minimieren in den Systemtray |
| Tray-Icon immer anzeigen | Permanent anzeigen |
| Icon-Caching aktivieren | Icons in `icons.res` cachen (empfohlen) |
| Keine Icons verwenden | Icon-Anzeige deaktivieren |
| Windows Aero verwenden | Aero-Design nutzen (Vista+) |
| Aero-Glow deaktivieren | Weißen Schatten hinter Menütext entfernen |
| Beim Start nach Updates suchen | Automatisch nach Updates suchen |
| Sortiereinstellungen speichern | Sortierpräferenzen merken |
| Sprunglisten aktivieren | Windows 7+-Sprunglisten-Integration |
### Kompatibilitätseinstellungen
| Einstellung | Beschreibung |
|------------|-------------|
| Befehle bis Flood | Verzögerung zwischen Befehlen (340 empfohlen für fremde Server) |
| Nicht-Standard-Query-Port erlauben | Verbindung zu anderen Ports als 10011 |
| Löschen wichtiger Gruppen erlauben | Löschen der ersten 5 Server-/4 Channelgruppen erlauben |
| Verlassen wichtiger Gruppen erlauben | serveradmin darf Admin Server Query verlassen |
| Machine-ID ändern erlauben | Änderung der Machine-ID ermöglichen |
### SSH-Tunnel-Profile
SSH-Profile für Server konfigurieren. Bei Verbindung zu einem Server mit passendem SSH-Profil verwendet YaTQA automatisch den Tunnel.
### Kreisdiagramm-Styles
Auswahl aus 4 verschiedenen Kreisdiagramm-Styles (durch Benutzerabstimmung ausgewählt).
---
## Startparameter
| Parameter | Beschreibung |
|-----------|-------------|
| `-a` | Verbindung zum Standardserver |
| `-b [IP]` | Blacklist-Prüfung |
| `-c IP Query_Port [User Pass [Voice_Port]]` | Verbindung zum angegebenen Server |
| `-d` | DNS-Auflösung |
| `-i` | Iconsammlung |
| `-p` | Rechtedateien-Editor |
| `-s [IP]` | Benutzerstatistik |
| `-debug` | Debug-Logging aktivieren |
---
## Systemanforderungen
### Mindestanforderungen
- **Betriebssystem:** Windows XP+ (Desktop), Windows 2012+ (Server)
- **Speicher:** 3 MB für YaTQA (mehr für Konfiguration/Snapshots)
- **Auflösung:** 960×720 (allgemein), 1024×720 (Serverbaum), 1024×768 (Konsole)
### Fehlende Funktionen unter Windows XP
- Geist-Modus
- Nameserver für DNS-Auflösung ändern
- Einklappbare DNS-Ergebnisse
- Einklappbare Gruppen im Servergruppenmodus der Benutzer-DB
### Fehlende Funktionen unter Windows Vista/XP
- Sprunglisten
### Wine/Linux-Einschränkungen
- Speicherlecks (Wine unterstützt kein Entfernen von Link-Labels)
- Auch unter XP fehlende Funktionen fehlen unter Wine
- Zusätzliche Einschränkungen: Keine Array-Gruppierung, keine DNS-Gruppierung, kein Servergruppenmodus in der Benutzer-DB
- Plink muss manuell installiert werden (Version 0.61+)
---
## Schlüsselkonzepte
### ServerQuery-Interface
Das TeamSpeak-3-ServerQuery-Interface ist ein textbasiertes Protokoll zur Serververwaltung. YaTQA kapselt diese Schnittstelle in einer GUI mit:
- Befehlsautovervollständigung
- Parameterhilfe
- Werteauswahl
- Ergebnisanalyse
### Virtueller Server
Ein virtueller Server ist eine unabhängige TeamSpeak-Serverinstanz, die auf einem einzelnen physischen Serverprozess läuft. Mehrere virtuelle Server können auf einer Instanz laufen.
### Instanz
Der Serverprozess, der einen oder mehrere virtuelle Server hostet. Verwaltet über den „serveradmin"-Account.
### Snapshot
Ein vollständiges Backup der Einstellungen eines virtuellen Servers (ohne Port und ID). Enthält keine Dateien, Icons oder Avatare.
### Pseudo-Snapshot
Ein vom Benutzer manipulierter Snapshot, der zum Kopieren von Servern ohne Beibehaltung des originalen Keypairs verwendet werden kann.
### Rechtesystem
TeamSpeak verwendet ein hierarchisches Rechtesystem mit:
- Servergruppen
- Channelgruppen
- Client-Rechte
- Rechte-Powers (Werte, die steuern, was gesetzt werden kann)
### Anti-Flood
TeamSpeak-Server begrenzen die Häufigkeit von Query-Befehlen. YaTQA bietet konfigurierbare Verzögerungen und „Befehle bis Flood"-Einstellungen, um Bans zu vermeiden.
### Blacklist / Blacklist2
TeamSpeak führt Blacklists gebannter IPs (Blacklist1) und Server-UIDs (Blacklist2).
### Abzeichen
Visuelle Indikatoren im TeamSpeak, die Benutzerstatus, Addon-Creator-Status usw. anzeigen. YaTQA kann Abzeichen konfigurieren.
### DNS-Auflösung
TeamSpeak-Clients lösen Serveradressen über mehrere Methoden auf: A-Einträge, CNAME, SRV-Einträge und TSDNS. YaTQA visualisiert diesen Prozess.
---
## Bekannte Einschränkungen
- **Channel-Passwörter:** YaTQA sendet grundsätzlich keine Channel-Passwörter. Erfordert `b_channel_join_ignore_password` und `b_ft_ignore_password`-Rechte.
- **Unicode:** Nur Basic Multilingual Plane (BMP) unterstützt (TeamSpeak-Einschränkung).
- **Integrierte DNS-Auflösung:** Nur A- und CNAME-Einträge (TSDNS und SRV im integrierten Resolver nicht unterstützt).
- **Geist-Modus:** Viele Funktionen funktionieren nicht; Geist hat nur Query-Gast-Rechte.
- **Konsole:** Nur die üblichen Einschränkungen des TS3-Servers.
---
## IPv6-Unterstützung
Eckige Klammern `[]` um die Serveradresse schreiben. Unterstützt seit v1.4/2.0-pre für Query-Verbindungen. IPv4-Tunnel (z.B. `[::ffff:7f00:1]`) werden nicht unterstützt.
---
## Projekthistorie
- **10.04.2011:** Entwicklungsbeginn (ursprünglich „TS3Telnet" genannt)
- **29.06.2011:** Erste Alpha-Version veröffentlicht
- **18.04.2014:** v2.0 führte Registrierungserfordernis für einige Funktionen ein
- **22.08.2019:** YaTQA wieder uneingeschränkt Freeware
- **01.03.2023:** v3.9.9b veröffentlicht (Zeitlimit dauerhaft entfernt)
### Namensherkunft
„Yet Another TeamSpeak³ Query App" — benannt, weil es beim Entwicklungsbeginn bereits viele Query-Tools gab, aber keines auf dem Rechner des Autors funktionierte.
### Aussprache
[jatka] in IPA-Lautschrift — auch als deutsches Wort aussprechbar.
---
## Globale Tastenkürzel
| Kürzel | Aktion |
|--------|--------|
| Strg+F | Filtern (Rechte, Log) oder Suchen |
| Strg+Alt+F | In Listen suchen |
| F3 | Weiter suchen |
| Strg+A | Alles auswählen |
| Strg+C | Kopieren oder ausgewählte Daten speichern |
| Strg+Alt+A | Spalten automatisch anpassen |
| F2 | Umbenennen |
| F5 | Tab aktualisieren |
| NUM + | Ausgewählte Checkbox-Elemente aktivieren |
| NUM - | Ausgewählte Checkbox-Elemente deaktivieren |
| Strg+Leertaste | Parameterwert auswählen (Konsole) |
| Strg+E | Ausgewählten Text escapen (Konsole) |
| Strg+S | Diagramm als Bild speichern |
---
## Ressourcen
- **Website:** https://yat.qa/
- **Download:** https://dl.yat.qa/stable/
- **Funktionen:** https://yat.qa/funktionen/
- **Anleitung:** https://yat.qa/manual/ (nur Englisch)
- **Changelog:** https://yat.qa/changelog/ (nur Englisch)
- **FAQ:** https://yat.qa/haeufige-fragen/
- **Support:** https://yat.qa/unterstuetzung/
- **Ressourcen:** https://yat.qa/ressourcen/
- **Über:** https://yat.qa/ueber/
---
## Übersetzung
YaTQAs Originalsprache ist Deutsch. Die Übersetzung erfolgt mit OmegaT und XLIFF-Dateien. Den Autor vorher kontaktieren. Das Übersetzungssystem verwendet:
- `%s` — Zeichenketten-Platzhalter
- `%d` — Dezimalzahl-Platzhalter
- `&` — Tastenkürzel
- `&&` — Tatsächliches Kaufmanns-Und
- `|` — Senkrechter Strich (Hinweistext-Trennzeichen)
- `\r\n` — Neue Zeile
- `\t` — Tabulator
-348
View File
@@ -1,348 +0,0 @@
# YaTQA Knowledge Base (English)
> Source: https://yat.qa/ — Last fetched: 2026-06-13
> Version: v3.9.9b (01 Mar 2023)
## Overview
**YaTQA** (Yet Another TeamSpeak³ Query Admin Tool) is a Windows application for managing **TeamSpeak 3 servers and instances** using the ServerQuery interface. It provides a graphical interface to all query commands, eliminating the need to learn raw query syntax.
- **Author:** Janni "Яedeemer" K. (northern Germany)
- **Language:** Written in Delphi 2009 (50,000+ lines of code)
- **Development started:** April 10, 2011
- **First release:** June 29, 2011
- **License:** Free and fully functional freeware (no adware/spyware)
- **Platforms:** Windows XP and up, Linux via Wine
- **Size:** ~1.3 MiB installer
- **Languages included:** English and German (selectable during installation)
- **Supported servers:** TeamSpeak 3.9.0 through 3.13.7, TeaSpeak 1.4.10-beta
- **Download:** https://dl.yat.qa/stable/
- **Website:** https://yat.qa/
### Key Tagline
*"Dinosaurs weren't using TeamSpeak and wiped about 66 million years ago. Coincidence? I think not."*
---
## Features
**YaTQA supports ALL ServerQuery features with no exceptions.** The feature list below focuses on capabilities beyond what the standard TS3 client offers.
### General Features (No Admin Required)
- **DNS Resolver:** Detailed DNS lookup visualization simulating TeamSpeak client behavior (10 different client version lookups)
- **Blacklist Check:** Check TeamSpeak's blacklist for any IP
- **Blacklist2:** Check TeamSpeak's blacklist2 for virtual servers from an instance's server list
- **User Graph:** View server statistics from Planet TeamSpeak as a chart, save as PNG image
- **Client Cache:** Find avatars, icons, and chat logs in your client cache
### Console (Query Interface)
- **Autocomplete:** Command completion including undocumented commands
- **Parameter Help:** Displays every command's parameters based on extensive research
- **Parameter Value Selection:** Press Ctrl+Space to select values from a list
- **Result Analysis:** Groups datasets and explains most values
- **Scripting:** Load and execute command lists from files
- **Events:** Subscribe to server events and log them in the console
### SSH Tunnel
- **Encryption:** Fully encrypted connection (except file transfers)
- **Speed:** Notably faster on most servers (similar to `tcp_nodelay`)
- **Privacy:** Always hides your IP (you appear as 127.0.0.1)
- **Flood Bypass:** Circumvents all flood restrictions (127.0.0.1 is usually whitelisted)
### Instance Features (Requires serveradmin)
- View/edit instance settings and stats
- View license details and IP bindings
- See all virtual servers
- Add local notes to servers (stored locally)
- Start/stop/create/delete/rename virtual servers
- Become invisible (server bug, may be fixed)
- Send message to all servers
- Create/mass-create/deploy snapshots (including file-inclusive snapshots)
- Deploy manipulated snapshots
- Copy servers using snapshots
- Reset permissions to template groups
- Save/restore channel file backups (incremental backup supported)
### Virtual Server Features
- Ignore host message modal quit and high security level
- Very detailed virtual server statistics
- Edit multiple servers at once
- Collapsible server tree (optionally topmost)
- Move/kick/ban/describe multiple users at once
- Create multiple channels at once
- Use channel as template for other channels
- Edit multiple channels at once
- Send messages to multiple users/channels at once
- Edit permissions of multiple users/channels at once
- Move files between channels
- Image preview without download (bmp, gif, jpg, png, pbm, pgm, ppm, xbm, xpm)
- Upload/download entire folder structures
- Add users to groups by entering names
- Working permission overview with realtime editing
- Copy permissions between servers/instances
- Compare permission values and powers
- Find all clients/groups with a certain permission
- Edit multiple groups at once
- Enhanced client database with more details and search features
- Download full client database with one click
- Export client database to HTML or CSV
- Highlight banned users and IP-sharing profiles
- Browse log from any position
- Manage user custominfo (search, view, edit, add)
- Export log to HTML or TXT
- Download icons and avatars
- Identify avatar owners on your server
- Manage server template
- Monitor uploads/downloads
### Supported Image Formats
| Format | Description |
|--------|-------------|
| bmp | Windows Bitmap |
| gif | Graphics Interchange Format |
| jpg/jpeg | Joint Photographic Experts Group |
| png | Portable Network Graphics |
| pbm | Portable Bitmap (ASCII and binary) |
| pgm | Portable Graymap (ASCII and binary) |
| ppm | Portable Pixmap (ASCII and binary) |
| xbm | X BitMap |
| xpm | X PixMap |
---
## Architecture / How It Works
### Connection Methods
- **Raw TCP/Telnet:** Standard query connection (default port 10011)
- **YaTQA SSH Tunnel:** Via Plink (PuTTY suite) — encrypted, faster, hides IP
- **TeamSpeak SSH:** Native TS3.3+ SSH support (also supported but fewer advantages)
### Data Storage
- **Portable Mode:** All data in installation directory (`yatqa.ini` present)
- **Standard Mode:** Some files stored in `%APPDATA%\YaTQA`
- **Icon Cache:** 16-bit RES format (`icons.res`)
- **Command History:** `commandhistory.txt`
- **Debug Log:** `RedeemerTS3.log` (created with `-debug` switch)
### DNS Resolution
YaTQA simulates lookup steps done by TeamSpeak and displays them visually. Uses Google's DNS servers for reliability. Supports:
- A and CNAME records
- SRV records
- TSDNS lookups
- All 10 different client version DNS behaviors
### Snapshot System
- Snapshots contain all server settings (except port and virtual server ID)
- Snapshots do NOT include files, icons, or avatars
- File backups include files and icons (not avatars due to server limitations)
- Pseudo snapshots allow server copying without keypair
- Supports Zstd-compressed snapshots (3.10.0+ format)
### Anti-Flood Protection
- Configurable "Commands to Flood" setting (recommended: ~20)
- Configurable delay between commands (recommended: 340ms for non-own servers)
- SSH connections bypass flood restrictions (127.0.0.1 whitelisted)
---
## Configuration
### Application Settings
| Setting | Description |
|---------|-------------|
| Improved XP Unicode display | Uses Arial Unicode MS for better CJK support |
| Refresh on tab change | Auto-refresh data when switching tabs |
| Use local time | Local time instead of UTC |
| Improved channel dropdowns | Tree view lines for sub-channels |
| Minimize to tray | Minimize to system tray |
| Always show tray icon | Persistent tray icon |
| Enable icon caching | Cache icons in `icons.res` (recommended) |
| Don't use icons globally | Disable icon display |
| Try Windows Aero | Use Aero theme (Vista+) |
| Disable Aero glow | Remove white shadow behind menu text |
| Search for updates on start | Auto-check for updates |
| Save sort settings | Remember sort preferences |
| Enable jump lists | Windows 7+ jump list integration |
### Compatibility Settings
| Setting | Description |
|---------|-------------|
| Commands to flood | Delay between commands (340 recommended for remote servers) |
| Allow non-default query port | Connect to ports other than 10011 |
| Allow deleting important groups | Enable deletion of first 5 server/4 channel groups |
| Allow leaving important groups | Allow serveradmin to leave Admin Server Query |
| Allow changing machine ID | Enable machine ID modification |
### SSH Tunnel Profiles
Configure SSH profiles for servers. When connecting to a server with a matching SSH profile, YaTQA automatically uses the tunnel.
### Pie Chart Styles
Choose from 4 different pie chart styles (selected by user voting).
---
## Startup Parameters
| Parameter | Description |
|-----------|-------------|
| `-a` | Connect to default server |
| `-b [IP]` | Blacklist check |
| `-c IP Query_Port [User Pass [Voice_Port]]` | Connect to specified server |
| `-d` | DNS lookup |
| `-i` | Icon collection |
| `-p` | Permission editor |
| `-s [IP]` | User statistics |
| `-debug` | Enable debug logging |
---
## System Requirements
### Minimum Requirements
- **OS:** Windows XP+ (desktop), Windows 2012+ (server)
- **Disk:** 3 MB for YaTQA (more for configuration/snapshots)
- **Resolution:** 960×720 (general), 1024×720 (server tree), 1024×768 (console)
### Features Missing on Windows XP
- Ghost Mode
- Nameserver for DNS lookups
- DNS lookup group folding
- Folding server groups in user DB server group mode
### Features Missing on Windows Vista/XP
- Jump lists
### Wine/Linux Limitations
- Memory leaks (Wine doesn't support removing link labels)
- Features missing on XP also missing on Wine
- Additional limitations: no array property grouping, no DNS grouping, no server group mode in user DB
- Plink must be installed manually (version 0.61+)
---
## Key Concepts
### ServerQuery Interface
The TeamSpeak 3 ServerQuery interface is a text-based protocol for managing TeamSpeak servers. YaTQA wraps this interface in a GUI, providing:
- Command autocompletion
- Parameter help
- Value selection
- Result analysis
### Virtual Server
A virtual server is an independent TeamSpeak server instance running on a single physical server process. Multiple virtual servers can run on one instance.
### Instance
The server process that hosts one or more virtual servers. Managed via the "serveradmin" account.
### Snapshot
A complete backup of a virtual server's settings (excluding port and ID). Does not include files, icons, or avatars.
### Pseudo Snapshot
A user-manipulated snapshot that can be used to copy servers without preserving the original keypair.
### Permissions System
TeamSpeak uses a hierarchical permission system with:
- Server groups
- Channel groups
- Client permissions
- Permission powers (values that control what can be set)
### Anti-Flood
TeamSpeak servers limit query command frequency. YaTQA provides configurable delays and "Commands to Flood" settings to avoid bans.
### Blacklist / Blacklist2
TeamSpeak maintains blacklists of banned IPs (Blacklist1) and server UIDs (Blacklist2).
### Badges
Visual indicators in TeamSpeak showing user status, addon creator status, etc. YaTQA can configure badges.
### DNS Resolution
TeamSpeak clients resolve server addresses through multiple methods: A records, CNAME, SRV records, and TSDNS. YaTQA visualizes this process.
---
## Known Limitations
- **Channel passwords:** YaTQA never sends channel passwords. Requires `b_channel_join_ignore_password` and `b_ft_ignore_password` permissions.
- **Unicode:** Only Basic Multilingual Plane (BMP) supported (TeamSpeak limitation).
- **Integrated DNS lookups:** Only A and CNAME records (TSDNS and SRV unsupported in built-in resolver).
- **Ghost mode:** Many features don't work; ghost has Query Guest permissions.
- **Console:** Only limitations from TS3 server apply.
---
## IPv6 Support
Use square brackets `[]` around the server address. Supported since v1.4/2.0-pre for query connections. IPv4 tunnels (e.g., `[::ffff:7f00:1]`) are not supported.
---
## Project History
- **2011-04-10:** Development started (originally named "TS3Telnet")
- **2011-06-29:** First alpha version released
- **2014-04-18:** v2.0 introduced registration requirement for some features
- **2019-08-22:** YaTQA became unlimited freeware again
- **2023-03-01:** v3.9.9b released (removed time limit permanently)
### Naming
"Yet Another TeamSpeak³ Query App" — named because there were already many query tools when development started, but none worked for the author.
### Pronunciation
[jatka] in IPA notation — also suitable for German speakers.
---
## Global Hotkeys
| Shortcut | Action |
|----------|--------|
| Ctrl+F | Filter (permissions, log) or find |
| Ctrl+Alt+F | Find in lists |
| F3 | Find next |
| Ctrl+A | Select all |
| Ctrl+C | Copy or save selected data |
| Ctrl+Alt+A | Auto-adjust columns |
| F2 | Rename |
| F5 | Refresh tab |
| NUM + | Check selected checkbox items |
| NUM - | Uncheck selected checkbox items |
| Ctrl+Space | Select parameter value (console) |
| Ctrl+E | Escape selected text (console) |
| Ctrl+S | Save chart as image |
---
## Resources
- **Website:** https://yat.qa/
- **Download:** https://dl.yat.qa/stable/
- **Features:** https://yat.qa/features/
- **Manual:** https://yat.qa/manual/
- **Changelog:** https://yat.qa/changelog/
- **FAQ:** https://yat.qa/faq/
- **Support:** https://yat.qa/support/
- **Resources:** https://yat.qa/resources/
- **About:** https://yat.qa/about/
---
## Translation
YaTQA's original language is German. Translation is done using OmegaT with XLIFF files. Contact the author before translating. The translation system uses:
- `%s` — String placeholder
- `%d` — Decimal number placeholder
- `&` — Shortcut key
- `&&` — Actual ampersand
- `|` — Vertical line (hint text separator)
- `\r\n` — New line
- `\t` — Tab
-51
View File
@@ -1,51 +0,0 @@
# Chanora Privacy Policy Baseline
**Document status:** Engineering baseline candidate for DV review
**Date:** 2026-05-29
**Release status:** Requires product/legal approval before public or store release
## 1. Summary
Chanora is a client application for connecting to TeamSpeak 3-compatible servers selected by the user. Chanora does not operate the external servers users connect to and does not control server-side data handling.
## 2. Data Stored Locally
Chanora may store the following data on the user's device:
| Data | Purpose | Storage expectation |
|---|---|---|
| Server bookmarks | Reconnect to user-selected servers | Local database or app storage |
| Recent connection details | Improve reconnection and user workflow where implemented | Local app storage |
| Identity references and sensitive credentials | Authenticate to compatible servers | Platform secure storage or documented fallback |
| Audio and UI settings | Preserve user preferences | Local app storage |
| Diagnostic logs | Troubleshooting when the user chooses to export diagnostics | Local diagnostic storage/export bundle |
## 3. Permissions
Chanora may request platform permissions needed for voice communication and app operation:
| Permission or platform capability | Purpose |
|---|---|
| Microphone | Capture user voice for channel communication |
| Audio session / audio routing | Manage playback, capture, route changes, and voice processing |
| Notifications or foreground service where applicable | Maintain expected voice-session behavior on mobile platforms |
| Keyboard/input monitoring where applicable | Support push-to-talk on desktop platforms when allowed by the OS |
| Network access | Connect to user-selected compatible servers |
## 4. Diagnostics
Diagnostic export is user-initiated for MVP. Chanora must not automatically upload diagnostics, telemetry, or crash reports unless a later approved requirement and privacy update authorize that behavior.
Diagnostic bundles may include logs, platform information, app version, connection state, and error details. They must redact secrets before export. Users choose whether to share exported diagnostics with support or developers.
## 5. External Servers
When a user connects to a TeamSpeak 3-compatible server, communication occurs with that external server. Server operators may process connection, voice, text, identity, permission, and logging information according to their own policies. Chanora does not control those external policies.
## 6. No Automatic Cloud Sync
The MVP does not include automatic cloud sync of bookmarks, identities, settings, or diagnostics.
## 7. Release Approval Requirement
This privacy baseline is sufficient for DV discussion. It must be reviewed and approved by the product/legal owner before public or store release.
@@ -1,28 +0,0 @@
# ASPICE SWE.2/SWE.3 Integration Note
**Document status:** DV meeting baseline candidate
**Date:** 2026-05-29
## 1. Purpose
This note explains how Chanora's SWE.2 and SWE.3 documents support downstream verification.
## 2. Lifecycle Chain
```text
SysRS -> SysDes -> SRS -> SAD/SWE.2 -> SDD/SWE.3 -> SWE.4/SWE.5/SWE.6/SYS.4 verification
```
## 3. Integration Points
| Process | Chanora document | Verification handoff |
|---|---|---|
| SWE.2 | `docs/architecture/sad.md` | Defines components, interfaces, runtime flows, dependency rules |
| SWE.3 | `docs/architecture/sdd.md` | Defines modules, detailed behavior, data/state design, verification hooks |
| SWE.4 | `docs/verification/swe4-unit-verification-plan.md` | Consumes SDD module hooks |
| SWE.5 | `docs/verification/swe5-software-integration-verification-plan.md` | Consumes SAD interfaces and SDD integration hooks |
| SWE.6 | `docs/verification/swe6-software-verification-plan.md` | Verifies integrated software against SRS |
## 4. DV Conclusion
The SWE.2/SWE.3 integration route is documented for DV. Further itemized IDs can be added if required by a stricter process audit.
-21
View File
@@ -1,21 +0,0 @@
# Chanora External References
**Document status:** DV meeting baseline candidate
**Date:** 2026-05-29
## 1. Reference List
| Reference | Use |
|---|---|
| Flutter documentation | Cross-platform UI, build, localization, platform integration |
| Flutter Rust Bridge documentation | Typed Flutter/Rust bridge generation |
| Rust Cargo documentation | Workspace builds, tests, dependency locking |
| TeamSpeak 3-compatible protocol/library documentation | Protocol compatibility through `tsclientlib` |
| Apple Developer documentation | iOS/macOS signing, AVAudioSession, TestFlight/App Store requirements |
| Android Developer documentation | Permissions, foreground services, target SDK, audio routing |
| Material 3 guidelines | UI system baseline |
| ASPICE SWE/SYS process references | Lifecycle terminology for SWE.2, SWE.3, SWE.4, SWE.5, SWE.6, SYS.4 |
## 2. DV Use
External references support review but do not override Chanora baselines.
-36
View File
@@ -1,36 +0,0 @@
# Chanora DV Waiver Register
**Document status:** DV meeting baseline candidate
**Date:** 2026-05-29
**Applies to:** DV review and internal candidate validation only
## 1. Waiver Policy
A waiver records a known gap that reviewers may accept for a limited decision scope. A waiver does not delete the underlying requirement and does not approve public/store release unless the release owner explicitly accepts that scope.
## 2. Active Waivers and Deferrals
| ID | Gap | Source evidence | Impact | Accepted DV scope | Unblock condition |
|---|---|---|---|---|---|
| DV-WVR-001 | DEC-012 legal/trademark/OSS review remains open | `docs/implementation-status-2026-05-28.md` | Blocks public/store release and final compatible-server wording approval | Documentation review and internal validation only | Legal/trademark/OSS owner signs off and required notices/reports are complete |
| DV-WVR-002 | Android Keystore-backed DEK deferred to v1.1 | `docs/implementation-status-2026-05-28.md` | Limits Android secure-storage claim; file-fallback DEK remains a release risk | Internal validation only with limitation stated | Android Keystore-backed DEK implemented or product/security owner accepts release waiver |
| DV-WVR-003 | iOS `AVAudioSession.Mode.voiceChat` status was recorded as a prior blocker but recent commit history indicates follow-up implementation | `docs/implementation-status-2026-05-28.md`, recent commit `feat(ios): use AVAudioSession .voiceChat mode` | Requires updated validation so documents and implementation status do not conflict | DV may proceed if treated as evidence-needs-validation, not as a closed release gate | Run iOS device audio verification and update implementation status |
| DV-WVR-004 | Standalone event replay and runtime reducer-integration evidence not yet complete | `docs/implementation-status-2026-05-28.md`, local `cargo test -p chanora_state --locked` evidence | Reducer unit coverage supports state synchronization, but file-based replay evidence and live-event integration evidence remain open | DV documentation pass and internal validation | Event replay tooling implemented or requirement reprioritized; runtime reducer integration evidence attached |
| DV-WVR-005 | Event replay tool not found | `docs/implementation-status-2026-05-28.md` | Limits P1 state verification hooks SRS-061/SRS-098 | Accepted as P1 deferral | Event replay tooling implemented or requirement reprioritized |
| DV-WVR-006 | Desktop and iOS artifacts are source-buildable or unsigned only | `docs/implementation-status-2026-05-28.md`, `docs/release/ios-build.md` | Blocks packaged public release claims | Internal validation from source/unsigned builds only | Signed/notarized/package artifacts exist and hashes are recorded |
| DV-WVR-007 | Silero VAD asset bundled while `VoiceActivity` is platform-scoped | `docs/implementation-status-2026-05-28.md` | Risk that UI/release wording overstates VAD availability beyond verified Windows/Linux desktop paths | DV may pass if VoiceActivity claims are limited to verified desktop evidence and unsupported platforms remain disabled/unavailable | Mobile/macOS implementation allocated in a later baseline or asset/wording reconciled |
| DV-WVR-008 | Artifact hashes, tag, and candidate run IDs are not recorded in release record | `docs/release/release-readiness-go-nogo-record.md` | Blocks final release approval and reproducibility | DV documentation review only | Candidate build run records, tag, commit SHA, and artifact hashes are recorded |
| DV-WVR-009 | Android target compile and runtime smoke blocked locally | `docs/governance/maintainability-review-2026-06-08.md`, `docs/release/release-readiness-go-nogo-record.md` | Blocks Android runtime, permission-flow, and audio-lifecycle success claims | Documentation review only; internal validation must keep Android limitation stated | Android NDK compiler `aarch64-linux-android-clang` is available, `adb devices -l` shows an authorized target, and Android build/install/smoke evidence is attached |
## 3. Waiver Review Rules
| Rule | Required behavior |
|---|---|
| Scope control | Waivers in this file apply to DV/internal validation unless explicitly promoted by release owner approval |
| User-visible claims | Release notes, UI, and marketing wording must not claim unsupported capabilities |
| Security/legal claims | Security, privacy, legal, and OSS claims require owner sign-off before public release |
| Closure | A waiver closes only when the unblock condition is satisfied and the release-readiness record is updated |
## 4. DV Meeting Recommendation
Accept the waiver register for DV documentation pass. Do not accept these waivers as public/store release approval.
-26
View File
@@ -1,26 +0,0 @@
# Chanora Platform Release Policy
**Document status:** DV meeting baseline candidate
**Date:** 2026-05-29
## 1. Purpose
This policy defines platform release expectations for Chanora candidate builds.
## 2. Platform Policy
| Platform | Minimum release requirement | Current DV state |
|---|---|---|
| Android | Signed release or internal test artifact, target SDK compliance, permission/foreground-service validation | Internal validation only; Android DEK waiver active |
| iOS | Signed TestFlight/App Store build or explicitly unsigned verification build | Unsigned verification build only |
| Windows | Packaged build, smoke result, PTT capability evidence, signing decision | Source-buildable only |
| macOS | Universal build, signing/notarization, PTT capability evidence | Source-buildable only |
| Linux | Packaged build or documented source-build path, portal/fallback PTT evidence | Source-buildable only |
## 3. Release Claim Rule
Release notes and public wording must match the actual artifact and platform capability. A source-buildable platform must not be described as having a finished public binary release.
## 4. DV Conclusion
The platform policy is defined. Current candidate scope remains internal validation and documentation review.
@@ -1,105 +0,0 @@
# Chanora Release Readiness Go/No-Go Record
**Document status:** DV meeting baseline candidate
**Date:** 2026-05-29
**Candidate:** documentation/DV evidence over Rust workspace version `0.2.0-beta.1`; Flutter app version/build `0.3.0+100`
**Decision:** No-Go for public/store release; Conditional Go only for documentation review and continued internal DV validation
## 1. Decision Summary
Chanora has enough documented structure for DV review and continued internal release-candidate validation. It is not ready for public, store, or broad external release because legal/trademark/OSS sign-off, platform release artifacts, signing/notarization, and several verification evidence items remain open.
The phrase `Conditional Go` in this record is restricted to document-baseline review and internal validation planning. It is not a product release approval, not a public beta approval, and not a store-distribution approval.
| Decision scope | Result | Rationale |
|---|---|---|
| Documentation baseline for DV meeting | Conditional Go | SysRS, SysDes, SRS, verification plans, traceability summary, and waiver register are available |
| Internal candidate validation | Conditional Go | Core product paths are implemented enough to continue targeted validation with recorded limitations |
| Public release | No-Go | DEC-012 and platform release gates remain open |
| Store release | No-Go | Signing, app-store build, legal/privacy/security evidence, and artifact records are incomplete |
## 2. Candidate Metadata
| Field | Value |
|---|---|
| Workspace version | `0.2.0-beta.1` |
| Flutter app version/build | `0.3.0+100` from `apps/chanora_flutter/pubspec.yaml` |
| CHANGELOG latest candidate | `v0.3.0` baseline entry; public release version not reached |
| Build number | `100` from `apps/chanora_flutter/pubspec.yaml` |
| Commit SHA | To be recorded from the candidate build job before release approval |
| Git tag | To be recorded if a candidate is tagged for release validation |
| Artifact hashes | Not recorded in current workspace; required before release approval |
| Release owner | Product / Release Operations |
| Verification owner | Software QA with System Engineering support |
## 3. Current Implementation Readiness
Current implementation status is summarized in `docs/implementation-status-2026-05-28.md`.
| Area | Readiness statement |
|---|---|
| Core product path | Connect, channel/voice/chat/bookmark/storage/diagnostics paths are substantially implemented |
| CI baseline | Rust and Flutter automated checks are defined in `.github/workflows/ci.yml` |
| Audio benchmarks | Advisory workflow exists in `.github/workflows/bench-advisory.yml` |
| Platform coverage | Android and iOS platform work exists; desktop/iOS release artifacts are not ready for public distribution |
| Documentation | Verification plan set and DV gate summaries now exist for review |
## 4. Release Gates
| Gate | Status | Decision impact |
|---|---|---|
| Requirements/design baseline | Passed for DV | SysRS/SysDes/SRS available |
| Verification plan baseline | Passed for DV | `docs/verification/` plan set available |
| Traceability summary | Passed for DV | `docs/governance/traceability-matrix.md` available |
| Legal/trademark/OSS review DEC-012 | Blocked / open | Blocks public/store release |
| Privacy policy baseline | Baseline candidate | Requires owner/legal review before public/store release |
| Security/privacy evidence | Partial | Blocks strong secure-storage and diagnostic claims until audits attach evidence |
| Android secure-storage DEK | Deferred to v1.1 | Requires waiver for internal testing; limits release claim |
| Android target compile/install/smoke | Blocked locally | Missing Android NDK compiler `aarch64-linux-android-clang` and no authorized ADB target block Android runtime claims |
| iOS release build/signing | Unsigned verification only | Blocks TestFlight/App Store release |
| macOS signing/notarization | Not complete | Blocks macOS public binary release |
| Windows/Linux packaging | Source-buildable only for candidate | Blocks packaged public desktop release claims |
| Artifact hashes | Not recorded | Blocks final release approval |
## 5. Verification Evidence Status
| Evidence | Current status | Required action before public/store release |
|---|---|---|
| Rust workspace check/test | CI defined | Attach latest passing candidate run |
| Flutter analyze/test | CI defined | Attach latest passing candidate run |
| Cargo deny and cargo-about | CI defined | Attach latest passing candidate run and inventory records |
| Flutter license inventory | CI defined | Attach latest passing candidate run and inventory records |
| iOS unsigned build | CI defined | Attach latest passing candidate run; add signing evidence before release |
| Compatible-server demo | Evidence not attached in this record | Run and attach demo notes/logs |
| Audio send/receive and processing demo | Evidence not attached in this record | Run and attach platform evidence |
| Android target build/install/smoke | Blocked locally | Install/fix Android NDK compiler, connect/authorize a device or emulator, then attach build/install/smoke evidence |
| Diagnostics redaction/export demo | Evidence not attached in this record | Run and attach export review |
| Platform secure-storage audit | Partial | Attach per-platform audit or waiver |
| PTT capability evidence | Partial | Attach per-platform `PttCapabilityLevel` and backend record |
## 6. Platform Readiness
| Platform | Current readiness | Release decision |
|---|---|---|
| Android | Core platform implementation present; Android Keystore-backed DEK deferred; local target compile/install/smoke blocked by missing `aarch64-linux-android-clang` and no authorized ADB target | Conditional internal validation only after Android build/install/smoke evidence or explicit waiver |
| iOS | Unsigned build path present; signing and store pipeline incomplete | No-Go for store release |
| Windows | Source-buildable; smoke procedure exists | No-Go for packaged release until smoke/signing evidence exists |
| macOS | Source-buildable; public artifact not in candidate | No-Go for packaged release until signing/notarization evidence exists |
| Linux | Source-buildable; packaging not confirmed | No-Go for packaged release until artifact evidence exists |
## 7. Waivers and Deferrals
All current waivers and deferrals are controlled by `docs/release/dv-waiver-register.md`. A release approver may accept a waiver for internal validation, but public/store release waivers require explicit product, legal/security, and release-owner approval where applicable.
## 8. Final DV Recommendation
Recommended DV meeting outcome:
| Question | Recommendation |
|---|---|
| Can the document baseline pass DV review? | Yes, with recorded limitations |
| Can internal release-candidate validation continue? | Yes, with the waiver register attached |
| Can Chanora be publicly released now? | No |
| Can store release proceed now? | No |
The release decision remains **No-Go** until current candidate run evidence, legal/trademark/OSS approval, privacy/security approval, platform signing, and artifact records are complete.
-22
View File
@@ -1,22 +0,0 @@
# Software Requirements Specification
**Document status:** DV entry-point record
**Canonical document:** `../srs.md`
The canonical Chanora Software Requirements Specification currently lives at `docs/srs.md`. This file preserves the README-advertised path `docs/requirements/srs.md` for DV navigation.
Reviewers shall use `docs/srs.md` as the authoritative SRS baseline until the repository migration moves the canonical file into this directory.
## DV Review Summary
| Topic | Canonical source |
|---|---|
| Software requirement attributes | `docs/srs.md` section 2 |
| Component requirement groups | `docs/srs.md` section 5 |
| MVP acceptance verification support | `docs/srs.md` SRS-128 |
| SysDes-to-SRS coverage | `docs/srs.md` section 9 |
| SWE lifecycle handoff | `docs/srs.md` section 8 |
## DV Position
The SRS baseline is reviewable for DV. SAD, SDD, and verification documents consume this baseline through `docs/architecture/sad.md`, `docs/architecture/sdd.md`, and `docs/verification/`.
-22
View File
@@ -1,22 +0,0 @@
# System Requirements Specification
**Document status:** DV entry-point record
**Canonical document:** `../sysrs.md`
The canonical Chanora System Requirements Specification currently lives at `docs/sysrs.md`. This file preserves the README-advertised path `docs/requirements/sysrs.md` for DV navigation.
Reviewers shall use `docs/sysrs.md` as the authoritative SysRS baseline until the repository migration moves the canonical file into this directory.
## DV Review Summary
| Topic | Canonical source |
|---|---|
| System scope and context | `docs/sysrs.md` sections 2 through 5 |
| Verification and validation requirements | `docs/sysrs.md` section 24 |
| MVP acceptance requirements | `docs/sysrs.md` section 25, SysRS-241 through SysRS-257 |
| Traceability requirement | `docs/sysrs.md` SysRS-233 and SysRS-285 |
| No automatic telemetry posture | `docs/sysrs.md` SysRS-295 |
## DV Position
The SysRS baseline is reviewable for DV. Release approval remains controlled by `docs/release/release-readiness-go-nogo-record.md`.
@@ -1,43 +0,0 @@
# Chanora Dependency and Supply Chain Report
**Document status:** DV meeting baseline candidate
**Date:** 2026-05-29
**Scope:** Dependency, license, advisory, and supply-chain evidence for DV review
## 1. Purpose
This report summarizes the current dependency and supply-chain controls visible in the repository. It is not the final DEC-012 legal sign-off.
## 2. Automated Controls
| Control | Location | Current behavior |
|---|---|---|
| Rust license/advisory/bans/sources check | `.github/workflows/ci.yml` supply-chain job | Runs `cargo deny check --workspace --all-features` |
| Rust license inventory freshness | `.github/workflows/ci.yml` license-inventory job | Regenerates cargo-about inventory and diffs `docs/security/license-inventory.md` |
| Flutter license inventory freshness | `.github/workflows/ci.yml` flutter-license-inventory job | Runs `tools/dump_flutter_licenses.sh` and fails if `docs/security/flutter-license-inventory.md` is stale |
| Rust dependency lock enforcement | `.github/workflows/ci.yml` Rust job | Uses `cargo check/test --locked` |
| Flutter dependency resolution | `.github/workflows/ci.yml` Flutter job | Runs `flutter pub get`, analyze, and tests |
## 3. Dependency Areas
| Area | Examples from current repository | DV status |
|---|---|---|
| Rust workspace crates | `chanora_protocol`, `chanora_audio`, `chanora_storage`, `chanora_diagnostics`, `chanora_bridge`, `chanora_resolver`, `chanora_prefetch`, `chanora_state`, `chanora_core` | In workspace and covered by CI commands |
| Flutter app dependencies | `flutter_rust_bridge`, `audio_session`, `flutter_foreground_task`, `package_info_plus`, `share_plus`, `shared_preferences` | Covered by Flutter dependency resolution and license inventory job |
| Native/audio dependencies | Opus, platform audio stacks, Android/iOS audio services | Require platform build and license review evidence |
| Patched Rust dependency | `cmake` patched to a pinned git revision for Android build support | Requires DEC-032 tracking and periodic reevaluation |
| Pinned Android audio fork | `oboe` uses `https://github.com/EdisonJwa/oboe-rs` at a fixed revision | Removes machine-local path dependency while preserving reviewed Android callback/session fixes |
## 4. Open Evidence Gaps
| Gap | Impact | Required action |
|---|---|---|
| `docs/security/license-inventory.md` and Flutter inventory are referenced by CI but were not present in the current document listing | CI may fail or the repository may have untracked/missing inventory artifacts | Generate and commit inventories or update CI/documentation to the actual artifact location |
| DEC-012 remains open | Blocks public/store release | Complete legal/trademark/OSS review |
| Candidate CI run IDs are not recorded in release readiness | Reviewers cannot tie evidence to a specific release candidate | Attach latest passing run IDs to release-readiness record |
| Patched `cmake` dependency requires monitoring | Long-term supply-chain risk if fork remains pinned indefinitely | Reevaluate when upstream release includes the needed Android fix |
| `audiopus_sys` unmaintained advisory `RUSTSEC-2026-0150` is explicitly ignored in `deny.toml` | Keeps current Opus path buildable but remains a supply-chain risk | Track replacement or upstream remediation before public release sign-off |
## 5. DV Conclusion
Automated supply-chain controls are defined, but final dependency/legal approval is not complete. This supports DV documentation pass with a public-release blocker.
@@ -1,31 +0,0 @@
# Chanora Diagnostic Redaction Audit Report
**Document status:** DV meeting baseline candidate
**Date:** 2026-05-29
## 1. Scope
This report defines the diagnostic redaction audit required before enabling diagnostics for external testers or public release.
## 2. Redaction Targets
| Data class | Required handling |
|---|---|
| Server passwords | Redact before export |
| Identity/private-key material | Redact before export |
| Tokens and known secrets | Redact through known-secret registry |
| Host/IP/email/path values | Redact or minimize according to diagnostic policy |
| User text content | Avoid unnecessary capture; redact when classified as sensitive |
## 3. Evidence Required
| Evidence | Required result |
|---|---|
| Unit tests | Redactor removes sample secrets and registered known secrets |
| Export demo | User-initiated export produces a JSON bundle without sample secrets |
| Manual review | Reviewer inspects candidate export before external release |
| Privacy alignment | Privacy policy describes user-initiated diagnostic sharing |
## 4. DV Conclusion
Audit expectations are defined. Candidate export evidence must be attached before external tester release.
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -1,31 +0,0 @@
# Chanora Secure Storage Audit Report
**Document status:** DV meeting baseline candidate
**Date:** 2026-05-29
## 1. Scope
This report defines the secure-storage audit expected before public/store release.
## 2. Audit Matrix
| Platform | Expected backend | Current evidence state |
|---|---|---|
| Android | Android secure storage / Keystore-backed protection where implemented | Android Keystore-backed DEK deferred to v1.1 |
| iOS | Keychain | Device audit required |
| macOS | Keychain | Device audit required |
| Windows | Credential Manager | Device audit required |
| Linux | Secret Service with documented fallback behavior | Device audit required |
## 3. Required Checks
| Check | Required result |
|---|---|
| Secret persistence | Server passwords and identity secrets are not stored as unprotected plaintext |
| Fallback disclosure | Any file fallback is disclosed in release/security records |
| Diagnostic interaction | Stored secrets are registered for redaction where they can enter logs/export |
| CI behavior | CI keyring disabling is limited to headless test environments |
## 4. DV Conclusion
Secure-storage audit requirements are defined, but per-platform audit evidence is not complete. Public/store release remains blocked for strong secure-storage claims.
@@ -1,63 +0,0 @@
# Chanora Security, Privacy, and Legal Guideline
**Document status:** DV meeting baseline candidate
**Date:** 2026-05-29
**Scope:** Release-gate expectations for security, privacy, diagnostics, legal wording, and OSS review
## 1. Purpose
This guideline defines the minimum security, privacy, and legal checks that must be satisfied before Chanora moves beyond internal validation. It supports DV review by making gate ownership and evidence expectations explicit.
## 2. Gate Summary
| Gate | Requirement source | Required evidence | Current DV status |
|---|---|---|---|
| Secure storage | SysRS-237, SysRS-256, SRS-090 through SRS-095, SRS-126, SRS-137 | Platform audit for secret storage and fallback behavior | Partial; Android DEK waiver active |
| Diagnostic redaction | SysRS-238, SysRS-257, SRS-093 through SRS-102, SRS-126 | Redaction tests and export review | Evidence must be attached before external tester enablement |
| No automatic telemetry/upload | SysRS-295 and related SysDes/SRS privacy clauses | Inspection of runtime behavior and privacy wording | Baseline policy: no automatic upload in MVP |
| Dependency and OSS review | DEC-012, CI supply-chain jobs | Cargo deny/about, Flutter license inventory, legal sign-off | CI checks defined; DEC-012 remains open |
| Trademark/non-affiliation wording | SysRS-006, SysRS-240 | Legal/trademark review and UI/release wording inspection | Blocks public release until signed off |
| Privacy policy | Privacy and release readiness requirements | Published or approved privacy text | Baseline candidate exists; owner/legal review required |
## 3. Secure Storage Expectations
Sensitive data includes server passwords, identity/private-key material, tokens, diagnostic known secrets, and any credential-equivalent values. The application must use platform secure storage where available and must not silently advertise stronger protection than the active backend provides.
Required release evidence:
| Platform | Required evidence |
|---|---|
| Android | Key storage and DEK behavior review; Android Keystore-backed DEK gap is a release limitation until closed |
| iOS | Keychain behavior review on device |
| macOS | Keychain behavior review |
| Windows | Credential Manager behavior review |
| Linux | Secret Service behavior review and fallback limitation disclosure |
## 4. Diagnostic Redaction Expectations
Diagnostics must be user-initiated. Logs and export bundles must redact credentials, tokens, private paths when sensitive, host/IP/email where configured, and known secrets registered by runtime code.
Diagnostic evidence must include:
| Evidence | Required result |
|---|---|
| Redaction tests | Known secret classes are removed or replaced before export |
| Export demo | User can create a diagnostic bundle without automatic upload |
| Manual inspection | Exported JSON does not contain sample secrets used during the test |
| Privacy wording | User-facing policy explains what diagnostics contain and how sharing occurs |
## 5. Legal and OSS Expectations
Before public/store release, DEC-012 must close with approval covering:
| Topic | Required result |
|---|---|
| TeamSpeak compatibility wording | Wording states compatibility without implying official affiliation |
| App name and metadata | Store, README, About dialog, and release notes avoid prohibited claims |
| OSS license inventory | Rust and Flutter dependencies have reviewed license inventory |
| NOTICE and attribution | Notices are complete for bundled or linked third-party software |
| Vulnerability/advisory review | Known critical issues are resolved, waived, or documented by owner approval |
## 6. DV Conclusion
Security, privacy, and legal gates are sufficiently documented for DV discussion. They are not sufficiently closed for public/store release.
-33
View File
@@ -1,33 +0,0 @@
# Chanora Threat Model
**Document status:** DV meeting baseline candidate
**Date:** 2026-05-29
## 1. Scope
This threat model covers the Chanora client, local storage, diagnostics, bridge boundary, protocol adapter, audio path, platform services, and release artifacts. External compatible servers are outside Chanora control.
## 2. Assets
| Asset | Protection goal |
|---|---|
| Server passwords and identities | Prevent plaintext persistence and diagnostic leakage |
| Voice audio | Avoid unintended transmit and preserve user control |
| Diagnostic logs | Redact secrets before user-initiated export |
| Local bookmarks/settings | Preserve integrity and avoid accidental disclosure |
| Release artifacts | Preserve integrity and accurate capability claims |
## 3. Primary Threats
| Threat | Mitigation | Current DV status |
|---|---|---|
| Secret leakage in diagnostics | Known-secret registry and redactor | Requires export evidence |
| Plaintext or weak secret storage | Platform secure-storage abstraction and encryption | Android DEK waiver active |
| Stuck push-to-talk transmit | Missed-key-up watchdog and transmit gate | Requires platform PTT evidence |
| Protocol-library leakage into UI | Protocol adapter isolation | Architecture baseline covers boundary |
| Malicious or misconfigured external server | Treat server as external dependency and expose safe errors | Requires compatible-server/negative evidence |
| Over-claiming platform support | Capability records and release policy | Release record controls claims |
## 4. DV Conclusion
Major threats and mitigations are identified. Final release requires audit evidence for secure storage, diagnostics, platform PTT, and release artifacts.
-2850
View File
File diff suppressed because it is too large Load Diff
-3047
View File
File diff suppressed because it is too large Load Diff
-2014
View File
File diff suppressed because it is too large Load Diff
@@ -1,27 +0,0 @@
# Chanora Adaptive Layout and Platform Guide
**Document status:** DV meeting baseline candidate
**Date:** 2026-05-29
## 1. Layout Policy
Chanora prioritizes compact/mobile layout for MVP while preserving a path to medium and expanded layouts.
| Layout class | Current expectation |
|---|---|
| Compact | Primary supported layout for mobile and narrow windows |
| Medium | Must preserve connection and voice control visibility; side navigation rail remains a P1 gap where not implemented |
| Expanded | Persistent side panes are deferred beyond current candidate |
## 2. Platform Policy
| Platform concern | Required behavior |
|---|---|
| Safe areas/system bars | Critical controls remain reachable |
| Android back | Back intent service mediates app behavior |
| iOS gestures/haptics | Platform services handle iOS-specific behavior |
| Desktop PTT | UI displays actual PTT capability level and fallback state |
## 3. DV Conclusion
Adaptive layout policy is documented. Medium/expanded hardening remains a tracked post-MVP/P1 gap where not implemented.
-38
View File
@@ -1,38 +0,0 @@
# Chanora Material 3 Component Catalog
**Document status:** DV meeting baseline candidate
**Date:** 2026-05-29
## 1. Component Catalogue
| Component area | Source files | Purpose |
|---|---|---|
| Connect and bookmarks | `connect_widgets.dart`, `input_dialogs.dart` | Server input, bookmarks, connect actions |
| Channel and client view | `snapshot_view.dart`, `client_info_sheet.dart`, `channel_spacer.dart` | Channel tree, clients, client details |
| Chat | `chat_views.dart`, `bbcode_text.dart` | Channel text and BBCode rendering |
| Voice controls | `voice_bar.dart`, `voice_compact.dart`, `voice_settings*.dart` | Mute, deaf, PTT, levels, processing controls |
| Platform/permission indicators | `permission_state_banner.dart`, `ptt_capability_badge.dart`, `talk_power_warning.dart` | Platform readiness and safety warnings |
| Diagnostics | `audio_debug_stats_panel.dart` and diagnostics surfaces in app shell | Runtime/debug evidence and export support |
## 2. Acceptance Criteria
| Component area | DV acceptance criterion |
|---|---|
| Connect and bookmarks | User can enter server details, save/reuse bookmarks, and receive user-safe errors |
| Channel and client view | Channel tree and online clients remain visible after snapshot updates |
| Chat | Channel text renders without corrupting Unicode or unsafe BBCode display |
| Voice controls | Mute, deaf, PTT, metering, and processing controls expose current state clearly |
| Platform/permission indicators | Permission and capability limitations are visible and not color-only |
| Diagnostics | Diagnostic/debug surfaces do not expose unredacted secrets in release evidence |
## 3. Evidence Required Before Release
| Evidence | Purpose |
|---|---|
| Flutter widget test run | Confirms component behavior remains stable |
| Accessibility review | Confirms critical states are not color-only and controls are reachable |
| Candidate screenshots or demo notes | Supports DV review and release readiness |
## 4. DV Conclusion
The component catalog is sufficient for DV navigation. Final UI audit should attach screenshots or test evidence for each critical component.
-21
View File
@@ -1,21 +0,0 @@
# Chanora Material 3 Design Tokens
**Document status:** DV meeting baseline candidate
**Date:** 2026-05-29
## 1. Source
Implementation token source is `apps/chanora_flutter/lib/design/chanora_tokens.dart`.
## 2. Token Areas
| Token area | Purpose |
|---|---|
| Color roles | Connection, voice, permission, diagnostic, warning, and neutral states |
| Typography roles | App shell, status, channel/client lists, chat, settings, diagnostics |
| Spacing roles | Compact/mobile layout, control grouping, list density |
| Shape/elevation roles | Material 3 cards, sheets, banners, controls |
## 3. Verification
Token usage is verified through Flutter widget tests, visual review, and accessibility checks that critical state is not represented by color alone.
-8
View File
@@ -1,8 +0,0 @@
# Chanora Material 3 Guideline
**Document status:** DV path record
**Canonical source:** `../material3-guideline.md`
The current Material 3 guideline lives at `docs/material3-guideline.md`. This file preserves the README-advertised path `docs/ui-ux/material3-guideline.md` for DV navigation.
Reviewers shall use `docs/material3-guideline.md` as the canonical UI/UX guideline until the migration moves it into `docs/ui-ux/`.
@@ -1,60 +0,0 @@
# SWE.4 Unit Verification Plan
**Document status:** DV meeting baseline candidate
**Date:** 2026-05-29
**Scope:** Unit-level verification for Chanora software components
## 1. Purpose
This plan defines unit verification coverage for the software modules that implement Chanora behavior. The plan is based on the current repository state and the SRS verification hooks. It is acceptable for DV only when open unit gaps remain visible in the waiver register.
## 2. Unit Verification Scope
| Area | Components | Verification method | Current evidence |
|---|---|---|---|
| Rust core orchestration | `core/chanora_core` | Cargo unit tests, integration-oriented crate tests | `cargo test --workspace --locked --no-fail-fast` in CI |
| Protocol adapter | `crates/chanora_protocol` | Protocol DTO and error mapping tests | Workspace tests; protocol compatibility still needs SWE.5/SYS.4 evidence |
| State sync | `crates/chanora_state` | Snapshot, delta, reducer, malformed-event, reconnect, deterministic ordering, unknown-client, and channel-delete/client cleanup unit tests | Local `cargo test -p chanora_state --locked` passes with 27 tests |
| Audio subsystem | `crates/chanora_audio` | DSP, Opus, mixer, gate, PTT logic, baseline examples, benches | Workspace tests and benchmark harnesses; platform loopback evidence is integration/system scope |
| Storage | `crates/chanora_storage` | Bookmark repository, identity store, encryption behavior, keyring-disabled CI mode | Workspace tests with `CHANORA_DISABLE_KEYRING=1` in CI |
| Diagnostics | `crates/chanora_diagnostics` | Redaction, known-secret registry, diagnostic export JSON, log sink | Workspace tests and security audit plan |
| Resolver and prefetch | `crates/chanora_resolver`, `crates/chanora_prefetch`, Flutter prefetch debouncer | Resolver fallback, cache TTL, generation safety, debouncer tests | Workspace tests and `apps/chanora_flutter/test/services/prefetch_debouncer_test.dart` |
| Flutter services | `apps/chanora_flutter/lib/services` | Dart unit tests | Service tests under `apps/chanora_flutter/test/services/` |
| Flutter widgets | `apps/chanora_flutter/lib/widgets` and screen widgets | Widget tests | Widget tests under `apps/chanora_flutter/test/widgets/` |
## 3. Required CI Commands
| Command | Owner | Expected use |
|---|---|---|
| `cargo check --workspace --locked` | Software | Rust compile verification |
| `CHANORA_DISABLE_KEYRING=1 cargo test --workspace --locked --no-fail-fast` | Software / QA | Rust unit and crate tests without host keyring dependency |
| `cargo clippy --workspace --all-targets -- -D warnings` | Software | Advisory static analysis in current CI |
| `flutter analyze` in `apps/chanora_flutter` | Software | Dart static analysis |
| `flutter test --exclude-tags e2e` in `apps/chanora_flutter` | Software / QA | Flutter unit and widget tests |
For local code-change reviews, a Rust change is not complete until `cargo fmt --all`, `cargo check --workspace`, and `cargo test --workspace` have been run fresh and read for failures. Flutter or bridge changes additionally require Flutter analysis/tests.
## 4. SRS Unit Coverage Focus
| SRS group | Unit focus | Status for DV |
|---|---|---|
| SRS-036 through SRS-043 | Rust core and state behavior | Reducer unit evidence present; candidate CI/run ID still required for release record |
| SRS-054 through SRS-061 | State sync reducers and replay support | Reducer unit coverage present; standalone event replay support remains P1/not complete |
| SRS-062 through SRS-083 | Audio capture, processing, codec, playback, controls | Partial; unit and benchmark evidence exists, full platform loopback is SWE.5/SYS.4 |
| SRS-084 through SRS-095 | Storage, secure storage, diagnostics | Partial; CI avoids real keyring and must be supplemented by platform audits |
| SRS-165 through SRS-178 | Localization and Unicode handling | Partial; generated localization exists and targeted tests should be reviewed |
| SRS-184 and platform behavior items | App initialization and platform services | Partial; service tests exist for back intent, permissions, bootstrap, and lifecycle |
## 5. Known SWE.4 Gaps
| Gap | Impact | Required DV handling |
|---|---|---|
| Standalone event replay tool is not yet complete | Limits P1 replay-based state-sync verification claims | Keep event replay waiver; reducer unit evidence is available |
| Event replay tool not found | P1 verification hook is incomplete | Mark deferred/P1 in SWE.6 and waiver register if discussed |
| Platform keyring behavior not exercised in CI | Secure-storage unit evidence is incomplete for real OS services | Cover through platform audit/SYS.4, not CI-only claims |
| Audio device hot-plug recovery follow-up exists | Limits reliability evidence for SRS-082 | Mark as P1 gap |
| Android runtime smoke cannot run without attached target | Rust unit tests do not exercise Android permission/audio/lifecycle fail-safes | `adb devices -l` must show a device or emulator before Android runtime success can be claimed |
## 6. SWE.4 DV Decision Rule
SWE.4 can pass for documentation readiness if all existing unit commands are identified and open unit gaps are listed as limitations. SWE.4 cannot be used to approve public release until required unit evidence is executed on the release candidate and attached to the release-readiness record.
@@ -1,71 +0,0 @@
# SWE.5 Software Integration Verification Plan
**Document status:** DV meeting baseline candidate
**Date:** 2026-05-29
**Scope:** Integration verification across Chanora software components
## 1. Purpose
This plan defines how Chanora verifies that independently tested software components work together. It covers the integration paths identified by SRS section 8 and SysDes verification handoff items.
## 2. Integration Paths
| Integration path | Covered components | Primary requirements | Evidence method |
|---|---|---|---|
| Flutter to bridge to Rust core | Flutter UI/state, generated FRB bindings, `chanora_bridge`, `chanora_core` | SRS-031 through SRS-035, SRS-103 | Flutter integration tests, Rust bridge tests, manual candidate smoke |
| Core to protocol adapter | `chanora_core`, `chanora_protocol`, `tsclientlib` | SRS-044 through SRS-053, SRS-131, SRS-134 | Protocol integration tests and compatible-server demo |
| Protocol to state | Protocol events, Rust core state handling, `chanora_state`, Flutter snapshot mapper | SRS-054 through SRS-061, SRS-124 | Reducer tests, snapshot mapper tests, reconnect/error tests |
| Audio to platform | `chanora_audio`, OS audio APIs, Flutter voice controls, platform permissions | SRS-062 through SRS-083, SRS-104 through SRS-115, SRS-135 | Audio loopback tests, platform smoke, mobile device tests |
| Storage to platform secure storage | `chanora_storage`, keyring adapters, Flutter bookmark/identity UI | SRS-084 through SRS-095, SRS-126, SRS-137 | Storage tests, platform secure-storage audit |
| Diagnostics export | Diagnostics crate, Flutter diagnostics UI, redaction, share/export surface | SRS-095 through SRS-102, SRS-126, SRS-128 | Redaction tests, diagnostic export review, manual export demo |
| Server resolution prefetch | Flutter host-field debouncer, `chanora_prefetch`, `chanora_resolver`, connect path | Resolver/prefetch design specs and connection requirements | Unit tests, Android connect smoke, manual connect demo |
| Packaging and release build | Flutter build, Rust cdylib/framework/DLL/SO packaging, CI workflows | SRS-116 through SRS-123, SRS-127 | CI build evidence, unsigned iOS build, platform-specific smoke |
## 3. Required Integration Evidence
| Evidence | Current state | DV conclusion |
|---|---|---|
| CI Rust workspace test run | Defined in `.github/workflows/ci.yml` | Accept as automated baseline when latest run is attached |
| CI Flutter analyze/test run | Defined in `.github/workflows/ci.yml` | Accept as automated baseline when latest run is attached |
| iOS unsigned release build | Defined in `.github/workflows/ci.yml` and `docs/release/ios-build.md` | Accept for unsigned build verification only |
| Audio benchmark advisory | Defined in `.github/workflows/bench-advisory.yml` | Accept as advisory performance evidence, not a release blocker |
| Windows smoke procedure | Defined in `tools/windows-smoke.md` | Accept only when an executed result is attached |
| Android connect and permission smoke | Referenced by implementation status and tests | Requires executed evidence for release decision |
## 4. Integration Acceptance Criteria
An integration path passes when:
| Criterion | Requirement |
|---|---|
| Buildability | Integrated components compile in CI or on the declared target build host |
| Data contract stability | DTOs and bridge boundaries preserve required fields and error states |
| Error behavior | Integration failures produce user-safe errors, not crashes or secret leakage |
| Platform behavior | Platform-specific permission, audio, and lifecycle behavior matches the target platform policy |
| Evidence attachment | Test logs, CI run IDs, smoke records, or manual demo notes are referenced in the release-readiness record |
## 5. Known SWE.5 Gaps
| Gap | Impact | Required DV handling |
|---|---|---|
| Desktop release artifacts are source-buildable only for current candidate | Blocks binary distribution readiness for Windows/macOS/Linux | Release record must state source-build-only scope |
| iOS build is unsigned | Blocks App Store/TestFlight release approval | Release record must state unsigned verification only |
| Android Keystore-backed DEK deferred | Limits secure-storage integration claim on Android | Waiver required for internal testing; public release claim blocked |
| Event replay infrastructure not found | Limits protocol-state integration stress evidence | Mark P1 gap |
| Android target compile/runtime blocked during local review | Missing NDK compiler `aarch64-linux-android-clang` and no attached authorized target block device/emulator verification of Android audio, permission, lifecycle, and storage fail-safe behaviour | Fix/install the NDK toolchain, connect a device/emulator, confirm with `adb devices -l`, then run Android build/install/smoke before claiming Android success |
## 6. Android Runtime Verification Gate
Android integration changes require a working Android target toolchain and a connected device or emulator. The minimum local gate is:
1. The Android NDK compiler needed by the target build, including `aarch64-linux-android-clang` for arm64, is available.
2. `adb devices -l` shows one authorized target.
3. Android app builds for that target.
4. The app installs and launches.
5. Permission, connect-screen, audio-start/stop, and diagnostic-export smoke paths are exercised or explicitly marked not applicable to the change.
If the NDK compiler is unavailable or no target is connected and authorized, Android verification is blocked rather than passed.
## 7. SWE.5 DV Decision Rule
SWE.5 can pass for DV documentation readiness if every integration path has an identified evidence method and every incomplete path has a waiver or follow-up. SWE.5 does not pass for public release until current candidate integration runs are attached to the release-readiness record.
@@ -1,62 +0,0 @@
# SWE.6 Software Verification Plan
**Document status:** DV meeting baseline candidate
**Date:** 2026-05-29
**Scope:** Integrated software verification against `docs/srs.md`
## 1. Purpose
This plan verifies the integrated Chanora software against the SRS. It focuses on SRS-128 and the MVP acceptance requirements inherited from SysRS-241 through SysRS-257.
## 2. SRS Verification Strategy
| SRS area | Verification approach | Evidence source |
|---|---|---|
| Software process and traceability | Review and inspection | `docs/srs.md`, `docs/governance/traceability-matrix.md` |
| UI and app shell | Flutter widget/service tests and demo | `apps/chanora_flutter/test/` |
| Bridge and Rust core | Workspace tests and integration smoke | CI Rust job, bridge/core tests |
| Protocol and connection | Protocol integration and compatible-server demo | Protocol tests, manual server demo |
| State sync | Reducer tests, snapshot mapper tests, reconnect/error scenarios, and runtime integration evidence | Rust state tests, Flutter mapper tests, compatible-server runtime evidence |
| Audio | Audio tests, processing tests, benchmark advisory, platform demo | `chanora_audio` tests/benches and manual platform evidence |
| Storage and secure storage | Storage tests and platform secure-storage audit | Rust storage tests, platform audit |
| Diagnostics and redaction | Redaction tests, diagnostic export demo, security review | Diagnostics tests, export review |
| Platform and release | Platform smoke and release build inspection | CI, platform smoke docs, release record |
## 3. MVP Acceptance Matrix
| SysRS | Acceptance requirement | SRS coverage | Required evidence | Current DV status |
|---|---|---|---|---|
| SysRS-241 | Connect to TeamSpeak 3-compatible server using `tsclientlib` | SRS-045, SRS-046, SRS-049, SRS-050, SRS-128, SRS-134 | Compatible-server connection demo and protocol integration evidence | Passed with limitation when demo log is attached; not sufficient for public release alone |
| SysRS-242 | Display server channel tree | SRS-019 through SRS-022, SRS-054 through SRS-058, SRS-128 | UI demo, snapshot/state tests | Reducer unit evidence present; candidate UI/demo and runtime reducer-integration evidence must still be attached |
| SysRS-243 | Display online clients | SRS-019 through SRS-022, SRS-054 through SRS-058, SRS-128 | UI demo, snapshot/state tests | Reducer unit evidence present; candidate UI/demo and runtime reducer-integration evidence must still be attached |
| SysRS-244 | Allow user to join a voice channel | SRS-023, SRS-024, SRS-045 through SRS-051, SRS-128 | Channel join demo, error mapper tests | Passed with limitation when candidate demo is attached |
| SysRS-245 | Send voice | SRS-062 through SRS-071, SRS-077, SRS-079, SRS-128 | Audio loopback/platform demo | Partial; platform evidence must be attached |
| SysRS-246 | Receive voice | SRS-071 through SRS-076, SRS-078, SRS-081, SRS-128 | Audio loopback/platform demo | Partial; platform evidence must be attached |
| SysRS-247 | Support microphone mute | SRS-025, SRS-077, SRS-079, SRS-128 | UI/audio gate demo or test | Passed with limitation when candidate demo is attached |
| SysRS-248 | Support output deaf | SRS-025, SRS-078, SRS-128 | UI/audio gate demo or test | Passed with limitation when candidate demo is attached |
| SysRS-249 | Support push-to-talk | SRS-077 through SRS-079, SRS-197 through SRS-200, SRS-128 | PTT backend tests, platform capability evidence | Partial; release record must state platform capability level |
| SysRS-250 | Support Echo Canceller | SRS-064 through SRS-067, SRS-125, SRS-128 | Audio processing test/demo | Partial; attach audio evidence |
| SysRS-251 | Support Automatic Gain Control | SRS-064 through SRS-067, SRS-125, SRS-128 | Audio processing test/demo | Partial; attach audio evidence |
| SysRS-252 | Support Noise Suppression | SRS-064 through SRS-067, SRS-125, SRS-128 | Audio processing test/demo | Partial; attach audio evidence |
| SysRS-253 | Support High-Pass Filter | SRS-064 through SRS-067, SRS-125, SRS-128 | Audio processing test/demo | Partial; attach audio evidence |
| SysRS-254 | Send and receive channel text messages | SRS-019, SRS-036 through SRS-038, SRS-170 through SRS-174, SRS-128 | Chat UI tests and compatible-server demo | Passed with limitation when candidate demo is attached |
| SysRS-255 | Save and reuse server bookmarks | SRS-084 through SRS-089, SRS-128 | Storage tests and UI demo | Passed with limitation when candidate demo is attached |
| SysRS-256 | Use secure storage for sensitive data | SRS-090 through SRS-095, SRS-126, SRS-137 | Security audit and platform storage evidence | Partial; Android Keystore-backed DEK deferred |
| SysRS-257 | Export redacted diagnostic logs | SRS-028, SRS-093 through SRS-102, SRS-126, SRS-128 | Redaction tests and export demo | Passed with limitation when redaction/export evidence is attached |
## 4. Candidate Software Verification Runs
For a release decision, the following run records must be attached or linked from `docs/release/release-readiness-go-nogo-record.md`:
| Run record | Command or method | Required for |
|---|---|---|
| Rust workspace CI | `cargo check --workspace --locked` and `cargo test --workspace --locked --no-fail-fast` | All Rust-backed SRS behavior |
| Flutter CI | `flutter analyze` and `flutter test --exclude-tags e2e` | UI, service, and widget SRS behavior |
| Candidate compatible-server demo | Manual or scripted demo against a controlled TeamSpeak-compatible server | SysRS-241 through SysRS-246, SysRS-254 |
| Candidate audio demo | Manual or scripted loopback/platform run | SysRS-245 through SysRS-253 |
| Candidate diagnostics demo | Export and inspect redacted diagnostic bundle | SysRS-257, SRS-093 through SRS-102 |
| Candidate secure-storage audit | Platform inspection for Windows, macOS, Linux, iOS, Android | SysRS-256, SRS-090 through SRS-095 |
## 5. SWE.6 DV Decision Rule
SWE.6 can pass the DV meeting if the acceptance matrix is accepted as the controlling checklist and each partial item is carried into the release-readiness record. SWE.6 cannot approve public release while DEC-012, Android secure-storage limitation, platform signing, and incomplete candidate evidence remain open.
@@ -1,58 +0,0 @@
# SYS.4 System Integration Verification Plan
**Document status:** DV meeting baseline candidate
**Date:** 2026-05-29
**Scope:** System integration verification against `docs/sysdes.md`
## 1. Purpose
This plan verifies Chanora as an integrated application system, including software, operating-system services, hardware, network dependencies, external compatible servers, diagnostics, and release operations.
## 2. System Elements Under Verification
| Element | Integration concern | Verification method |
|---|---|---|
| External TeamSpeak 3-compatible server | Connection, authentication, channel tree, clients, voice, channel text, server permissions | Compatible-server demo and protocol compatibility matrix |
| OS audio services | Capture, playback, route changes, permissions, mobile audio session, foreground behavior | Platform audio tests and manual device smoke |
| Audio hardware | Microphone/headset/speaker availability and failure handling | Platform smoke and user-safe error checks |
| Platform secure storage | Keychain/Credential Manager/Secret Service/mobile key stores and fallback behavior | Platform security audit |
| Network | DNS/SRV/TSDNS resolution, unreachable server behavior, reconnect | Resolver tests and network failure smoke |
| Platform packaging | Android, iOS, Windows, macOS, Linux build and packaging behavior | CI build, unsigned iOS build, platform smoke, release inspection |
| Diagnostics export | User-initiated export and secret redaction | Export demo and security review |
| Public wording | Non-affiliation and compatible-server claims | Legal/trademark review |
## 3. SysDes Verification Handoff Coverage
| SysDes item | Handoff | SYS.4 handling |
|---|---|---|
| SysDes-102 | Protocol verification via protocol probe and compatibility matrix | Requires compatible-server evidence and protocol adapter review |
| SysDes-103 | State verification via reducer and event replay tests | Reducer evidence handled in SWE.4/SWE.5; event replay remains P1 gap |
| SysDes-104 | Audio loopback and processing tests | Requires platform audio evidence and processing tests |
| SysDes-105 | Security audit for storage, keys, passwords, validation, redaction | Requires security/privacy/legal gate review |
| SysDes-106 | Deployment package, signing, notarization, app-store build, metadata | Release-readiness record controls final decision |
| SysDes-107 | MVP acceptance verification for SysRS-241 through SysRS-257 | SWE.6 acceptance matrix controls software evidence; SYS.4 adds environment evidence |
## 4. Platform Matrix
| Platform | Current candidate status | Required SYS.4 evidence before public/store release |
|---|---|---|
| Android | Implemented features include permissions, foreground service, Oboe audio, MODE_IN_COMMUNICATION; Android Keystore-backed DEK deferred; local target compile/runtime smoke blocked by missing `aarch64-linux-android-clang` and no authorized ADB target | NDK target compilation, `adb devices -l` authorized target evidence, device smoke, permission flow, foreground voice, secure-storage limitation waiver, Play target SDK inspection |
| iOS | Source-buildable and unsigned; AVAudioSession work exists; public artifact not ready | Unsigned build evidence, device audio session smoke, signing/TestFlight evidence before release |
| Windows | Source-buildable; smoke procedure exists | Executed smoke result, PTT capability evidence, packaging/signing evidence before release |
| macOS | Source-buildable; not in current release artifacts | Build evidence, PTT capability evidence, signing/notarization evidence before release |
| Linux | Source-buildable; GlobalShortcuts portal behavior depends on environment | Build/smoke evidence, portal/focused fallback capability evidence, packaging evidence before release |
## 5. SYS.4 Acceptance Criteria
| Criterion | Required result |
|---|---|
| External server compatibility | Candidate connects to a controlled compatible server and exercises connection, channel, voice, and text flows |
| Platform behavior transparency | Release notes and UI do not overstate platform PTT, packaging, or secure-storage capabilities |
| Security/privacy/legal readiness | DEC-012 and privacy/security gates are signed off or explicitly block release |
| Release artifact integrity | Build number, commit SHA, tag, artifact hashes, and signing status are recorded |
| Environmental limitations | Source-build-only, unsigned, or platform-specific limitations are listed in release readiness |
| Android runtime claim control | No Android runtime, permission-flow, or audio-lifecycle success is claimed until target compile, install, and device/emulator smoke evidence are attached |
## 6. SYS.4 DV Decision Rule
SYS.4 can pass the documentation baseline if system integration responsibilities, platform evidence needs, and release blockers are explicit. SYS.4 cannot pass for public/store release until platform-specific evidence and legal/signing gates are complete.
@@ -1,91 +0,0 @@
# Chanora Verification Master Plan
**Document status:** DV meeting baseline candidate
**Date:** 2026-05-29
**Applies to:** Chanora Rust workspace `0.2.0-beta.1`, Flutter app `0.3.0+100`, and current DV/release-candidate evidence
**Primary upstream documents:** `docs/sysrs.md`, `docs/sysdes.md`, `docs/srs.md`, `docs/architecture/sad.md`, `docs/architecture/sdd.md`, `docs/implementation-status-2026-05-28.md`
## 1. Purpose
This plan defines the verification evidence Chanora must present at the DV meeting. It does not approve release by itself. It gives reviewers a single route from requirements and design baselines to available tests, demos, audits, waivers, and release gates.
The DV meeting may approve the verification posture for continued internal candidate work if the open gates are accepted as explicit waivers. Public or store release remains blocked until the release-readiness record reaches `Go`.
## 2. Verification Lifecycle Mapping
| Lifecycle level | Plan | Primary input | Verification focus |
|---|---|---|---|
| SWE.4 | `docs/verification/swe4-unit-verification-plan.md` | `docs/architecture/sdd.md` module behavior plus current crate and Flutter tests | Unit behavior of reducers, protocol mappers, audio processors, storage, diagnostics, UI services, and utility logic |
| SWE.5 | `docs/verification/swe5-software-integration-verification-plan.md` | `docs/architecture/sad.md` component interfaces and `docs/architecture/sdd.md` module integration hooks | Integration across Flutter, bridge, Rust core, protocol, audio, storage, diagnostics, resolver, and packaging boundaries |
| SWE.6 | `docs/verification/swe6-software-verification-plan.md` | `docs/srs.md` | Integrated software verification against SRS, especially SRS-128 MVP acceptance |
| SYS.4 | `docs/verification/sys4-system-integration-verification-plan.md` | `docs/sysdes.md` and external environment assumptions | System integration with compatible servers, OS services, hardware, network, app stores, diagnostics, and release operations |
## 3. Verification Policy
Verification evidence shall be recorded as one of these states:
| State | Meaning | DV handling |
|---|---|---|
| Passed | Evidence exists and satisfies the stated criterion | Accept as supporting evidence |
| Passed with limitation | Evidence exists, but scope is narrower than final release scope | Accept only with documented limitation |
| Not run | Criterion is defined but no run is recorded for the candidate | Requires waiver or follow-up action |
| Failed | Evidence exists and does not satisfy the criterion | Blocks the covered release scope unless waived by the release owner |
| Deferred | Requirement is intentionally outside current candidate scope | Requires requirement stage or waiver reference |
| Blocked | External decision, platform access, legal sign-off, or environment prevents completion | Requires owner and unblock condition |
No document in this pack may convert an implementation gap into a pass. Gaps must be represented as `Not run`, `Deferred`, or `Blocked`.
## 4. Current Evidence Sources
| Evidence source | Current content | DV use |
|---|---|---|
| `.github/workflows/ci.yml` | Rust workspace check/test, advisory clippy, cargo-deny, cargo-about inventory check, Flutter analyze/test, unsigned iOS release build | Build, unit, static-analysis, supply-chain, Flutter test, and iOS unsigned build evidence |
| `.github/workflows/bench-advisory.yml` | Advisory-only realtime audio benchmark workflow for PR/push events | Performance trend evidence, not a hard quality gate |
| `docs/implementation-status-2026-05-28.md` | Current implementation status, blockers, partial areas, and P1/P2 gaps | Primary readiness and waiver input |
| `apps/chanora_flutter/test/` | Flutter widget/service/e2e-labeled tests | SWE.4/SWE.5/SWE.6 evidence depending on test type |
| Rust crate tests and benches | Workspace tests plus audio benchmark harnesses | SWE.4/SWE.5 performance and component evidence |
| `tools/windows-smoke.md` | Windows source-build smoke procedure | SYS.4/SWE.5 manual platform evidence when executed |
| `docs/release/ios-build.md` | Unsigned iOS verification build note | Release and platform build evidence |
## 5. Entry Criteria for DV Review
| Criterion | Status | Evidence |
|---|---|---|
| SysRS baseline available | Met | `docs/sysrs.md` |
| SysDes baseline available | Met | `docs/sysdes.md` |
| SRS baseline available | Met | `docs/srs.md` |
| SAD baseline available | Met | `docs/architecture/sad.md` |
| SDD baseline available | Met | `docs/architecture/sdd.md` |
| Verification plans available | Met by this pack | `docs/verification/` |
| Traceability summary available | Met by this pack | `docs/governance/traceability-matrix.md` |
| Release decision record available | Met by this pack | `docs/release/release-readiness-go-nogo-record.md` |
| Open gates represented as waivers or blockers | Met by this pack | `docs/release/dv-waiver-register.md` |
## 6. Exit Criteria for DV Meeting
The DV meeting can pass the documentation baseline if reviewers agree that:
| Exit criterion | Required result |
|---|---|
| Requirements-to-verification route is reviewable | SysRS/SysDes/SRS items map to verification plans and acceptance evidence |
| MVP acceptance criteria are explicit | SysRS-241 through SysRS-257 appear in SWE.6 with evidence status |
| Verification scope is honest | Known gaps are not marked as passed |
| Waivers are explicit | Each release-affecting gap has owner, impact, mitigation, and unblock condition |
| Release recommendation is clear | Current candidate is not represented as public-release-ready while DEC-012 and other gates remain open |
## 7. Open Gates Affecting Release
| Gate | Status | Release impact | Owning document |
|---|---|---|---|
| DEC-012 legal/trademark/OSS sign-off | Blocked / open | Blocks public or store release | `docs/legal/trademark-and-attribution-review.md`, `docs/release/dv-waiver-register.md` |
| Android Keystore-backed DEK | Deferred to v1.1 | Blocks claim that Android secrets use hardware-backed DEK protection | `docs/release/dv-waiver-register.md` |
| Android target compilation and runtime smoke | Blocked locally | Blocks Android runtime, permission-flow, and audio-lifecycle success claims until NDK compiler and authorized target evidence exist | `docs/governance/maintainability-review-2026-06-08.md`, `docs/release/dv-waiver-register.md` |
| Full state reducer test suite | Partial | Blocks full claim for SysRS-235/SysDes-103/SRS-059 through SRS-061 | `docs/release/dv-waiver-register.md` |
| Desktop and iOS release artifacts | Source-buildable / unsigned only | Blocks broad binary distribution claims | `docs/release/release-readiness-go-nogo-record.md` |
| Store signing and notarization | Not complete for candidate | Blocks production release | `docs/release/release-readiness-go-nogo-record.md` |
## 8. DV Recommendation
Recommended DV outcome: **Pass documentation baseline with release waivers recorded**.
This means the project has enough document structure to conduct DV review and continue internal candidate validation, but it does not mean the candidate is approved for public release. The release decision remains **No-Go for public/store release** until legal, signing, platform, and evidence gates are closed or formally waived by the accountable owners.