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.
8.0 KiB
Legal review readiness — DEC-012 sign-off checklist
| Version | Date | Status |
|---|---|---|
| 0.1.0 | 2026-05-15 | Initial draft alongside v1.0.0-rc.1 |
Purpose
DEC-012 in product-decision-register.md records the legal /
trademark / licensing review as the only outstanding gate before
the MVP public release per DEC-001 sequencing. That decision was
accepted as a release gate on 2026-05-14; the actual review work
has not been performed.
This document is the engineering-side handoff package for that review. It enumerates exactly what the reviewer needs to confirm, points to the artefacts in this repository that answer each item, and lists the work the reviewer must perform that the engineering side cannot.
Engineering does not make legal decisions. Items marked "engineering: done" mean the underlying technical artefact is in place; the corresponding legal confirmation is still required.
Scope
Reviewer is expected to confirm or correct each of the following
before v1.0.0-rc.1 is promoted to v1.0.0 and any release
artefact is published publicly or to a store.
1. Trademark — "Chanora"
- DEC-018 accepted "Chanora" as the public product name.
- Engineering: name appears in
Cargo.toml,pubspec.yaml, the About dialog, the AppBar title via theappTitlelocalisation key, and every commit message. - Reviewer action:
- Trademark registrability check in target jurisdictions (CN, US, EU at minimum, per DEC-002 target platforms' user base).
- Confirm no conflicting registration in voice-communication software / mobile-app categories.
- Issue go / no-go ruling. A no-go ruling triggers a rename which
invalidates
v1.0.0-rc.1and forces a new RC.
2. Non-affiliation statement — TeamSpeak
- DEC-019 accepted the working wording:
Chanora is independent and is not affiliated with, endorsed by, sponsored by, or officially associated with TeamSpeak.
- Engineering: that exact sentence ships in:
NOTICE(top of file).README.md## License and trademarksection.- The in-app About dialog (English:
aboutNonAffiliationARB key; Chinese Simplified:aboutNonAffiliationinapp_zh.arb, translated by an engineer — translation should be reviewed for legal precision).
- Reviewer action:
- Confirm the English wording is sufficient under target-market consumer-protection and unfair-competition statutes.
- Confirm the Chinese-Simplified translation does not weaken the statement.
- Confirm there is no remaining text anywhere in the product that could imply affiliation (search hints: "TeamSpeak", "official", "endorsed").
3. Trademark usage — "TeamSpeak"
The product documentation and UI strings reference "TeamSpeak" in several places where we describe interoperability (e.g. "TeamSpeak-compatible servers"). This is nominative use.
- Reviewer action:
- Confirm each occurrence of "TeamSpeak" in user-facing strings, documentation, and store metadata is permissible nominative use under target-jurisdiction trademark law.
- Recommend a
™or®symbol convention if required.
4. License posture — Chanora's own code
- DEC-020 accepted dual-license Apache-2.0 OR MIT.
- Engineering: the texts ship as
LICENSE-APACHEandLICENSE-MITat the repository root; the aggregatorLICENSEreferences both. Cargo-level package manifests carrylicense.workspace = truepointing toApache-2.0 OR MITin the workspaceCargo.toml. - Reviewer action:
- Confirm the dual-license declaration is consistent with all contributor agreements (none in place yet — see open items).
- Confirm
LICENSEfile contents satisfy each app store's source- code-availability and inbound-license requirements.
5. Third-party license posture — direct dependencies
NOTICEenumerates the direct dependency list as of v1.0.0-rc.1.- Each direct dependency is permissively licensed
(
MIT,Apache-2.0,MIT OR Apache-2.0,BSD-3-Clause). No GPL / LGPL / AGPL surfaces in the direct set. - Reviewer action:
- Confirm the
NOTICEenumeration matches what the build tooling actually links (the audit must be repeated against acargo about generate --workspaceoutput and a FlutterLicenseRegistrydump as of the release build). - Confirm each direct dependency's attribution obligations are satisfied (Apache-2.0 requires a copy of the license text, the NOTICE entry, and a list of changes in any modified copies).
- Confirm no copyleft transitive dependency creeps in via
tsclientliborcpal. The most likely failure mode is a crypto / DSP subdep with LGPL coverage;cargo denyconfig should refuse those.
- Confirm the
6. tsclientlib posture specifically
The project pins tsclientlib to a specific commit
(04aa249 on https://github.com/ReSpeak/tsclientlib). The crate is
upstream-licensed MIT OR Apache-2.0. It implements the
TeamSpeak 3 protocol from publicly observed behaviour, not from
TeamSpeak proprietary sources.
- Reviewer action:
- Confirm linking against
tsclientlibdoes not by itself create a derivative-work obligation under TeamSpeak's own licenses or EULAs. - Confirm using
tsclientlibto talk to third-party TeamSpeak-protocol servers does not create a trademark or contract-tort exposure.
- Confirm linking against
7. Crypto + secure-storage compliance
chacha20poly1305(Apache-2.0 OR MIT) provides envelope encryption for the identity at rest and bookmark passwords.keyring(Apache-2.0 OR MIT) hits the platform Secret Service / Keychain / Credential Manager for the DEK.- No symmetric or asymmetric primitive other than the above is
introduced by Chanora's own code;
tsclientlibcarries its own protocol-level crypto. - Reviewer action:
- Confirm export-control posture for the resulting binary (cryptography category determination, ECCN, any EAR self- classification needed for store distribution).
- Confirm any privacy-statement updates required by jurisdictions that treat persistent device identifiers as personal data.
8. Data handling — DEC-016 / DEC-017
- DEC-016 No automatic diagnostic upload. The
export_diagnosticsbridge function is invoked only on user action and the redacted output is local-only (Clipboard or share-sheet). - DEC-017 Crash reporting disabled. Repository grep for
sentry|crashlytics|bugsnagreturns zero hits as of v1.0.0-rc.1. - Engineering: diagnostics redaction is enforced at write-time by
the in-bridge
RedactingLogLayer; testschanora_diagnostics::tests::*cover the policy. - Reviewer action:
- Confirm privacy policy text aligns: no telemetry, no automatic upload, no crash reporting in MVP.
- Confirm app-store privacy-label entries are consistent.
9. Store-listing copy
Out of scope for engineering; reviewer drafts and validates per DEC-002 staged platform list:
- Google Play Store (Android arm64-v8a)
- Apple App Store (iOS, MVP gate)
- Microsoft Store / direct (Windows)
- Mac App Store / direct (macOS)
- Linux (direct distribution; no store)
Open engineering work blocking sign-off
These are concrete items that engineering must close before the reviewer's work can complete. They do not require legal input themselves — they are listed here so the reviewer's scope is clear.
- Produce a
cargo about generate --workspaceoutput checked intodocs/security/. - Produce a Flutter
LicenseRegistrydump for the release build checked into the same path. - Wire
cargo deny check licensesinto CI with a deny-list of GPL / LGPL / AGPL / commercial source licenses. - Confirm iOS and macOS build artefacts can ship (DEC-002 staged release allows deferring these; today neither has a live build).
Out-of-scope
The following are not part of DEC-012 and have their own owners and decisions:
- Cryptographic primitive selection (
chacha20poly1305, key sizes, KDF choice) — Security Architect; closed by DEC-013.2. - Codec choice (Opus) — Software Architect.
- TLS / connection security — falls inside
tsclientlib.