aboutsummaryrefslogtreecommitdiffstats
path: root/CLAUDE.md
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-10-05 08:59:06 +0200
committerChristophe Besson <cbesson@gmail.com>2026-10-05 09:20:38 +0200
commitcce8a911553597ada33e275bc9b29fd34121074d (patch)
tree58e2eddfe4f0535e5d177959d8d6ea6da15cc552 /CLAUDE.md
parentbacab81915a9ab640437b7d674bf9e29e701b1f1 (diff)
downloadmeshbay-cce8a911553597ada33e275bc9b29fd34121074d.tar.gz
chore: license MeshBay — LGPL protocol layer, AGPL for the rest
The protocol layer is LGPL-3.0-or-later in every language it exists in, so any client may use it whatever its own licence: meshbay-common, and the files marked with an SPDX line — keyderive.js, crypto.js, playlist-crypto.js, transport*.js; keyring.js, transcripts.js and argon2-wasm.js on the desktop; Kdf.kt, Keyring.kt and Transcripts.kt on Android. Everything else is AGPL-3.0-or-later, which the RPM specs and package.json already declared without a licence file to back them. Two AGPL section 7 permissions: - group applications may be under any licence when they use the interface only through a named surface (static/licenses/APPLICATION-EXCEPTION.txt); the reference application is 0BSD so that copying it brings no AGPL code; - the Android application may be conveyed linked with Google Play services. Third-party code is accounted for: THIRD-PARTY-NOTICES.txt is generated from what a build ships (packaging/third_party_notices.py) for the deb/rpm venv and the frozen Windows node — PyAV's wheel grafts in libx264 and libx265, which its BSD licence does not mention — and the vendored browser libraries get their licence texts and htm-preact.js its provenance. Wheels carry SPDX metadata, RPMs %license, debs a DEP-5 copyright file, every Windows target LICENSE.txt. test_licensing.py holds the line: the LGPL layer imports nothing under the AGPL, the reference application nothing outside the application interface, and every SPDX line is one of the known ones. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'CLAUDE.md')
-rw-r--r--CLAUDE.md56
1 files changed, 55 insertions, 1 deletions
diff --git a/CLAUDE.md b/CLAUDE.md
index d5b66c7..6845b5f 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -26,7 +26,7 @@ readily as what is (§15.2, §15.3); a feature that lands deletes its line there
```
meshbay/
├── packages/
-│ ├── meshbay-common/ # Shared crypto + protocol — python3-meshbay-common RPM
+│ ├── meshbay-common/ # Shared crypto + protocol — python3-meshbay-common RPM (LGPL; rest AGPL)
│ ├── meshbay-hub/ # Hub server (FastAPI + PostgreSQL) — meshbay-hub RPM
│ ├── meshbay-node/ # Node daemon + local UI — meshbay-node RPM
│ ├── meshbay-client/ # Desktop client (Electron)
@@ -132,6 +132,60 @@ Scope: `hub`, `node`, `common`, or omitted for cross-cutting
- **Never log GEK, private keys, or plaintext passwords** — even at DEBUG level
- **meshbay.org is internet-facing** — open port → test → close port + kill processes in same block
+## Licensing
+
+**The protocol layer is LGPL-3.0-or-later, in every language; everything else is
+AGPL-3.0-or-later.** The protocol layer is `meshbay-common` (`COPYING.LESSER` +
+`COPYING` in its package) and, in the clients, the files whose first line is
+`// SPDX-License-Identifier: LGPL-3.0-or-later`: `keyderive.js`, `crypto.js`,
+`playlist-crypto.js`, `transport.js`, `transport-*.js`; `meshbay-client/src/`
+`keyring.js`, `transcripts.js`, `argon2-wasm.js`; Android `keys/Kdf.kt`,
+`Keyring.kt`, `Transcripts.kt`. A file without that line has its package's
+licence: the AGPL (`LICENSE` at the root, copied into `meshbay-hub/` and
+`meshbay-node/` because a wheel's `license-files` cannot reach outside its
+package; into `static/licenses/` with the LGPL and GPL, so that every client
+carries all three).
+
+- **An LGPL file depends only on LGPL files, permissive vendored code or the
+ platform.** One import of an AGPL module and a client using the layer is under
+ the AGPL after all. What a host must supply (`window.MeshBayPlatform`,
+ `window.meshbay`, a `Secrets` store) is reached as an injected interface, never
+ imported. `test_licensing.py` checks the closure.
+- **The same piece has the same licence on every platform.** A port is LGPL when
+ its original is (Keyring.kt ↔ keyring.js ↔ keyderive.js), and stays on the AGPL
+ side when its original is part of a shell (DeviceKey.kt ↔ the device key in
+ `main.js`). A new protocol file is added to the list here, to the README, and
+ to `LGPL_FILES` in the test, with its SPDX line. The Android application adds a §7 permission for
+Google Play services (`meshbay-android/LICENSE-EXCEPTION.txt`).
+
+- **A new dependency must be compatible with GPLv3.** Apache-2.0 already is
+ everywhere (watchdog, asyncpg, msgpack, okhttp), so nothing GPLv2-*only* can
+ come in. GPL dependencies exist and are fine for the AGPL packages (mutagen in
+ the node; PyAV's wheel grafts in libx264/libx265) — **but not for
+ `meshbay-common`**, whose point is to be usable under the LGPL: it imports
+ only permissive packages, and keeps doing so. The same goes for the LGPL files
+ in the clients.
+- **Group applications may be under any licence** —
+ `static/licenses/APPLICATION-EXCEPTION.txt`, an AGPL §7 permission over a
+ named surface: the props and registry fields of §9.2–9.4, the exports of
+ `i18n.js`, `icon.js`, `file-utils.js`, `settings-ui.js`, `folder-tree.js`,
+ `style.css`'s classes and the catalogues' keys. **That list is a commitment to
+ third-party authors**: renaming or removing an export of those modules, or a
+ prop, breaks applications nobody here can see. Adding a module to it is a
+ decision, made in the exception file (the test reads the list from there). The
+ reference application (`helloworld-app*.js`) is 0BSD and imports nothing
+ outside that surface, so copying it never brings AGPL code along.
+- **A proprietary dependency is a licensing change, not a dependency.** Play
+ services needed an exception; another one needs its own, and keeps the
+ Android application out of F-Droid until a flavour without it exists.
+- **A vendored file** gets its entry in `static/vendor/PROVENANCE.md` and its
+ licence text in `static/vendor/LICENSES.txt`, in the same commit.
+- **Notices are generated, not listed.** `packaging/third_party_notices.py`
+ writes `THIRD-PARTY-NOTICES.txt` from the metadata of the environment a build
+ ships (the deb/rpm venv, the frozen Windows node); a hand-kept list would be
+ wrong by the next upgrade. The ffmpeg the Windows build fetches is not a
+ Python package and keeps its own `packaging/win/LICENSE-ffmpeg.txt`.
+
## Design, security findings and protocol — one document
**`docs/MESHBAY_DESIGN.md` is the specification.** Everything that used to be