docs: accept ADR 0048, one generic image with installed modules outside it #63

Merged
Zayin_Admin merged 1 commits from docs/adr-0048-installed-modules into main 2026-10-07 13:04:24 +00:00
Member

Records a new architecture decision. Docs only: no runtime source, Dockerfile, Compose, CI, or test changes.

ADR 0048: Ekklesia ships one generic image, and installed modules live outside it

  • One generic platform image with zero feature modules. Building it does not depend on what is in modules/ in the checkout, and it takes no installation-specific input. Per-installation images and assembly repositories are not part of the model.
  • Installation-owned module storage: EKKLESIA_MODULES_DIR selects it (/var/lib/ekklesia/modules in the shipping image; <repo>/modules when unset, for development). Mounted read-only to Ekklesia. Changes are discovered only at a controlled restart, with no hot loading.
  • Self-contained installed modules: each carries its manifest, built artifacts, migrations, and production runtime dependencies; the platform lends none. Native dependencies must match the image runtime. The exact Drizzle version is recorded as a constraint of the current implementation, not a permanent contract.
  • Disable, uninstall, and purge are distinct. Removing code keeps data and stored state, purge is deferred, and reinstalling recovers the retained state.
  • Migration history of an absent module is retained and reported instead of blocking planning. A present (or returning) module and Core stay strictly validated: a missing applied migration, a checksum mismatch, or a downgrade still fails.
  • Trust boundary unchanged: modules are trusted code. pnpm boundaries only proves workspace source, so conformance of installed packages moves to module CI, packaging validation, and the harness. This is not a sandbox.

Relationship to earlier decisions

  • Supersedes (partial) 0044: only "Composition from pinned sources", the topology table saying the api image contains the enabled modules, and the per-instance-lockfile consequence.
  • Supersedes (partial) 0009: only the rejection of applied history absent from the inventory, which 0009 left to "a future explicit platform policy".
  • Amends 0006: cloning into modules/ plus a workspace install becomes the development workflow only.
  • Extends 0028 and 0030.
  • Following the existing convention (0014, 0021, 0024), the partly superseded ADRs keep their status and text unchanged.

Other docs

  • docs/architecture/decisions/README.md: index entry.
  • 0047-module-ci-harness.md (Proposed): one header cross-reference saying steps 1 and 3 must be revised against 0048 before acceptance. Its decision text is not changed here.
  • deploy/README.md: a short note that its composition model is being replaced, and that the image behaves as documented until the implementation lands.

The instance repository is untouched. It pins v0.1.2 and vendors deploy/ from that tag, so this branch does not affect it.

Verification

  • pnpm verify: passed (format, lint, boundaries, typecheck, tests, module and migration validation, identity schema, build).
  • pnpm deploy:config: all three Compose combinations valid.
  • All 93 relative links in the changed files resolve.

🤖 Generated with Claude Code

Records a new architecture decision. **Docs only:** no runtime source, Dockerfile, Compose, CI, or test changes. ## ADR 0048: Ekklesia ships one generic image, and installed modules live outside it - **One generic platform image** with zero feature modules. Building it does not depend on what is in `modules/` in the checkout, and it takes no installation-specific input. Per-installation images and assembly repositories are not part of the model. - **Installation-owned module storage:** `EKKLESIA_MODULES_DIR` selects it (`/var/lib/ekklesia/modules` in the shipping image; `<repo>/modules` when unset, for development). Mounted read-only to Ekklesia. Changes are discovered only at a controlled restart, with no hot loading. - **Self-contained installed modules:** each carries its manifest, built artifacts, migrations, and production runtime dependencies; the platform lends none. Native dependencies must match the image runtime. The exact Drizzle version is recorded as a constraint of the current implementation, not a permanent contract. - **Disable, uninstall, and purge are distinct.** Removing code keeps data and stored state, purge is deferred, and reinstalling recovers the retained state. - **Migration history of an absent module** is retained and reported instead of blocking planning. A present (or returning) module and Core stay strictly validated: a missing applied migration, a checksum mismatch, or a downgrade still fails. - **Trust boundary unchanged:** modules are trusted code. `pnpm boundaries` only proves workspace source, so conformance of installed packages moves to module CI, packaging validation, and the harness. This is not a sandbox. ## Relationship to earlier decisions - **Supersedes (partial) 0044:** only "Composition from pinned sources", the topology table saying the `api` image contains the enabled modules, and the per-instance-lockfile consequence. - **Supersedes (partial) 0009:** only the rejection of applied history absent from the inventory, which 0009 left to "a future explicit platform policy". - **Amends 0006:** cloning into `modules/` plus a workspace install becomes the development workflow only. - **Extends 0028 and 0030.** - Following the existing convention (0014, 0021, 0024), the partly superseded ADRs keep their status and text unchanged. ## Other docs - `docs/architecture/decisions/README.md`: index entry. - `0047-module-ci-harness.md` (Proposed): one header cross-reference saying steps 1 and 3 must be revised against 0048 before acceptance. Its decision text is not changed here. - `deploy/README.md`: a short note that its composition model is being replaced, and that the image behaves as documented until the implementation lands. The instance repository is untouched. It pins v0.1.2 and vendors `deploy/` from that tag, so this branch does not affect it. ## Verification - `pnpm verify`: passed (format, lint, boundaries, typecheck, tests, module and migration validation, identity schema, build). - `pnpm deploy:config`: all three Compose combinations valid. - All 93 relative links in the changed files resolve. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
ekklesia-bot added 1 commit 2026-10-07 12:45:37 +00:00
docs: accept ADR 0048, one generic image with installed modules outside it
CI / verify (pull_request) Successful in 52s
CI / infrastructure-smoke (pull_request) Successful in 35s
CI / migration-smoke (pull_request) Successful in 1m49s
CI / image-build (pull_request) Successful in 21s
CI / deploy-smoke (same-origin) (pull_request) Successful in 41s
CI / deploy-smoke (split) (pull_request) Successful in 1m3s
cefdde36a2
Ekklesia produces one platform image with zero feature modules. Installed
modules live in installation-owned storage selected by EKKLESIA_MODULES_DIR
(/var/lib/ekklesia/modules in the image, <repo>/modules in development),
mounted read-only and discovered only at a controlled restart. An installed
module directory is self-contained; the platform lends it no dependencies.

Uninstall is distinct from disable and purge: removing module code keeps its
data and stored state, and applied migration history of an absent module is
retained and reported instead of blocking planning. Present modules and Core
stay strictly validated.

Supersedes in part ADR 0044 (composition from pinned sources) and ADR 0009
(rejection of history absent from the inventory); amends ADR 0006; extends
ADR 0028 and ADR 0030. ADR 0047 gains a cross-reference saying it must be
revised before acceptance, and deploy/README.md notes that its composition
model is being replaced. No code, Dockerfile, Compose, CI, or test changes.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Zayin_Admin merged commit 4d28a82937 into main 2026-10-07 13:04:24 +00:00
Zayin_Admin deleted branch docs/adr-0048-installed-modules 2026-10-07 13:04:24 +00:00
Sign in to join this conversation.
No Reviewers
No labels
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Zayin/Ekklesia#63