Files
chanora/docs/governance/legal-review-readiness.md
T
EdisonJwa b932dc1405 feat(legal): land cargo-about + cargo-deny + Flutter license inventory
Closes engineering deliverables 1–3 from the open-work table in
`docs/governance/legal-review-readiness.md` so the DEC-012 legal
review can actually run. With this commit, the only remaining
engineering item blocking sign-off is signed Windows / macOS / iOS
build artefacts, deferrable per the DEC-002 staged release plan.

Tooling
-------

* `about.toml` + `about.hbs` + `about-md.hbs` configure cargo-about
  with the DEC-020 license posture and the five-target matrix
  (Linux, Android, Windows, macOS, iOS). One per-crate clarification
  for `allo-isolate` (`flutter_rust_bridge` transitive that ships
  Apache-2.0 via `license-file` rather than an SPDX `license`
  field). `cargo about generate` runs with zero warnings.
* `deny.toml` mirrors the cargo-about allow-list and adds minimal
  bans / sources / advisories config. `cargo deny check` reports
  `advisories ok, bans ok, licenses ok, sources ok` for the
  workspace; multiple-versions of `windows_x86_64_msvc` produce
  advisory `warn` (no fail) because three windows-targets versions
  reach the graph via `jni`, `cpal`, and `keyring` respectively.
* `tools/dump_flutter_licenses.sh` + `tools/dump_flutter_licenses.dart`
  walk `apps/chanora_flutter/pubspec.lock`, resolve each dependency
  to its local pub-cache directory, read the LICENSE file, and emit
  `docs/security/flutter-license-inventory.md`. SDK-sourced
  packages (`flutter`, `flutter_localizations`, `flutter_test`,
  `flutter_web_plugins`, `sky_engine`) resolve to the Flutter
  framework BSD-3-Clause LICENSE under `$FLUTTER_ROOT` (or
  `$HOME/sdks/flutter`).

Artefacts
---------

* `docs/security/license-inventory.md` — 364 transitive Rust
  crates with full license texts. Apache-2.0 (276), MIT (55),
  Unicode-3.0 (19), BSD-3-Clause (7), ISC (7). Zero copyleft.
* `docs/security/license-inventory.html` — same data rendered as
  styled HTML for reviewer convenience.
* `docs/security/flutter-license-inventory.md` — 94 Dart / Flutter
  packages with their LICENSE texts. Zero packages without a
  resolvable LICENSE in this RC.

CI
--

* New `supply-chain` job runs `cargo deny check --workspace
  --all-features` via `EmbarkStudios/cargo-deny-action@v2`. Fails
  the build on any GPL / LGPL / AGPL / commercial-source license
  surfacing transitively.
* New `license-inventory` job installs `cargo-about --features cli`
  and regenerates `docs/security/license-inventory.md`; diffs
  against the committed copy and fails on drift. Forces
  contributors who touch the Cargo.lock to refresh the inventory.
* New `flutter-license-inventory` job runs
  `tools/dump_flutter_licenses.sh` against the just-resolved pub
  cache; same diff-on-drift semantics.

Governance
----------

* `docs/governance/legal-review-readiness.md` §5 cross-links the
  three new artefacts in a "Reviewer artefacts" subsection.
* The open-work table at the bottom of the doc is rewritten as a
  status grid: items 1–3 now read **Done**; item 4 (signed iOS /
  macOS builds) remains the only open engineering blocker, with a
  pointer back to `staged-release-plan.md`.

Verification
------------

* `CHANORA_DISABLE_KEYRING=1 cargo test --workspace`: all 49 unit
  + integration tests green (unchanged from v1.0.0-rc.1).
* `cargo deny check`: advisories ok, bans ok, licenses ok,
  sources ok.
* `cargo about generate --output-file …`: zero warnings.
* `tools/dump_flutter_licenses.sh`: 94 packages, 0 without LICENSE.
* `flutter analyze`: clean.

No code changes touch the runtime; this is governance-tooling only.
2026-05-15 14:00:16 +08:00

201 lines
9.0 KiB
Markdown

# 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 artefacts** checked into the repository:
- `docs/security/license-inventory.md` and
`docs/security/license-inventory.html` — full transitive Rust
inventory generated by `cargo about generate` from
`about.toml`. Covers 364 crates across the workspace.
- `docs/security/flutter-license-inventory.md` — Flutter / Dart
inventory generated by `tools/dump_flutter_licenses.sh`.
Covers 94 packages including the Flutter SDK BSD-3-Clause
text.
- `deny.toml``cargo deny` configuration enforcing the
DEC-020 license posture as a CI guardrail. The `supply-chain`
job in `.github/workflows/ci.yml` runs `cargo deny check` on
every push and PR.
* **Reviewer action**:
- Confirm the `NOTICE` enumeration matches what the build tooling
actually links by spot-checking against the inventories above.
- 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.
| # | Item | Status |
|---|------|--------|
| 1 | `cargo about generate --workspace` output checked into `docs/security/license-inventory.{md,html}` | **Done** (v1.0.0-rc.2 candidate) — generated from `about.toml`. 364 transitive crates enumerated; CI fails on staleness. |
| 2 | Flutter `LicenseRegistry` dump checked into `docs/security/flutter-license-inventory.md` | **Done** (v1.0.0-rc.2 candidate) — generated by `tools/dump_flutter_licenses.sh`; 94 packages enumerated; CI fails on staleness. |
| 3 | `cargo deny check licenses` (with allow-list mirroring DEC-020) | **Done** (v1.0.0-rc.2 candidate) — config at `deny.toml`, CI job `supply-chain` runs `cargo deny check` on every push. |
| 4 | Live iOS and macOS build artefacts | **Open** — DEC-002 staged release allows deferring; today neither has a live build. See `staged-release-plan.md`. |
## 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`.