feat: add module contracts and discovery
CI / verify (push) Has been cancelled
CI / infrastructure-smoke (push) Has been cancelled

This commit is contained in:
ekklesia
2026-07-12 22:14:01 -05:00
parent d9489384c1
commit 57552a21a4
43 changed files with 2277 additions and 21 deletions
+99
View File
@@ -0,0 +1,99 @@
# Module development
An Ekklesia module is a backend capability package. It owns business behavior and data declarations;
it never owns components, styles, layouts, renderers, navigation, or other UI.
## Required package shape
Each immediate child of `modules/` must contain:
```text
modules/example/
├── ekklesia.module.json
├── package.json
└── src/server/index.ts
```
`package.json` must use ESM, a strict semantic version, a unique package name, and:
```json
{
"ekklesia": {
"layer": "module"
}
}
```
Its version must match the module manifest version. Internal package dependencies use `workspace:`
ranges and supported package entrypoints.
## Manifest
The canonical manifest is inert JSON so discovery can validate a module without executing it:
```json
{
"manifestVersion": 1,
"id": "calendar",
"name": "Calendar",
"version": "0.1.0",
"compatibility": {
"platform": "^0.1.0",
"moduleSdk": "^0.1.0"
},
"dependencies": {
"modules": {
"required": {
"people": "^0.1.0"
}
},
"capabilities": {
"optional": ["media.items"]
}
},
"capabilities": ["calendar.events"],
"permissions": ["calendar.events.read"],
"storage": {
"buckets": [
{
"id": "assets",
"description": "Private event assets owned by Calendar."
}
]
},
"entrypoints": {
"server": "./src/server/index.ts"
}
}
```
Module, capability, and permission identifiers are lowercase and namespaced. Entrypoints must begin
with `./`, stay inside the package, and exist. Unknown manifest properties are rejected, including
presentation fields such as components or renderers.
Storage bucket IDs are logical names scoped to the module. Modules may request multiple buckets.
Core will later map them to deployment-specific physical S3 buckets and provide scoped access;
module code must not configure SeaweedFS or other S3 clients directly.
## Discovery behavior
Run:
```bash
pnpm modules:validate
```
Discovery checks every installed module atomically. It rejects malformed manifests, duplicate IDs
or package names, version mismatches, incompatible platform or SDK ranges, missing required modules
or capabilities, incompatible installed dependencies, cycles, and missing or escaping entrypoints.
Missing optional dependencies are allowed. Valid modules are ordered dependency-first with stable
identifier sorting.
Discovery does not load server code. Lifecycle execution, route/job registration, Drizzle schema
aggregation and migrations, and physical bucket provisioning are deliberately deferred.
## Start from the template
Copy `templates/module` to `modules/<your-module-id>` and follow its README. The template is part of
the workspace and is validated by the same contracts and discovery implementation as installed
modules.