# 0005: Static module manifests and atomic discovery - Status: Superseded - Superseded by: [0006](0006-versioned-capabilities-and-compiled-module-runtime.md) - 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.ts` manifests were rejected because discovery would cross the code-execution boundary before validation. - Embedding the full manifest in `package.json` was 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.