# Third-party notices This project is MIT licensed. The published container image includes the following third-party components. Two artefacts are published from this repository and they carry different obligations. The **container image** contains only the binaries the build produces, and the licence gate below asserts that no GPL-only object is among them. The **upstream source snapshot** attached to `upstream-*` releases is a verbatim redistribution of philippe44's pinned tree — every submodule, in source form, exactly as fetched. Because it is complete rather than curated, the prebuilt `libmad.a` and `libfaad.a` archives inside it ship alongside their own `mad/` and `faad2/` sources, which is what GPL-2.0 §3(a) asks for. Pruning the snapshot down to "just the parts we build" would break that, so it is deliberately not pruned beyond the prebuilt executables described in `scripts/make-upstream-snapshot.sh`. ## AirConnect and its libraries [philippe44/AirConnect](https://github.com/philippe44/AirConnect) — **MIT**, © Philippe. Pinned at the SHAs in `upstream.lock` and patched at build time; the patches are in `patches/` and are themselves MIT. Its submodules, all by the same author unless noted: | Component | Licence | Role | |---|---|---| | `crosstools` | MIT | Logging, sockets, threading, the OpenSSL dynamic loader | | `libraop` | MIT | RAOP/AirPlay server, ALAC decode | | `libmdns` | MIT / BSD | mDNS responder and browser | | `libpupnp` | BSD-3-Clause | libupnp (Intel/pupnp) | | `libcodecs` | see below | Encoder collection | | `dmap-parser` | MIT | DAAP/DMAP metadata | | `nanopb` ([upstream](https://github.com/nanopb/nanopb)) | Zlib | Protobuf for the Cast protocol | | `libjansson` | MIT | JSON for the Cast protocol | ## Codecs `libcodecs` bundles several encoders and decoders under different licences. The bridges use only the **encoders** (plus ALAC decoding, which lives in `libraop`'s own `alac.c`). | Codec | Licence | Linked in? | |---|---|---| | libFLAC | BSD-3-Clause | yes — default codec | | shine (MP3 encoder) | LGPL-2.1 | yes — `AIRCONNECT_CODEC=mp3` | | FAAC (AAC encoder) | FAAC licence, with patent notes | yes — `AIRCONNECT_CODEC=aac` | | soxr | LGPL-2.1 | linked, resampling | | ALAC | Apache-2.0 | decode path | | **libmad** (MP3 *decoder*) | **GPL-2.0** | **no** | | **FAAD2** (AAC *decoder*) | **GPL-2.0** | **no** | | Ogg / Vorbis / Opus | BSD-3-Clause | not referenced | ### Why the GPL entries matter, and how we keep them out `libcodecs.a` is a *thin archive*: it references its sibling archives by path, including `libmad.a` and `libfaad.a`, both GPL-2.0. A static linker only pulls in archive members that resolve an undefined symbol, and AirConnect never decodes MP3 or AAC — so no member of either archive should ever be linked. "Should" is not sufficient for an image we publish, because linking a single GPL-2.0 object would place the whole binary under the GPL. So `scripts/build-bridges.sh` asserts it after every build: ```sh "${TRIPLE}-nm" -C "$OUT/$app" | grep -qiE ' (mad_(decoder|frame|stream|synth)_|faacDecode|NeAACDec)' \ && exit 1 ``` The build fails if either decoder is ever pulled in. This runs per architecture, in CI as well as locally. LGPL components (shine, soxr) are statically linked. The LGPL permits this provided recipients can relink; the pinned sources and the exact build steps are in `upstream.lock`, `patches/` and `scripts/build-bridges.sh`, and the object archives are published by their upstream projects. ## Runtime | Component | Licence | Notes | |---|---|---| | OpenSSL 3 (`libssl3`) | Apache-2.0 | **Not linked.** `cross_ssl.c` defines forwarding symbols that `dlopen()` libssl at runtime | | Debian bookworm-slim | various | Base image | ## Manager The Rust manager's dependency tree is Apache-2.0/MIT throughout (tokio, axum, serde, rust-embed, reqwest with rustls, quick-xml, tracing, time, anyhow, mime_guess). `cargo tree` in `manager/` lists the exact set for a given build. The web interface has no runtime dependencies — no framework, no bundler, no CDN. ## Reporting If you believe a component is misattributed here, please open an issue. Bugs in upstream AirConnect are reported to [philippe44/AirConnect](https://github.com/philippe44/AirConnect/issues) where they apply there rather than only here.