2.9 KiB
0005: Static module manifests and atomic discovery
- Status: Accepted
- Date: 2026-07-12
Context
Ekklesia modules must be installable by placing a package in modules/ without editing Core or a
central registry. Core must validate identity, compatibility, dependencies, capabilities, storage
requirements, and entrypoints before it runs module behavior. Importing an executable TypeScript
manifest would allow top-level module code to run before validation completed.
Decision
Every module uses one inert, versioned ekklesia.module.json manifest. @ekklesia/contracts owns
the authoritative Zod schema and serializable types. @ekklesia/module-sdk re-exports those public
contracts and provides defineModule for typed programmatic validation without becoming a Core
service locator.
Core scans immediate non-hidden directories under the configured modules directory. Discovery validates all manifests and package metadata, resolves entrypoints without loading them, checks platform and Module SDK compatibility, resolves module and capability dependencies, and produces a deterministic dependency-first order. Any error rejects the entire discovery result with sorted, structured issues; no module server code is partially loaded.
Storage requirements are declarative. A module may request one or more logical buckets in its manifest, but it cannot create provider clients or select physical bucket names. The later Core storage service will provision deployment-prefixed physical buckets and give the owning module scoped handles. Buckets remain private unless a future explicit storage contract says otherwise.
Alternatives
- Executable
module.tsmanifests were rejected because discovery would cross the code-execution boundary before validation. - Embedding the full manifest in
package.jsonwas rejected because it couples the platform contract to package-manager metadata and makes the manifest harder to version independently. - A manually maintained import registry was rejected because every module installation would require a central source edit.
- Letting modules configure SeaweedFS or S3 clients directly was rejected because Core owns credentials, provider selection, isolation, and lifecycle.
Consequences
JSON manifests do not provide TypeScript inference by themselves, so validation commands and clear path-aware errors are part of the authoring workflow. A JSON Schema can be generated from the authoritative contract later for editor completion.
Discovery currently proves entrypoint existence but does not import server behavior, execute lifecycle hooks, provision requested buckets, or register routes, jobs, schemas, and migrations. Those operations begin only after a complete valid discovery result in later runtime slices.
Migration implications
The manifest includes manifestVersion: 1. Future incompatible shapes require an explicit schema
version and migration path rather than silently changing existing module interpretation.