Files
chanora/docs/governance/legal-review-readiness.md
T
EdisonJwa 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.
2026-05-15 02:24:42 +08:00

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 the appTitle localisation 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.1 and 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 trademark section.
    • The in-app About dialog (English: aboutNonAffiliation ARB key; Chinese Simplified: aboutNonAffiliation in app_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-APACHE and LICENSE-MIT at the repository root; the aggregator LICENSE references both. Cargo-level package manifests carry license.workspace = true pointing to Apache-2.0 OR MIT in the workspace Cargo.toml.
  • Reviewer action:
    • Confirm the dual-license declaration is consistent with all contributor agreements (none in place yet — see open items).
    • Confirm LICENSE file contents satisfy each app store's source- code-availability and inbound-license requirements.

5. Third-party license posture — direct dependencies

  • NOTICE enumerates 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 NOTICE enumeration matches what the build tooling actually links (the audit must be repeated against a cargo about generate --workspace output and a Flutter LicenseRegistry dump 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 tsclientlib or cpal. The most likely failure mode is a crypto / DSP subdep with LGPL coverage; cargo deny config should refuse those.

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 tsclientlib does not by itself create a derivative-work obligation under TeamSpeak's own licenses or EULAs.
    • Confirm using tsclientlib to talk to third-party TeamSpeak-protocol servers does not create a trademark or contract-tort exposure.

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; tsclientlib carries 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_diagnostics bridge 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|bugsnag returns zero hits as of v1.0.0-rc.1.
  • Engineering: diagnostics redaction is enforced at write-time by the in-bridge RedactingLogLayer; tests chanora_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.

  1. Produce a cargo about generate --workspace output checked into docs/security/.
  2. Produce a Flutter LicenseRegistry dump for the release build checked into the same path.
  3. Wire cargo deny check licenses into CI with a deny-list of GPL / LGPL / AGPL / commercial source licenses.
  4. 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.