Implements ADR 0049's deferred native target (linux-x64-glibc) and ADR 0052's reviewed license supplements, proven with a real module that uses sharp. packageFormat stays 1, any packaging is unchanged, and Signage is untouched.
Packager (@ekklesia/module-pack)
--target linux-x64-glibc. Native or platform-specific packages stay outside the bundle. They are found by the same generic rule that refuses them in any, with no names hard-coded.
Closure. Each native package's runtime closure is walked through its own dependencies, installed optionalDependencies matching the target's os/cpu/libc, and required peers. It is copied as real files flat under node_modules/<name>, with:
no links;
no dev dependencies;
no .d.ts or source maps;
no other platforms' packages.
Fails closed on missing or foreign-platform required dependencies, version conflicts, links inside a package, a foreign ELF machine, a native package whose Node.js engines range doesn't cover the package's, and a native target with no addon.
Runtime metadata comes from the binaries, via a small ELF reader (no shelling out):
nodeApi comes from the addon's own node_api_module_get_api_version_v1;
nodeAbi is used for ABI-specific addons;
libcVersion is the newest GLIBC_ symbol version needed.
Supplements (ADR 0052).
Package-provided material stays primary.
An exact match on name + version + ekklesia-content-v1 digest adds labelled material after it.
The digest covers sorted, normalized relative paths plus each file's size and SHA-256, and nothing else. It is documented in src/supplements.ts.
Fails closed: a mismatch, a declared-licence conflict, a tampered or unlisted supplement file, or missing material with no supplement.
Verifier (Core)
Host check:linux-x64-glibc is accepted only when the host's platform, arch, glibc family and version (process.reportglibcVersionRuntime) and Node-API version (process.versions.napi) are compatible. Anything unprovable fails closed.
ELF and addon check: every ELF file must be x86-64, and 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 must state libcVersion (ADR 0049).
Contents: 184 components and 143 unique texts, assembled reproducibly from the exact upstream sources sharp-libvips v1.3.3 builds linux-x64 from:
27 C/C++ libraries and glib's gvdb;
librsvg's Rust crates, reproduced with cargo tree after the build's own edits;
the Rust standard library at the rustc commit recorded in the binary;
the LGPL-3.0, GPL-3.0 and MPL-2.0 texts.
PROVENANCE.md records every source with its SHA-256, plus the method and exclusions.
Pin:ekklesia-content-v1:sha256:50647b0b…, identical whether computed from the installed copy or the registry tarball.
Line endings:.gitattributes keeps supplement texts byte-exact (-text), because each is named by its SHA-256.
Open: LGPL/MPL source-availability determinations stay open, as ADR 0052 states. The docs say a package carrying this supplement is not yet treated as publicly distributable.
Proof
A checked-in AGPL-3.0-or-later fixture module (tests/fixtures/native-module) packs to native-proof-0.1.0-linux-x64-glibc.tar.gz: 8,863,205 bytes, 125 files plus metadata, 21.6 MB unpacked.
Determinism: two fresh clones at unrelated absolute paths produce byte-identical archives (sha256 bbcfd086…), with no host or checkout path inside.
Runtime: Core's verifier accepts the package. Extracted elsewhere, it runs a sharp resize and a PNG round trip in an empty-environment process.
Every module resolution stays inside the package.
Only the package's addon and libvips, plus the host's glibc and libstdc++, are loaded.
Verification
module-pack: 78 tests, including the new native-target, native-closure and supplements suites.
Core package verification: 64.
pnpm verify: passes.
The deploy smoke was not run. The image installs production dependencies only, so sharp, a dev dependency, doesn't enter it, and the smoke's any-target template lifecycle is unaffected.
ADR 0052 remains Proposed, so you can decide whether this implementation accepts it.
Implements **ADR 0049's deferred native target** (`linux-x64-glibc`) and **ADR 0052's reviewed license supplements**, proven with a real module that uses `sharp`. `packageFormat` stays 1, `any` packaging is unchanged, and Signage is untouched.
## Packager (`@ekklesia/module-pack`)
- **`--target linux-x64-glibc`.** Native or platform-specific packages stay outside the bundle. They are found by the same generic rule that refuses them in `any`, with no names hard-coded.
- **Closure.** Each native package's runtime closure is walked through its own `dependencies`, installed `optionalDependencies` matching the target's `os`/`cpu`/`libc`, and required peers. It is copied as **real files flat under `node_modules/<name>`**, with:
- no links;
- no dev dependencies;
- no `.d.ts` or source maps;
- no other platforms' packages.
- **Fails closed** on missing or foreign-platform required dependencies, version conflicts, links inside a package, a foreign ELF machine, a native package whose Node.js `engines` range doesn't cover the package's, and a native target with no addon.
- **Runtime metadata comes from the binaries,** via a small ELF reader (no shelling out):
- `nodeApi` comes from the addon's own `node_api_module_get_api_version_v1`;
- `nodeAbi` is used for ABI-specific addons;
- `libcVersion` is the newest `GLIBC_` symbol version needed.
- **Supplements (ADR 0052).**
- Package-provided material stays primary.
- An exact match on **name + version + `ekklesia-content-v1` digest** adds labelled material after it.
- The digest covers sorted, normalized relative paths plus each file's size and SHA-256, and nothing else. It is documented in `src/supplements.ts`.
- **Fails closed:** a mismatch, a declared-licence conflict, a tampered or unlisted supplement file, or missing material with no supplement.
## Verifier (Core)
- **Host check:** `linux-x64-glibc` is accepted only when the host's platform, arch, glibc family and version (`process.report` `glibcVersionRuntime`) and Node-API version (`process.versions.napi`) are compatible. Anything unprovable fails closed.
- **ELF and addon check:** every ELF file must be x86-64, and 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 must state `libcVersion` (ADR 0049).
## The libvips supplement (`@img/[email protected]`)
- **Contents:** 184 components and 143 unique texts, assembled reproducibly from the **exact upstream sources sharp-libvips v1.3.3 builds linux-x64 from**:
- 27 C/C++ libraries and glib's `gvdb`;
- librsvg's Rust crates, reproduced with `cargo tree` after the build's own edits;
- the Rust standard library at the `rustc` commit recorded in the binary;
- the LGPL-3.0, GPL-3.0 and MPL-2.0 texts.
`PROVENANCE.md` records every source with its SHA-256, plus the method and exclusions.
- **Pin:** `ekklesia-content-v1:sha256:50647b0b…`, identical whether computed from the installed copy or the registry tarball.
- **Line endings:** `.gitattributes` keeps supplement texts byte-exact (`-text`), because each is named by its SHA-256.
- **Open:** LGPL/MPL source-availability determinations stay open, as ADR 0052 states. The docs say a package carrying this supplement is **not yet treated as publicly distributable**.
## Proof
- A checked-in AGPL-3.0-or-later fixture module (`tests/fixtures/native-module`) packs to `native-proof-0.1.0-linux-x64-glibc.tar.gz`: 8,863,205 bytes, 125 files plus metadata, 21.6 MB unpacked.
- **Determinism:** two fresh clones at unrelated absolute paths produce byte-identical archives (sha256 `bbcfd086…`), with no host or checkout path inside.
- **Runtime:** Core's verifier accepts the package. Extracted elsewhere, it runs a sharp resize and a PNG round trip in an empty-environment process.
- Every module resolution stays inside the package.
- Only the package's addon and libvips, plus the host's glibc and libstdc++, are loaded.
## Verification
- module-pack: 78 tests, including the new native-target, native-closure and supplements suites.
- Core package verification: 64.
- `pnpm verify`: passes.
- The deploy smoke was not run. The image installs production dependencies only, so `sharp`, a dev dependency, doesn't enter it, and the smoke's `any`-target template lifecycle is unaffected.
ADR 0052 remains **Proposed**, so you can decide whether this implementation accepts it.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
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]>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Implements ADR 0049's deferred native target (
linux-x64-glibc) and ADR 0052's reviewed license supplements, proven with a real module that usessharp.packageFormatstays 1,anypackaging is unchanged, and Signage is untouched.Packager (
@ekklesia/module-pack)--target linux-x64-glibc. Native or platform-specific packages stay outside the bundle. They are found by the same generic rule that refuses them inany, with no names hard-coded.dependencies, installedoptionalDependenciesmatching the target'sos/cpu/libc, and required peers. It is copied as real files flat undernode_modules/<name>, with:.d.tsor source maps;enginesrange doesn't cover the package's, and a native target with no addon.nodeApicomes from the addon's ownnode_api_module_get_api_version_v1;nodeAbiis used for ABI-specific addons;libcVersionis the newestGLIBC_symbol version needed.ekklesia-content-v1digest adds labelled material after it.src/supplements.ts.Verifier (Core)
linux-x64-glibcis accepted only when the host's platform, arch, glibc family and version (process.reportglibcVersionRuntime) and Node-API version (process.versions.napi) are compatible. Anything unprovable fails closed..nodemust be an ELF object.anypackages now also refusenode_modules/and ELF files.nodeApiornodeAbi, and Linux targets must statelibcVersion(ADR 0049).The libvips supplement (
@img/[email protected])Contents: 184 components and 143 unique texts, assembled reproducibly from the exact upstream sources sharp-libvips v1.3.3 builds linux-x64 from:
gvdb;cargo treeafter the build's own edits;rustccommit recorded in the binary;PROVENANCE.mdrecords every source with its SHA-256, plus the method and exclusions.Pin:
ekklesia-content-v1:sha256:50647b0b…, identical whether computed from the installed copy or the registry tarball.Line endings:
.gitattributeskeeps supplement texts byte-exact (-text), because each is named by its SHA-256.Open: LGPL/MPL source-availability determinations stay open, as ADR 0052 states. The docs say a package carrying this supplement is not yet treated as publicly distributable.
Proof
tests/fixtures/native-module) packs tonative-proof-0.1.0-linux-x64-glibc.tar.gz: 8,863,205 bytes, 125 files plus metadata, 21.6 MB unpacked.bbcfd086…), with no host or checkout path inside.Verification
pnpm verify: passes.sharp, a dev dependency, doesn't enter it, and the smoke'sany-target template lifecycle is unaffected.ADR 0052 remains Proposed, so you can decide whether this implementation accepts it.
🤖 Generated with Claude Code