diff --git a/AGENTS.md b/AGENTS.md index b4b29482e..48aeb27f7 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -239,9 +239,17 @@ Key files: `--runtime-probe` must all succeed before frame-copy can relax the renderer sandbox. Any failure reports a stable reason and falls back to native-view without crashing; an environment flag never bypasses this gate. +- Snap uses an exact private `shared-memory` plug. The probe and playback + helper share one sanitized loader environment: ambient preload/library + paths are removed, the validated private closure wins, and trusted Snap GL + roots precede generic in-snap library roots. - Bundled Linux releases must publish the exact source archives/git records, checksums, licenses, flags, patches, build scripts, and the pinned hwdata - `pnp.ids` input. Canonical maintenance docs: + `pnp.ids` input. Each bundled package carries + `embedded-mpv-notices.json`, `THIRD_PARTY_NOTICES.txt`, and the exact + `licenses/**` files. CI may cache immutable source inputs, but regenerates + notices and `linux-frame-copy-runtime-sources.tar.xz` for the current + checkout on every run. Canonical maintenance docs: `docs/architecture/embedded-mpv-native.md` and `tools/embedded-mpv/README.md`. diff --git a/CLAUDE.md b/CLAUDE.md index bbcd8f0b8..4368b7267 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -635,8 +635,16 @@ engine` (restart required) or marker-only. Stored or explicit opt-ins cannot bypass the fail-closed packaged manifest/file/hash gate and bounded `--runtime-probe`; any failure keeps the sandbox enabled, records a stable reason, and falls back to - native-view without crashing. On Windows, package validation requires the - exact MPV DLL named by the helper's PE import table beside the executable. + native-view without crashing. Snap uses an exact private `shared-memory` + plug; probe and playback share a sanitized loader environment in which the + validated private closure and trusted Snap GL roots have explicit + precedence. Bundled Linux packages carry hash-validated + `embedded-mpv-notices.json`, `THIRD_PARTY_NOTICES.txt`, and `licenses/**`. + CI caches the staged runtime plus immutable source inputs, never finished + notices or the compliance tarball; it regenerates those notices and the + deterministic `linux-frame-copy-runtime-sources.tar.xz` for the current + checkout. On Windows, package validation requires the exact MPV DLL named by + the helper's PE import table beside the executable. Backend adapter: `apps/electron-backend/src/app/services/embedded-mpv-frame-copy.adapter.ts`; shared-controls adapter: diff --git a/docs/architecture/embedded-mpv-native.md b/docs/architecture/embedded-mpv-native.md index cbe17dc39..d409791bb 100644 --- a/docs/architecture/embedded-mpv-native.md +++ b/docs/architecture/embedded-mpv-native.md @@ -92,8 +92,11 @@ Every x64 layout contains the addon, frame reader, helper, and a normalized `embedded-mpv-runtime.json`. The Electron executable, Electron libraries, `embedded_mpv.node`, and the frame reader must not link libmpv; only the helper may do so. AppImage, Snap, and Flatpak retain dynamically linked, replaceable -runtime libraries and ship the corresponding source/build metadata. DEB, RPM, -and Pacman intentionally contain no private `native/lib` directory. +runtime libraries and ship the corresponding source/build metadata. Their +native directory also contains hash-validated `embedded-mpv-notices.json`, +`THIRD_PARTY_NOTICES.txt`, and `licenses//**`. DEB, RPM, Pacman, and +marker-only packages intentionally contain neither a private `native/lib` +directory nor the bundled-runtime legal payload. ARM Linux packages remain marker-only. They never borrow x64 native artifacts, even when build environment variables claim a matching staged architecture. @@ -664,12 +667,17 @@ library to an `$ORIGIN` RUNPATH, and enforces the portable ABI ceilings complete dependency closure, and absence of build-prefix paths. CI may restore exact-keyed caches for staged -`vendor/embedded-mpv/-/` runtimes. The cache includes only -generated headers, libraries, and manifests; it never contains -`embedded_mpv.node`. Runtime cache entries are saved only from trusted -repository refs. The Linux cache key covers the builder/stager and pinned -source inputs, and its accompanying source-compliance artifact remains a -release requirement, not a cache side effect. +`vendor/embedded-mpv/-/` runtimes. The Linux cache contains +only generated headers, libraries, the runtime manifest, and immutable source +inputs: exact archives, a clean recursive libplacebo checkout, and collected +license inputs. It never contains `embedded_mpv.node`, generated notices, or +the finished source-compliance archive. Runtime cache entries are saved only +from trusted repository refs. The Linux cache key covers the builder/stager, +notice generator, pinned sources, and toolchain. On every run, including a +cache hit, CI validates the cached hashes and clean checkout, regenerates the +notices for the current runtime manifest, and creates the deterministic +`linux-frame-copy-runtime-sources.tar.xz` for the current repository revision +and binary diff. Windows CI uses a checksum-pinned `win32-x64` runtime archive configured through `IPTVNATOR_WINDOWS_EMBEDDED_MPV_RUNTIME_URL` and @@ -692,6 +700,14 @@ submodules, licenses, exact flags, build-host/toolchain data, runtime hashes, and the dynamic closure. FFmpeg/mpv remain LGPL-compatible and dynamically linked; codecs outside that build configuration are not implied. +`generate-linux-runtime-notices.cjs` collects the exact upstream license files +for every pinned package and all recursive libplacebo submodules. Generation +is fail-closed for a missing, undeclared, symlinked, size-mismatched, or +hash-mismatched file. Portable and Flatpak package hooks copy only the +validated notice manifest, aggregate notice, and per-package license tree; +package-layout verification revalidates that legal payload against the +embedded source-runtime manifest. + The Electron backend build consumes the staged runtime/build inputs. On Linux it links the helper against the verified staged `libmpv.so.2`, never against a generic host `-lmpv`, then verifies the helper's `DT_NEEDED` and @@ -749,9 +765,13 @@ packaging passes with `IPTVNATOR_EMBEDDED_MPV_PLATFORM=linux`, `IPTVNATOR_REQUIRE_EMBEDDED_MPV=1`, and one exact `IPTVNATOR_LINUX_FRAME_COPY_PROFILE`. Each produced artifact is extracted and verified, and the x64 helper probe runs in the intended runtime environment. -The source-compliance bundle is uploaded with the binary artifacts. ARM -artifacts are independently verified as marker-only and never run the x64 -helper. +Bundled package layouts must include the generated notices and exact license +tree. The separately uploaded +`linux-frame-copy-runtime-sources.tar.xz` contains the exact archive set, +clean recursive libplacebo checkout, notice/license inputs, runtime metadata, +current revision/diff, and build tooling. Its tar metadata is normalized for +deterministic output. ARM artifacts are independently verified as marker-only +and never run the x64 helper. During temporary artifact tests, CI may also set `IPTVNATOR_REQUIRE_EMBEDDED_MPV=1` for PR and `master` push jobs where a runtime is known to exist. After the artifacts are manually validated, remove temporary conditions so ordinary development builds leave `IPTVNATOR_REQUIRE_EMBEDDED_MPV` unset or `0`. This keeps the native feature in-tree without making every non-release build depend on runtime artifacts. diff --git a/tools/embedded-mpv/README.md b/tools/embedded-mpv/README.md index 81feac02d..2fd4ff8c2 100644 --- a/tools/embedded-mpv/README.md +++ b/tools/embedded-mpv/README.md @@ -49,12 +49,17 @@ vendor/embedded-mpv/ lib/libmpv.so lib/libmpv.so.2 lib/ + notices/embedded-mpv-notices.json + notices/THIRD_PARTY_NOTICES.txt + notices/licenses// runtime-manifest.json ``` These directories are generated release inputs and are ignored by git. `runtime-manifest.json` is the profile-neutral source/build manifest. Packaging writes a normalized `embedded-mpv-runtime.json` beside the native artifacts. +Bundled Linux profiles flatten the three notice entries from `notices/` into +that same native directory; system and marker-only profiles remove them. ## Building And Staging @@ -150,9 +155,12 @@ with `readelf` that: The package hook copies native artifacts into `app.asar.unpacked/electron-backend/native/`, selects the system or bundled -layout, restores exact file modes, and writes the packaged manifest. Package -validation also scans the Electron executable and all shipped Electron -libraries for a direct libmpv dependency. +layout, restores exact file modes, writes the packaged manifest, and validates +the bundled legal payload. AppImage, Snap, and Flatpak receive +`embedded-mpv-notices.json`, `THIRD_PARTY_NOTICES.txt`, and +`licenses//**`; DEB, RPM, Pacman, and marker-only packages must not +retain them. Package validation also scans the Electron executable and all +shipped Electron libraries for a direct libmpv dependency. At startup, Linux x64 frame-copy is advertised only after the main process validates that manifest/files and successfully executes: @@ -178,10 +186,20 @@ extracted for manifest, mode, package-metadata, ELF-isolation, and helper-probe checks. System formats are probed after their declared dependency is installed; Snap and Flatpak also require a sandboxed probe where the runner supports it. -The binary release must include a source-compliance bundle containing the exact -downloaded archives (including hwdata), the recorded libplacebo checkout or git -bundle and submodules, builder/stager/manifest code, generated runtime manifest, -and local patches. A cache hit does not remove this obligation. +The Linux runtime cache contains only staged headers/libraries/manifest plus +immutable source inputs: exact downloaded archives (including hwdata), a clean +recursive libplacebo checkout, and collected license files. It never caches +finished notices or the compliance tarball. After either a build or cache hit, +CI revalidates those inputs, regenerates `vendor/embedded-mpv/linux-x64/notices` +for the current runtime manifest, and creates +`linux-frame-copy-runtime-sources.tar.xz` for the current repository +revision/diff. + +That deterministic source-compliance archive contains the exact unique archive +hash set, clean libplacebo checkout and recursive submodules, license inputs, +generated notices, runtime/source index metadata, and the builder, stager, +manifest, and notice-generator code. The notice generator rejects missing, +undeclared, symlinked, size-mismatched, or hash-mismatched license files. Windows CI stages a checksum-pinned x64 LGPL archive. The DLL basename encoded in its import library is preserved and must be present beside diff --git a/vendor/embedded-mpv/README.md b/vendor/embedded-mpv/README.md index 861ffc243..eda5a014a 100644 --- a/vendor/embedded-mpv/README.md +++ b/vendor/embedded-mpv/README.md @@ -14,15 +14,20 @@ Each generated folder must contain `include/mpv/client.h` and `runtime-manifest.json`. Platform runtime/build inputs live under `lib/` or `bin/`. In particular, `linux-x64/lib/` contains the pinned, dynamically linked LGPL-compatible libmpv closure used to link the out-of-process frame-copy -helper. The binary runtime directories are ignored by git; generate, stage, or -restore them before building the Electron backend. +helper. `linux-x64/notices/` contains the generated +`embedded-mpv-notices.json`, `THIRD_PARTY_NOTICES.txt`, and exact +`licenses//**` tree. The generated runtime directories are ignored by +git; generate, stage, or restore them before building the Electron backend. Linux package profiles consume that one staged x64 source runtime differently: - DEB/RPM/Pacman remove the private closure and declare the system libmpv dependency. - AppImage/Snap/Flatpak retain the manifest-declared closure under - `app.asar.unpacked/electron-backend/native/lib/`. + `app.asar.unpacked/electron-backend/native/lib/` and flatten the validated + notice manifest, aggregate notice, and `licenses/**` tree beside it. +- DEB/RPM/Pacman and marker-only packages do not retain bundled-runtime + notices or license files. - Non-x64 Linux packages retain no native artifacts and ship only the unavailable marker.