Add ADR 0016 recording the accepted module database access design (ModuleDatabase, the frozen ModuleRuntimeServices boundary, one pool/one facade/one services-object identity, explicit migrations, and the trust model), with narrow cross-reference corrections to ADR 0006 and ADR 0015 where their original text is now inaccurate. Sweep docs/development/api.md, docs/development/authorization.md, docs/module-development/README.md, docs/development/testing.md, and docs/development/identity.md for the new database boundary and remaining Phase 4C staleness; correct the stale "Phase 4C is next" roadmap paragraph in platform-architecture.md and the matching gap in README's current-status narrative. Extend the module template with a permissioned GET /records route reading through context.services.database, using the canonical createModuleTable helper, with matching template tests.
47 lines
3.2 KiB
Markdown
47 lines
3.2 KiB
Markdown
# Ekklesia module template
|
|
|
|
This is the smallest supported backend-only Ekklesia module. It proves the static manifest,
|
|
compiled runtime and schema entrypoints, capability registration, a module-owned Drizzle table, a
|
|
generated module-owned migration, logical storage-bucket declarations, and one permissioned HTTP
|
|
route (`GET /records`, declared in `register`) that reads that table through
|
|
`context.services.database` — the platform-provided `ModuleDatabase` facade, never a
|
|
module-constructed Drizzle instance or a raw `pg` client. Migration execution and storage
|
|
provisioning are intentionally not included.
|
|
|
|
To create a module inside this repository:
|
|
|
|
1. Copy this directory to `modules/<module-id>`.
|
|
2. Rename the package in `package.json` and remove `private` when it is ready for publication.
|
|
3. Update the ID, name, version, namespaces, compatibility ranges, and bucket requests in
|
|
`ekklesia.module.json`.
|
|
4. Keep the manifest capability versions and dependency ranges aligned with the contracts the
|
|
module actually implements and consumes.
|
|
5. Replace `src/server/index.ts` with backend behavior only. Its `defineModuleRuntime` ID and version
|
|
must match the manifest; do not duplicate the rest of the manifest in TypeScript. Declare HTTP
|
|
routes only in `register`, against a permission the manifest already declares; `start`, `stop`,
|
|
and every route handler — never `register` — receive `context.services.database`, a typed
|
|
`ModuleDatabase` view over the platform's one PostgreSQL pool.
|
|
6. Replace the pure Drizzle declarations in `src/schema/tables.ts` and keep its table prefix aligned
|
|
with the module ID. Keep the `defineModuleSchema` ownership wrapper in `src/schema/index.ts`
|
|
aligned too, and never import another module's schema.
|
|
7. Update `drizzle.config.ts`, generate forward migrations with `pnpm migration:generate
|
|
--name=lowercase_name` from the module directory, and review the SQL. Keep each generated tag in
|
|
`drizzle/meta/_ekklesia.json`, classify it as `none` or `approval-required`, and change that
|
|
file's `moduleId` when renaming the template.
|
|
8. Run `pnpm install`, `pnpm build`, `pnpm modules:validate`, `pnpm migrations:validate`, and
|
|
`pnpm verify` from the repository
|
|
root. The declared production entrypoint is the compiled `dist/server/index.js`, not source
|
|
TypeScript; the schema entrypoint is likewise compiled to `dist/schema/index.js`.
|
|
|
|
Do not add UI components, styles, renderers, navigation, or layouts. Those belong to surfaces.
|
|
Keep imports side-effect-free, register capabilities in `register`, acquire resources in `start`,
|
|
and release them in `stop`. Never construct a Drizzle instance, read `DATABASE_URL`, or reach for a
|
|
raw `pg` client — `context.services.database` is the only supported way to query this module's own
|
|
tables, and it is never available during `register`.
|
|
|
|
The migration directory uses the pinned stable Drizzle Kit `0.31.10` PostgreSQL journal and
|
|
snapshot format. Migrations are forward-only and may modify only this module's objects. Offline
|
|
validation treats SQL as opaque bytes, calculates SHA-256 from the exact contents, and never opens a
|
|
database or executes SQL. Destructive declarations are review metadata, not automatic SQL
|
|
classification or approval.
|