Implements ADR 0051: every Module Package v1 declares the module's own license and carries its text. packageFormat stays 1, and pre-ADR-0051 metadata fails closed.
Changes
Contracts.ekklesia.package.json requires an SPDX license expression, validated with spdx-expression-parse. UNLICENSED, empty and malformed expressions are refused, and files must list exactly one non-empty root LICENSE.
Package contracts move to the @ekklesia/contracts/module-package subpath. The module SDK re-exports the contracts root into every module bundle, and spdx-exceptions (CC-BY-3.0) and spdx-license-ids (CC0-1.0) ship no licence files. Bundling them would make every module fail notices generation.
The template test asserts that no SPDX code reaches a bundle or THIRD_PARTY_NOTICES. Only Core and module-pack used those names; Signage doesn't.
Packager.
The license comes from the source package.json's string declaration and is never invented.
--license-file is required: a non-empty regular file, with no symlinks, parent search or download.
Its bytes are copied unchanged to LICENSE, listed with size and SHA-256, and covered by the archive digest.
THIRD_PARTY_NOTICES stays third-party only, and bundled Ekklesia code stays in incorporates.
Verifier. Rejects missing or invalid license metadata, and a missing, unlisted, duplicated or corrupted LICENSE, through the schema plus the existing strict inventory.
Template. Packaged as AGPL-3.0-or-later with the repository's canonical LICENSE, passed explicitly in the package Dockerfile, the smoke script and the docs.
ADR 0051 → Accepted.
Work was started by Codex, then reviewed and completed in Claude Code. The additions are refusing an empty license file, requiring a non-empty LICENSE entry in the schema, and empty-file and symlink tests.
Verification
Focused tests: contracts 43, Core package verification/CLI/discovery 105, module-pack 50 (including the template package): all pass.
Deterministic package: the template packed twice gives byte-identical archives (sha256 8dc5055f…). The packaged LICENSE equals the repository AGPL text (sha256 0d96a4ff…), and license is AGPL-3.0-or-later.
EKKLESIA_SMOKE_TOPOLOGY=split pnpm deploy:smoke: passed. The template was packaged with --license-file, verified by the image's own verifier (14 files), installed, removed and reinstalled, and the whole lifecycle succeeded.
pnpm verify: one run on this branch. Format, lint, boundaries, typecheck and build passed, and every package's tests passed except 3 Core import-safety tests, which hit their 5 s timeout:
cli-bootstrap-platform-owner.test.ts
doctor-import.test.ts
module-http-import.test.ts
These tests spawn a fresh import and time out only under the full parallel pnpm verify load. After the smoke, the four known import-safety files (5 tests, the three above plus cli-create-initial-owner.test.ts) passed in isolation in about 1 s.
This is a known, pre-existing flake. It has hit 3 of the last 4 full runs across recent branches, on unchanged test code.
Full verify was not rerun locally; CI provides the next full run.
The flake deserves its own small fix, such as a longer timeout for these import tests.
Not changed: Signage, the database ABI, packageFormat 2, marketplace policy, image licensing and rog-ekklesia-instance.
Implements **ADR 0051**: every Module Package v1 declares the module's own license and carries its text. `packageFormat` stays 1, and pre-ADR-0051 metadata fails closed.
## Changes
- **Contracts.** `ekklesia.package.json` requires an SPDX `license` expression, validated with `spdx-expression-parse`. `UNLICENSED`, empty and malformed expressions are refused, and `files` must list exactly one non-empty root `LICENSE`.
- Package contracts move to the **`@ekklesia/contracts/module-package` subpath**. The module SDK re-exports the contracts root into every module bundle, and `spdx-exceptions` (CC-BY-3.0) and `spdx-license-ids` (CC0-1.0) ship no licence files. Bundling them would make every module fail notices generation.
- The template test asserts that no SPDX code reaches a bundle or `THIRD_PARTY_NOTICES`. Only Core and module-pack used those names; Signage doesn't.
- **Packager.**
- The license comes from the source `package.json`'s string declaration and is never invented.
- `--license-file` is required: a non-empty regular file, with no symlinks, parent search or download.
- Its bytes are copied unchanged to `LICENSE`, listed with size and SHA-256, and covered by the archive digest.
- `THIRD_PARTY_NOTICES` stays third-party only, and bundled Ekklesia code stays in `incorporates`.
- **Verifier.** Rejects missing or invalid license metadata, and a missing, unlisted, duplicated or corrupted `LICENSE`, through the schema plus the existing strict inventory.
- **Template.** Packaged as `AGPL-3.0-or-later` with the repository's canonical `LICENSE`, passed explicitly in the package Dockerfile, the smoke script and the docs.
- **ADR 0051 → Accepted.**
Work was started by Codex, then reviewed and completed in Claude Code. The additions are refusing an empty license file, requiring a non-empty `LICENSE` entry in the schema, and empty-file and symlink tests.
## Verification
- **Focused tests:** contracts 43, Core package verification/CLI/discovery 105, module-pack 50 (including the template package): all pass.
- **Deterministic package:** the template packed twice gives byte-identical archives (sha256 `8dc5055f…`). The packaged `LICENSE` equals the repository AGPL text (sha256 `0d96a4ff…`), and `license` is `AGPL-3.0-or-later`.
- **`EKKLESIA_SMOKE_TOPOLOGY=split pnpm deploy:smoke`:** passed. The template was packaged with `--license-file`, verified by the image's own verifier (14 files), installed, removed and reinstalled, and the whole lifecycle succeeded.
- **`pnpm verify`:** one run on this branch. Format, lint, boundaries, typecheck and build passed, and every package's tests passed except **3 Core import-safety tests**, which hit their **5 s timeout**:
- `cli-bootstrap-platform-owner.test.ts`
- `doctor-import.test.ts`
- `module-http-import.test.ts`
These tests spawn a fresh import and time out only under the full parallel `pnpm verify` load. After the smoke, the four known import-safety files (5 tests, the three above plus `cli-create-initial-owner.test.ts`) passed in isolation in about 1 s.
- This is a known, pre-existing flake. It has hit 3 of the last 4 full runs across recent branches, on unchanged test code.
- Full verify was not rerun locally; CI provides the next full run.
- The flake deserves its own small fix, such as a longer timeout for these import tests.
**Not changed:** Signage, the database ABI, packageFormat 2, marketplace policy, image licensing and rog-ekklesia-instance.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Every Module Package v1 now declares the module's license and carries its
text. packageFormat stays 1; pre-ADR-0051 metadata fails closed.
- Contracts: ekklesia.package.json requires an SPDX `license` expression,
validated with spdx-expression-parse, with UNLICENSED and non-expressions
refused. The `files` list must hold exactly one non-empty root LICENSE.
The package contracts move to the @ekklesia/contracts/module-package
subpath, so the SPDX parser and its data (spdx-exceptions and
spdx-license-ids ship no licence files) never reach a module bundle
through the SDK's re-export of the contracts root.
- Packager: reads the source package.json's string SPDX declaration and
never invents one. It requires an explicit --license-file (a non-empty
regular file, no symlink, no parent search, no download) and copies its
bytes unchanged to LICENSE, listed with size and SHA-256 and covered by
the archive digest. THIRD_PARTY_NOTICES stays third-party only, and
bundled Ekklesia code stays in `incorporates`.
- Verifier: rejects missing or invalid license metadata, and a missing,
unlisted, duplicated, or corrupted LICENSE, through the schema and the
existing strict inventory.
- Template: packaged as AGPL-3.0-or-later with the repository's canonical
LICENSE, passed explicitly (Dockerfile, smoke, docs). Packing it twice
gives byte-identical archives.
Started by Codex; reviewed and completed in Claude Code (empty license-text
refusal, schema non-empty LICENSE, symlink and empty-file tests).
ADR 0051 is Accepted.
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 0051: every Module Package v1 declares the module's own license and carries its text.
packageFormatstays 1, and pre-ADR-0051 metadata fails closed.Changes
ekklesia.package.jsonrequires an SPDXlicenseexpression, validated withspdx-expression-parse.UNLICENSED, empty and malformed expressions are refused, andfilesmust list exactly one non-empty rootLICENSE.@ekklesia/contracts/module-packagesubpath. The module SDK re-exports the contracts root into every module bundle, andspdx-exceptions(CC-BY-3.0) andspdx-license-ids(CC0-1.0) ship no licence files. Bundling them would make every module fail notices generation.THIRD_PARTY_NOTICES. Only Core and module-pack used those names; Signage doesn't.package.json's string declaration and is never invented.--license-fileis required: a non-empty regular file, with no symlinks, parent search or download.LICENSE, listed with size and SHA-256, and covered by the archive digest.THIRD_PARTY_NOTICESstays third-party only, and bundled Ekklesia code stays inincorporates.LICENSE, through the schema plus the existing strict inventory.AGPL-3.0-or-laterwith the repository's canonicalLICENSE, passed explicitly in the package Dockerfile, the smoke script and the docs.Work was started by Codex, then reviewed and completed in Claude Code. The additions are refusing an empty license file, requiring a non-empty
LICENSEentry in the schema, and empty-file and symlink tests.Verification
Focused tests: contracts 43, Core package verification/CLI/discovery 105, module-pack 50 (including the template package): all pass.
Deterministic package: the template packed twice gives byte-identical archives (sha256
8dc5055f…). The packagedLICENSEequals the repository AGPL text (sha2560d96a4ff…), andlicenseisAGPL-3.0-or-later.EKKLESIA_SMOKE_TOPOLOGY=split pnpm deploy:smoke: passed. The template was packaged with--license-file, verified by the image's own verifier (14 files), installed, removed and reinstalled, and the whole lifecycle succeeded.pnpm verify: one run on this branch. Format, lint, boundaries, typecheck and build passed, and every package's tests passed except 3 Core import-safety tests, which hit their 5 s timeout:cli-bootstrap-platform-owner.test.tsdoctor-import.test.tsmodule-http-import.test.tsThese tests spawn a fresh import and time out only under the full parallel
pnpm verifyload. After the smoke, the four known import-safety files (5 tests, the three above pluscli-create-initial-owner.test.ts) passed in isolation in about 1 s.Not changed: Signage, the database ABI, packageFormat 2, marketplace policy, image licensing and rog-ekklesia-instance.
🤖 Generated with Claude Code