Files
ekklesiaandClaude Opus 5.5 44d385cd7f
CI / verify (pull_request) Successful in 1m6s
CI / infrastructure-smoke (pull_request) Successful in 27s
CI / migration-smoke (pull_request) Successful in 1m54s
CI / image-build (pull_request) Successful in 29s
CI / deploy-smoke (same-origin) (pull_request) Successful in 43s
CI / deploy-smoke (split) (pull_request) Successful in 1m30s
feat: native linux-x64-glibc module packages and reviewed license supplements (ADR 0049, ADR 0052)
Implements ADR 0049's deferred native target and ADR 0052's reviewed
license supplements. The proof case is a real module using sharp.
packageFormat stays 1, and `any` is unchanged.

Packager (@ekklesia/module-pack):
- --target linux-x64-glibc. Native or platform-specific packages, found by
  the same generic rule that refuses them in `any`, stay outside the bundle.
- Each native package's production closure is walked through its own
  dependencies, installed optionalDependencies that match the target, and
  required peers. It is copied as real files flat under node_modules/<name>,
  with no links, dev dependencies, declarations, source maps, or other
  platforms' packages. Missing or foreign-platform required dependencies,
  version conflicts, links, foreign machines, and Node.js range conflicts
  fail closed.
- runtime.nodeApi, nodeAbi, and libcVersion are read from the binaries by a
  small ELF reader: the addon's node_api_module_get_api_version_v1 and the
  newest GLIBC_ symbol version needed. No shelling out. A native target with
  no addon is refused.
- ADR 0052 supplements: package-provided material stays primary. An exact
  match on name, version, and ekklesia-content-v1 digest (sorted normalized
  paths with each file's size and SHA-256; no metadata) adds labelled
  material after the package's own. Any mismatch, a declared-licence
  conflict, or a malformed or unreviewed supplement file fails. Missing
  material with no supplement still fails.

Supplement for @img/[email protected]:
- 184 components and 143 unique texts, assembled from the exact upstream
  sources sharp-libvips v1.3.3 builds linux-x64 from: 27 C/C++ libraries,
  glib's gvdb, librsvg's Rust crates (reproduced with cargo tree), the Rust
  standard library at the rustc commit recorded in the binary, plus the
  LGPL-3.0, GPL-3.0, and MPL-2.0 texts. Each source is recorded with its
  SHA-256 in PROVENANCE.md.
- It pins digest ekklesia-content-v1:sha256:50647b0b…, which is identical
  from the installed copy and from the registry tarball.
- LGPL/MPL source-availability determinations stay open, as ADR 0052
  states. Nothing claims they are met.

Verifier (Core):
- linux-x64-glibc is accepted only on a host whose platform, arch, glibc
  family and version, and Node-API version (from Node itself) match.
- Every ELF file must be x86-64; every .node must be an ELF object.
- `any` packages now also refuse node_modules/ and ELF files.
- Contract: native metadata must state nodeApi or nodeAbi, and Linux targets
  libcVersion (ADR 0049).

Proof:
- A checked-in AGPL native fixture packs byte-identically from unrelated
  copies (8.86 MB) and verifies with Core's verifier.
- Extracted elsewhere, it runs a sharp resize and PNG round trip in an
  empty-environment process. Every resolution stays in the package, and
  only the package's addon and libvips plus host system libraries load.

Signage is untouched.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-07 20:16:53 -05:00

11 KiB

Provenance: license supplement for @img/[email protected]

This is the human-readable record of how the reviewed material in supplement.json was assembled (ADR 0052). The packager does not read this file. It reads only supplement.json and the texts that file lists, each one named by its SHA-256.

Review of this supplement is project and code review of a build input. It checks that the material matches the sources named below. It is not legal review. It does not establish that every redistribution obligation for this binary is met. In particular, it does not decide whether or how the source-availability obligations of its LGPL and MPL components are met, which remains open.

The package

Field Value
Package @img/sharp-libvips-linux-x64 1.3.3, from the npm registry
npm integrity sha512-4vKmvAst9nrowcqquKFAyZJUDolUaIp8uRiN0mWFguJ1IplC9/pitXtlnnlU4aa/eJw3J7i67V+pwUL+wZGdsA==
Declared licence LGPL-3.0-or-later
Content digest ekklesia-content-v1:sha256:50647b0b1e0b99943f24e4a1580650c0d8fe7744779b0f16271dcd2d59a7678c

The content digest is over the six files the packager copies: README.md, package.json, versions.json, lib/index.js, lib/glib-2.0/include/glibconfig.h, and lib/libvips-cpp.so.8.18.6. It was computed twice and gave the same result both times: once from the copy pnpm installed, and once from the registry tarball extracted directly.

The package ships no licence text and no notices. Its README lists 29 libraries and the licence each is used under, mostly as links. lib/libvips-cpp.so.8.18.6 is one shared object with those libraries built into it.

What was built into the binary

The build is sharp-libvips v1.3.3:

  • source: https://github.com/lovell/sharp-libvips/archive/refs/tags/v1.3.3.tar.gz;
  • sha256: 544ebd8e34be4baf751cc26c8691a46eddbb56183ead1b20ca5b737e93482d86.

The build is defined by build/posix.sh, platforms/linux-x64/Dockerfile, and versions.properties. Its versions.properties matches the package's own versions.json.

  • C and C++ libraries. 27 libraries are built from the upstream archives below, at exactly the URLs build/posix.sh fetches.
    • proxy-libintl is listed in versions.json but is built only for musl and macOS, not for linux-x64 (glibc). It is therefore not a component of this binary.
    • Highway is built, because WITHOUT_HIGHWAY is unset for linux-x64.
  • gvdb. glib is configured with --force-fallback-for=gvdb, so the gvdb subproject shipped inside glib's archive is built in. Its LGPL-2.1-or-later files are taken from that archive.
  • librsvg's Rust crates.
    • What the build does. It edits rsvg/Cargo.toml and librsvg-c/Cargo.toml, dropping the gif and webp image features and the pdf and ps cairo features. It runs cargo update --workspace, then builds librsvg-c with cargo cbuild --locked --release --target x86_64-unknown-linux-gnu, with neither the AVIF nor the pixbuf feature (no dav1d, pixbuf disabled).
    • How it was reproduced. In rust:1-slim (cargo 1.99.0), with the same edits, librsvg 2.62.91's shipped Cargo.lock was updated with cargo update --workspace.
      • That removed only the crates the edits drop (gif, image-webp, color_quant, and their dependencies). It changed no other version, so the compiled set follows from the shipped lockfile.
      • The resulting Cargo.lock has sha256 5ea585dbbcce18a8e74e094a383c4ca2f133102464bd3c9169636a485bf362c2.
    • The crate set. cargo tree -p librsvg-c --features capi --target x86_64-unknown-linux-gnu -e normal lists the crates. Procedural-macro crates are included, which is conservative.
    • Where the files come from. Each crate's licence files are taken from its published .crate file. The crate's sha256 is the checksum from that Cargo.lock.
    • Exceptions.
      • selectors 0.40.0 (MPL-2.0) ships no licence file, so it carries the standard MPL-2.0 text.
      • mutants 0.0.4 (MIT) ships no licence file. It is a no-op attribute macro that runs only at compile time and contributes no code to the binary, so it is not a component.
  • The Rust standard library.
    • The binary records /rustc/787af2b8c80638c51a4fc8e44f84e6891f243ec7/… paths. That is a nightly rustc commit, merged on 2026-08-25, two days before the package was built.
    • Its std lockfile pins the five crate versions that are visible in the binary's strings: addr2line 0.27.1, gimli 0.34.0, hashbrown 0.17.1, miniz_oxide 0.9.1, and rustc-demangle 0.1.28.
    • Where the files come from. COPYRIGHT, LICENSE-APACHE, LICENSE-MIT, and library/compiler-builtins/LICENSE.txt are taken from that commit.
    • The crates covered. These are std's crates.io dependencies for x86_64-unknown-linux-gnu, read from library/std/Cargo.toml's target sections at that commit:
      • addr2line, adler2, cfg-if, foldhash, gimli, hashbrown, libc, memchr, miniz_oxide, object, and rustc-demangle;
      • each with its .crate file's licence files.
    • Not covered, because it is not linked into this target:
      • build-only: cc, shlex, find-msvc-tools;
      • test-only: rand, rand_core, rand_xorshift;
      • other platforms: dlmalloc, fortanix-sgx-abi, hermit-abi, moto-rt, r-efi, r-efi-alloc, unwinding, vex-sdk, wasip1, wasip2, wasip3, wit-bindgen.
  • Not redistributed here. The binary dynamically links the host's libstdc++.so.6, libgcc_s.so.1, and glibc libraries. They come from the system that loads the package, so they are not part of this package.

Standard texts added

Text Source sha256
GNU LGPL 3.0, for the package's declared LGPL-3.0-or-later https://www.gnu.org/licenses/lgpl-3.0.txt e3a994d82e644b03a792a930f574002658412f62407f5fee083f2555c5f23118
GNU GPL 3.0, which the LGPL 3.0 incorporates https://www.gnu.org/licenses/gpl-3.0.txt 3972dc9744f6499f0f9b2dbf76696f2ae7ad8af9b23dde66d6af86c9dfb36986
MPL 2.0 https://www.mozilla.org/MPL/2.0/ (text file index.f75d2927d3c1.txt) 3f3d9e0024b1921b067d6f7f88deb4a60cbe7a78e76c64e3f1d7fc3b779b9d04

The MPL 2.0 text is carried for two components:

  • cairo. cairo ships the LGPL-2.1 and MPL-1.1 texts. sharp-libvips states that cairo is used under MPL 2.0.
  • selectors, which ships no licence file.

Licence names in supplement.json are as sharp-libvips's THIRD-PARTY-NOTICES.md states them for each library, and as each crate's Cargo.toml declares it. They are recorded, not determined.

Upstream archives (C and C++ libraries)

Each archive was downloaded from exactly the URL build/posix.sh uses for the versions in versions.properties:

Archive sha256
cairo-1.18.4.tar.xz 445ed8208a6e4823de1226a74ca319d3600e83f6369f99b14265006599c32ccb
cgif-0.5.3.tar.gz dcc7731e974ee77db75df26c99aca4d95f11ca2d267d870d42bce1e0d1e1e75f
expat-2.8.3.tar.xz f6256df90c906773d344da084402b7d3e4f22ed41b1a59c989098a83d3ea0c85
fontconfig-2.18.3.tar.gz 9ae01e1d53acdef56010c5451cd34aa41d325b2faccd8606448d8fa01b2496b3
freetype-2.14.3.tar.gz dc49de6b01a266eef4876a4dd34d9842c475d3e28ff2eff63bd2fb760ab56261
fribidi-1.0.16.tar.xz 1b1cde5b235d40479e91be2f0e88a309e3214c8ab470ec8a2744d82a5a9ea05c
glib-2.89.4.tar.xz 1cdbb799f558832e6f14b8337b5fd599c6918ab144977b55e05e00a5e2e84a2c
harfbuzz-14.3.1.tar.gz 05e602daf0846d7497d842807766ea32ca270f3e2c9284ce03811a2a1ed669c9
highway-1.4.0.tar.gz e72241ac9524bb653ae52ced768b508045d4438726a303f10181a38f764a453c
lcms2-2.19.1.tar.gz bfc54f7bab59fbc921012014a8032e4cba4abd46db47d46b76416a8c0b2815c8
libaom-3.15.0.tar.gz ea08c38ecc078bc85bb1b691020e52b06250f1a81fe7ca5b624629225081af96
libarchive-3.8.9.tar.xz 888c934f9d95648ecb9163dc8e23ab80a476ecb81a8f1154704a227b5b676dde
libexif-0.6.26.tar.xz 4a055ed6575e61ca46c3172be3c753cc16c9becd0f99ec71d58dd0e471476c0c
libffi-3.8.0.tar.gz 7da3e2d9a171eb0a038f592ecad3ff2bb2550f3496d87b3b29ad0cf4430c0db4
libheif-1.23.2.tar.gz 8bd5d41d19dc84536d118b04774709f244df6104ef66d623dad5fa4650143405
libimagequant-2.4.1.tar.gz 47d2a84b7b1052975c9d50a3d4e3cacbf57b43d84a4c3131210848ead9964dfb
libpng-1.6.58.tar.gz a9d4df463d36a6e5f9c29bd6f4967312d17e996c1854f3511f833924eb1993cf
librsvg-2.62.91.tar.xz 6caeae129d40dd88f8ec49436fd89bfe4ada716a125187a7fa0def8fcaa0b250
libtiff-v4.7.2.tar.gz 62b15f44c10106065211efa22a2dc77937bd97ee1f6e3afd2c9659010de112eb
libultrahdr-2.0.2.tar.gz aa8d193bb887c348c419780511dd03b374f4e07af8812b6d3f80c8537cf1ef2c
libwebp-1.6.0.tar.gz e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564
libxml2-2.15.3.tar.xz 78262a6e7ac170d6528ebfe2efccdf220191a5af6a6cd61ea4a9a9a5042c7a07
mozjpeg-0826579.tar.gz b680167bd5d9afebdd576a12f8c49d2c9066a3b92ef96a2b2c5f7829b8600fe5
pango-1.58.2.tar.xz 342385b6ca3b7c73455d7c80a13b7dbe4489e00bc3bd4c5bd6ed4dce421e374a
pixman-0.46.4.tar.gz d09c44ebc3bd5bee7021c79f922fe8fb2fb57f7320f55e97ff9914d2346a591c
vips-8.18.6.tar.xz 3c41e1d5458081bfa4a5bc54e116c46259c75c6760a18027764555632b9dda3e
zlib-ng-2.3.3.tar.gz f9c65aa9c852eb8255b636fd9f07ce1c406f061ec19a2e7d508b318ca0c907d1

Rust standard library sources

File at rustc 787af2b8c80638c51a4fc8e44f84e6891f243ec7 sha256
COPYRIGHT 172020dbfd5b53a226dfde77616190a48dcff519b0bc0e6deb91a8450782c4af
LICENSE-APACHE 62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a
LICENSE-MIT b71bd43a069ca0641a9ecfe585ca7b3c53b5cc1608f8b68321168698e28b5ea1
library/compiler-builtins/LICENSE.txt ab6eec6caf0fa5775e411c7a8bc6a45c4ef2956b0980b157ab74fc5cd62a928b
library/Cargo.lock fc922f114685e5cbdb3dce572cb7e3b7023a45b57e3a436e23abf35d240c5d9f

Each crate's .crate source and sha256 are recorded in that crate's source in supplement.json.

Open questions this supplement does not answer

  • Source availability. The LGPL components (libvips, glib, gvdb, pango, fribidi, libexif, libheif, librsvg, cairo under the LGPL alternative) and the MPL components (cairo and the MPL Rust crates) carry source-availability obligations. Whether and how those are met when this binary is redistributed has not been determined. Recording the upstream source locations above does not determine it.
  • Upstream accuracy. The licence each library is used under is sharp-libvips's statement. For example, it states that the LGPL libraries are used under LGPLv3 through the "any later version" clause, and that cairo is used under MPL 2.0. These statements are recorded, not verified.