docs/codebase-analysis-and-cleanup
13
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
8487acf167 | docs: align review findings and verification gates | ||
|
|
2f47e7ccee |
chore: prepare v0.3.0 release
bench-advisory / bench-advisory (push) Failing after 7m7s
ci / cargo check + cargo test (push) Successful in 10m56s
ci / cargo deny (licenses + advisories + bans + sources) (push) Successful in 53s
ci / cargo about (license inventory) (push) Successful in 10m46s
ci / flutter license inventory (push) Successful in 2m13s
ci / flutter analyze (push) Successful in 36s
ci / flutter iOS unsigned release build (push) Has been cancelled
- Rewrite CHANGELOG.md with v0.3.0 entry - Bump version to 0.3.0+100 - Fix split-per-abi Android APK builds |
||
|
|
ddf858cc6c | fix(audio): address CoreML VAD review feedback | ||
|
|
50768a8f48 |
feat(mvp): v1.0.0-rc.1 — keyring-backed DEK, encrypted bookmarks, MVP release-gate docs
Closes the v0.4 dual-file weakness in identity-at-rest and turns the release into an MVP public release candidate. The remaining work before `v1.0.0` is DEC-012 legal sign-off — see `docs/governance/legal-review-readiness.md` — and the staged platform promotions in `docs/governance/staged-release-plan.md`. No decision rows in `product-decision-register.md` change; the register's change-history advances to 0.9.8. `chanora_storage` ----------------- * New public `Crypto` trait + `IdentityFileStore::crypto()` give callers an encrypt / decrypt pair anchored on the per-install 32-byte DEK without exposing the key material. * `IdentityFileStore` keyring-first DEK retrieval (Linux Secret Service via D-Bus, macOS Keychain, Windows Credential Manager, iOS Keychain via the `keyring` crate). Pre-existing `identity.dek` files are opportunistically migrated into the keyring on first run; the on-disk DEK copy is removed once the keyring acknowledges. `CHANORA_DISABLE_KEYRING=1` forces the file-fallback path for tests and headless / CI hosts where a real keyring call would prompt the user or block on a missing D-Bus session. * `BookmarkRepository::with_crypto(dir, crypto)` encrypts the server password into a new `password_blob` BLOB column under the same per-install DEK. Schema v2 migration is idempotent — legacy v0.4 rows with a plain `password TEXT` are read transparently and lifted into `password_blob` on the next `update()`. `BookmarkRepository::new` (no crypto) is preserved for tests and as a documented fallback when the DEK is unreachable. * Storage tests rise from 8 to 10: encrypted bookmark password round-trip + legacy-plaintext-bookmark upgrade. `chanora_core` -------------- * `ChanoraSession::init_storage(dir)` wires the bookmark repository with crypto by default. On any crypto-derivation failure it falls back to the plain-password repository and logs the gap — better than hard-failing init. * `supervisor_loop` now tracks a 64-bit `snapshot_signature` over channels (id + parent + order + name) and clients (id + channel + name) instead of the old `(channel_count, client_count)` tuple. Any in-channel client move, channel rename, or reorder now fires `SessionEvent::SnapshotChanged`. The signature sorts by id before hashing so it's stable under input-vector reordering. * Two new unit tests cover the signature behaviour; new `tests/mvp_storage.rs` integration test drives `ChanoraSession::init_storage` end-to-end and verifies the bookmark `password_blob` does not contain the plaintext. * Re-export `ChannelId` + `ClientId` from `chanora_protocol` so downstream callers and tests can construct DTOs directly. Flutter ------- * New About dialog (info icon in the AppBar) surfaces DEC-018 (public name "Chanora"), DEC-019 (non-affiliation statement), and DEC-020 (Apache-2.0 OR MIT dual license). New ARB keys in `app_en.arb` and `app_zh.arb`: `aboutAction`, `aboutVersion`, `aboutNonAffiliation`, `aboutLicenseHeading`, `aboutLicenseBody`, `aboutThirdPartyHeading`, `aboutThirdPartyBody`. * `pubspec.yaml` version bumps to `1.0.0-rc.1+5`. Governance ---------- * `docs/governance/legal-review-readiness.md` — DEC-012 handoff package. Enumerates trademark / non-affiliation / license-text / third-party-attribution / `tsclientlib`-posture / crypto- export / data-handling items the legal reviewer must confirm, and lists the concrete engineering deliverables they block on (`cargo about generate`, `cargo deny check licenses`, Flutter `LicenseRegistry` dump). * `docs/governance/staged-release-plan.md` — DEC-002 channel schedule. Linux + Android sideload promote to GA on DEC-012 sign-off; Play Store / Windows / macOS / iOS gate on per- platform signed-build availability. Rollback policy included. * `product-decision-register.md` change-history advances to 0.9.8 with a single entry summarising v0.3, v0.4, and v1.0-rc.1 progress against DEC-001. No decision rows mutate. Build + ops ----------- * `NOTICE` refreshed for the MVP product-code dependency set: adds `chacha20poly1305`, `rand`, `zeroize`, `base64`, `keyring`, `connectivity_plus`, `path_provider`, `freezed_annotation`; drops PoC-only entries. * `CHANGELOG.md` restructured: explicit version sections for v0.3.0-beta.1, v0.4.0-beta.2, v1.0.0-rc.1. Previous "Unreleased" contents migrated into their respective milestone sections. * `.github/workflows/ci.yml` exports `CHANORA_DISABLE_KEYRING=1` for the cargo-test job — CI runners have no D-Bus session and the keyring crate would otherwise block. * `run-chanora.sh` reads `CHANORA_BUNDLE_FLAVOUR` (default `release`) and self-copies the latest cdylib into the bundle's `lib/` if missing. Verification ------------ * `cargo test --workspace` with `CHANORA_DISABLE_KEYRING=1`: all green (49 unit tests across the workspace; up from 36 at v0.4.0-beta.2). * `cargo test -p chanora_core --release -- --ignored alpha_smoke` passes against the live `cn.teamspeak.app` (DNS → connect → snapshot → disconnect in ~2.5 s). * `flutter analyze`: clean. * `cargo build -p chanora_bridge --release` + `flutter build linux --release` produce a working Linux x86_64 bundle. No Android live test in this commit per the user's note that the physical device was removed; the Android arm64-v8a build path is mechanically identical to v0.4.0-beta.2. |
||
|
|
9790005c3e |
feat(beta): wire voice in/out end-to-end with push-to-talk (v0.2.0-beta.1)
Reaches the Internal Beta milestone of DEC-001's release sequence the
same day as Alpha. Adds voice capture and playback through the full
Flutter UI → FRB → Rust core → tsclientlib → server path.
Promotions from PoC:
poc/audio-capture-playback-spike → crates/chanora_audio/
New product code:
crates/chanora_audio/src/engine.rs — cpal capture and playback,
audiopus Opus VoIP encoder (48 kHz mono 20 ms frames), tsclientlib
AudioHandler for decode + jitter buffer + mix on playback,
push-to-talk gate, graceful playback-only fallback when capture
is unavailable.
crates/chanora_protocol/src/adapter.rs — extended with
voice_out_tx (clonable mpsc::Sender<OutPacket>) and
take_voice_in() (one-shot mpsc::Receiver<InboundVoice>); main
loop now interleaves outbound voice drain, event pumping, and
control-request handling.
crates/chanora_protocol/src/lib.rs — re-exports the few
tsproto_packets types (OutAudio, OutPacket, InAudioBuf,
AudioData, CodecType, Direction) that chanora_audio
legitimately needs. Documented as the single deliberate
cross-crate type re-export per SAD-067, justified by the
performance cost of a parallel type hierarchy on the 20 ms
voice frame.
core/chanora_core/src/lib.rs — ChanoraSession::start_audio,
set_ptt, audio_stats; disconnect now stops the engine first.
crates/chanora_bridge/src/api.rs — startAudio, setPtt,
audioStats commands and BridgeAudioStats DTO.
apps/chanora_flutter/lib/main.dart — "Start audio" button +
hold-to-talk PTT button with pressed/released visual state +
live stats line (TX/RX/PTT). Stats polled every 500 ms.
ARB:
Both en and zh-Hans gain startAudioAction, pttHoldToTalk,
pttTransmitting, audioStatsLine. Banner updated to
"Beta build — voice in/out wired; not production ready."
FRB config:
flutter_rust_bridge.yaml gains local: true so codegen resolves
the workspace member's library stem to "chanora_bridge" instead
of falling back to "UNKNOWN".
Empirical verification (2026-05-14, against cn.teamspeak.app):
cargo check + cargo test --workspace: all green.
flutter analyze: 0 issues.
flutter test: 4/4 passing including:
- test/alpha_e2e_test.dart (regression: Alpha still works)
- test/beta_e2e_test.dart (Beta: connect → startAudio →
PTT cycle → disconnect against cn.teamspeak.app).
Live smoke (cargo test alpha_smoke -- --ignored): 49 channels,
37 clients retrieved.
Capture stream open against the host PipeWire auto_null source
refused (snd_pcm_hw_params); engine correctly logged the warning
and continued in playback-only mode. TX=0 frames, RX=0 frames
reflects the headless null-source environment; on a real mic
host the encoder produces ~50 frames/second while PTT is held.
Honest Beta scope (NOT in this release):
- AEC / AGC / NS / HPF DSP (DEC-007..010): AudioEffects exists
as a struct but the filters are no-ops. Beta+ work.
- Production-quality resampler: current code is linear
interpolation. Beta+ work.
- Identity persistence via chanora_storage: still ephemeral.
- Push-to-Dart event stream: UI polls instead.
- chanora_diagnostics tracing-layer wiring: still scaffold.
- Mobile (Android) cdylib + UI: PoC-proven, not yet in product.
- Reconnect / network-loss recovery for the voice path.
Docs updates:
- docs/governance/product-decision-register.md bumped to v0.9.7
(Beta-milestone change-history entry; no row changes).
- docs/governance/poc-results-summary.md bumped to v0.6.0
(RISK-PoC-005 updated with Beta progress).
|
||
|
|
4915ec0a1b |
feat(alpha): wire connect→snapshot→disconnect end-to-end (v0.1.0-alpha.1)
First Internal Alpha build per DEC-001. Closes the milestone of
'Flutter UI calls Rust via the typed bridge, Rust connects to a
TeamSpeak-compatible server through tsclientlib, returns a typed
snapshot, and disconnects cleanly.' Audio remains Beta scope.
Promotions from PoC:
poc/tsclientlib-connect-spike → crates/chanora_protocol/
New product code:
crates/chanora_protocol/src/{dto.rs,adapter.rs} — typed boundary
over tsclientlib. Tokio task owns the Connection; public
handle communicates via mpsc/oneshot. No tsclientlib types
cross out of the crate (SAD-067 / SysDes-011 / SysDes-029).
core/chanora_core/src/lib.rs — ChanoraSession composes the
protocol crate, enforces the DEC-006 single-connection
invariant.
crates/chanora_bridge/src/{api.rs,frb_generated.rs} — FRB 2.12.0
bridge per DEC-014. cdylib + staticlib + rlib. Typed
BridgeSnapshot / BridgeChannel / BridgeClient / BridgeError
DTOs. Process-wide OnceLock<Runtime> + OnceLock<ChanoraSession>.
flutter_rust_bridge.yaml at repo root.
apps/chanora_flutter/lib/main.dart — Alpha UI: server form,
connect button, channel tree, disconnect.
apps/chanora_flutter/lib/l10n/app_{en,zh}.arb expanded with the
Alpha key set; ARB metadata reaffirms ADR-008 for
server-provided content.
Generated Dart bindings under apps/chanora_flutter/lib/src/rust/.
Empirical verification (2026-05-14):
Workspace: cargo check + cargo test clean
(workspace tests: all green).
Bridge cdylib: target/release/libchanora_bridge.so produced
(~15 MB).
Flutter: flutter analyze clean; flutter test runs 3/3 green
including the alpha_e2e_test that drives the full
Dart → FRB → chanora_bridge → chanora_core → chanora_protocol
→ tsclientlib → UDP → cn.teamspeak.app
path. The captured logcat/stdout shows the tsproto resender
transitioning Connected → Disconnecting → Disconnected on
clean teardown.
Architecture changes:
- Removed the chanora_core ↔ chanora_bridge cyclic dependency.
chanora_core no longer knows the bridge exists; the bridge
maps from CoreError.
- chanora_bridge crate's #![forbid(unsafe_code)] lint relaxed
because FRB-generated glue legitimately uses unsafe at the
FFI boundary. Hand-written code remains unsafe-free.
Open follow-ups (NOT in this Alpha):
- Audio capture/playback wiring into chanora_audio
(Beta scope per DEC-001).
- Identity persistence via chanora_storage
(currently regenerated on every connect).
- Per-message diagnostics + redaction
(chanora_diagnostics still scaffold).
- Reconnect / network-loss recovery.
- Mobile (Android) build of the bridge cdylib + UI verification.
|
||
|
|
e0f34009d9 |
docs(governance): record product scaffolding paths (DEC-022)
Updates two documents to reflect the workspace + Flutter app
scaffold landed in the previous commit.
path-migration-map.md v0.9.2 -> v0.9.3:
Adds §3 Implementation Path Layout. Lists each subsystem's
canonical crate path alongside its SAD / SysDes / DEC authority.
Notes that the Flutter app is owned by Flutter tooling and is
not a Cargo workspace member.
CHANGELOG entry under [Unreleased]:
- Documents the seven new Cargo workspace members and the
invariants pinned at the workspace level.
- Documents the Flutter app scaffold, the DEC-004 minSdk = 28
override, and the DEC-015 English + Simplified Chinese ARB
catalogue (with the ADR-008 server-content reaffirmation).
- Records the empirical verification (cargo check + cargo test
+ flutter analyze + flutter test all clean).
|
||
|
|
0f418f1d7e |
feat(legal): resolve DEC-020 — dual-license under Apache-2.0 OR MIT
Closes the only previously-open decision in the register. Chanora is
now dual-licensed under either:
* Apache License, Version 2.0 (LICENSE-APACHE), OR
* MIT License (LICENSE-MIT)
at the recipient's option. This is the standard Rust-ecosystem
permissive model and is compatible with every direct dependency
in the PoC tree:
tsclientlib MIT OR Apache-2.0
flutter_rust_bridge MIT
cpal Apache-2.0
rusqlite MIT
keyring MIT OR Apache-2.0
hound Apache-2.0
ndk-context, jni, android_logger, regex, serde, tokio,
tracing, thiserror, zeroize, etc. MIT OR Apache-2.0
and with the Flutter framework's BSD-3-Clause.
Files added:
- LICENSE-APACHE Apache 2.0 license text.
- LICENSE-MIT MIT license text with the standard 2026 copyright
line.
Files updated:
- LICENSE Now the dual-license aggregator. Includes the standard
Apache-2.0 inbound-contribution clause ("Unless you
explicitly state otherwise, any contribution
intentionally submitted for inclusion in Chanora by you,
as defined in the Apache-2.0 license, shall be
dual-licensed as above, without any additional terms or
conditions.").
- NOTICE Rewritten with the dual-license declaration and an
inventory of direct dependencies with their upstream
licenses. Transitive deps remain to be enumerated by
build tooling (cargo about, Flutter LicenseRegistry).
- README.md §License section rewritten to point at LICENSE-APACHE
and LICENSE-MIT.
- docs/governance/product-decision-register.md v0.9.5 → v0.9.6:
DEC-020 status: Open → Accepted. §4 license row updated. §6
collapsed: every previously-Proposed or Open decision in the
register is now resolved. DEC-012 legal review remains as a
release-gating *work* item, but is not an open decision.
- docs/governance/poc-results-summary.md v0.3.0 → v0.4.0:
RISK-PoC-003 closed. DEC-020 row moved out of 'Still open'.
This is a license-model commitment, not a substitute for the
DEC-012 legal review. Per DEC-012 the actual legal review work
(transitive-dep OSS obligations, trademark registrability, final
sign-off on the non-affiliation wording) must still be completed
before any public/store release; that is sign-off work, not an
architectural decision.
Decision register state after this commit:
Accepted: 23 of 23 unique decisions
Open/Deferred: 0
Proposed: 0
|
||
|
|
a0d1c35461 |
docs(governance): owner confirmation on remaining 17 decisions (register v0.9.5)
Closes the 'Proposed / Owner Confirmation Required' state for every
decision in the register except DEC-020 (license, explicitly deferred
and now the only public-release-gating decision outstanding).
Accepted as recommended:
DEC-001 (Alpha → Beta → Public release sequence),
DEC-002 (all five platforms as MVP target, staged release allowed),
DEC-003 (iOS minimum: iOS 13),
DEC-005 (Android target SDK: Play-required API on upload date),
DEC-006 (single active server connection in MVP),
DEC-007/008/009/010 (AEC + AGC + NS + HPF defaults),
DEC-011 (platform-native audio first),
DEC-012 (legal/trademark/licensing review as a release gate),
DEC-013 (SQLite or equivalent for non-secret state),
DEC-016 (no automatic diagnostics upload),
DEC-017 (crash reporting disabled for MVP),
DEC-018 (product name: Chanora),
DEC-019 (drafted non-affiliation wording),
DEC-021 (Apple App Store SDK gate: Xcode 26+ / iOS 26 SDK+ on/after 2026-04-28).
Modified from the original recommendation by explicit owner ruling:
- DEC-004: Android minimum raised to API 28 (Android 9.0) from the
recommended API 24. Rationale: simpler audio path (AAudio stable
from API 28), narrower compatibility / privacy / scoped-storage
surface. Affects the Android spike's minSdk=24 in product code:
apps/chanora_flutter will need minSdk=28.
- DEC-015: MVP product language expanded to English + Chinese
(Simplified) from the recommended English-only. Rationale: the
demonstrated TS3-compatible-server audience (verified live against
cn.teamspeak.app) and broader TS3 audience include substantial
Chinese-speaking users. Adds zh-Hans translation, font, and
text-length-budget work to MVP. Server-provided content is still
preserved verbatim per ADR-008.
Still Open / Deferred:
- DEC-020 license model. The only remaining release-gating decision.
Documentation updates:
- product-decision-register.md → v0.9.5. §3 statuses updated, §4
renamed Recommended → Accepted with MODIFIED rows annotated,
§6 collapsed to DEC-020 only, §7 dated and statused for every
decision, change-history entry added.
- poc-results-summary.md → v0.3.0. §4 expanded with the
2026-05-14 owner-confirmation pass table. RISK-PoC-004 closed.
New RISK-PoC-006 (Android minSdk move 24 → 28) and RISK-PoC-007
(MVP language expansion to en + zh-Hans) added.
- CHANGELOG entry under [Unreleased].
|
||
|
|
4c64517e45 |
docs(governance): promote audio PoC to PASS; close mobile-Android half
Documentation update following the Android audio spike pass.
Decision register (v0.9.3 → v0.9.4):
- DEC-011.1 promoted from
'Accepted (desktop: cpal) / Deferred (mobile)'
to
'Accepted (desktop: cpal; Android: cpal-on-Oboe) / Deferred (iOS)'.
- Evidence pointer added: poc/audio-capture-playback-android-spike/
VERIFICATION.md.
PoC plan (v0.2.0 → v0.3.0):
- Audio row promoted from PARTIAL PASS to PASS.
- All six PoC plan entries are now PASS.
PoC results summary (v0.1.0 → v0.2.0):
- Audio row collapsed into one PASS spanning both spikes.
- RISK-PoC-001 narrowed from 'mobile audio' to 'iOS audio only'.
- Toolchain table expanded with Android NDK, cargo-ndk, AGP/
Gradle/Kotlin, jni/ndk-context/android_logger, and the test
device.
Cross-spike pointers updated:
- poc/audio-capture-playback-spike/VERIFICATION.md result and
follow-up sections updated to reference the Android spike.
- poc/README.md status table lists both audio spike directories.
CHANGELOG updated under [Unreleased].
|
||
|
|
271d23faf7 |
docs(governance): record PoC outcomes, owner decisions, and audit evidence
Closes Phases A and D of the post-PoC sequencing.
Decision register (v0.9.2 → v0.9.3):
- DEC-014 Accepted: flutter_rust_bridge 2.x pinned (closed by
poc/flutter_rust_bridge_hello).
- DEC-013.1 Accepted: rusqlite (bundled) (closed by
poc/sqlite-storage-spike).
- DEC-013.2 Accepted: Linux secure-storage backend policy —
Secret Service preferred, keyutils fallback (closed by
poc/secure-storage-spike; resolves SysRS-053 / SysRS-162
ambiguity).
- DEC-011.1 Accepted (desktop: cpal) / Deferred (mobile)
(closed by poc/audio-capture-playback-spike desktop half only).
- DEC-022 Accepted: canonical implementation directory layout per
the README sketch and SAD §7.2.
- DEC-020 explicitly Deferred by owner; remains a public-release
blocker.
Audit reports updated with empirical evidence:
- docs/security/secure-storage-audit-report.md v0.9.3:
SS-AUD-001/002/003/005/006 = PoC Pass with evidence pointers;
SS-TC-003 (Linux) Actual Result populated and Status = PoC Pass;
SS-AUD-004 cross-referenced to diagnostics-redaction PoC;
findings SS-FIND-001 (closed by DEC-013.2), SS-FIND-002 (keyutils
session caveat), SS-FIND-003 (non-Linux adapters still open).
- docs/security/diagnostic-redaction-audit-report.md v0.9.3:
REDACT-TC-001..010 = PoC Pass with evidence pointers; export
bundle policy §5 populated for every row; findings
REDACT-FIND-001 (regex coverage), REDACT-FIND-002
(tracing-layer integration), REDACT-FIND-003 (cross-spike
KnownSecretRegistry contract).
PoC plan (v0.1.0 → v0.2.0):
- Status column added to §2; outcomes recorded.
New doc:
- docs/governance/poc-results-summary.md v0.1.0 — single-page
reviewer-facing summary listing each spike's status, the
toolchain exercised, the owner decisions taken, the audit
coverage table, and open risks RISK-PoC-001..005 (mobile audio,
non-Linux secure-storage adapters, license, remaining
Proposed decisions, no product code yet).
This completes the post-PoC documentation work. Repo is at a clean
pause point: PoC code is committed, owner decisions are recorded,
audit reports carry empirical evidence, and the residual risks are
named in the summary doc.
|
||
|
|
181b3d329d |
docs(poc): add PoC index and record PoC outcomes in CHANGELOG
Adds poc/README.md as the top-level index across all six PoC spikes, recording status (5 PASS, 1 PARTIAL PASS), authority, and the non-promotion rule from proof-of-concept-plan.md §4. Updates CHANGELOG.md to enumerate the six spikes with their verification dates and to reference each spike's VERIFICATION.md. This completes Phase E of the post-bootstrap sequencing: E.1 git init + baseline import E.2 justfile E.3..E.8 six PoC spikes E.9 PoC index + CHANGELOG ← this commit |
||
|
|
f1bc9a6c85 |
chore(repo): initial baseline import (docs v0.9.2 + bootstrap)
Imports the v0.9.2 documentation baseline and the bootstrap files required by docs/governance/repository-bootstrap-plan.md v0.1.0 §3, minus the justfile (added in the next commit). This commit establishes the git history for the project. All previous work lived only as filesystem state with no version control. |