Files
Ekklesia/templates/module
ekklesia d9dd409aa3 feat: declare module permissions
Establishes the one canonical PermissionDeclaration contract
(packages/contracts/src/authorization.ts) — id/baseline/description,
strict, unknown-property-rejecting — consumed by both Core's
authorization registry and module manifests, replacing Core's
previously separate interface.

Bumps the canonical module manifest to manifestVersion 3: permissions
become complete declarations instead of bare identifier strings, with
manifest-owned namespace and duplicate-id enforcement. Version 2 and
bare string-array permissions are rejected outright; there is no
compatibility adapter.

Adds composePlatformPermissionRegistry (core/src/modules/permissions.ts),
a pure, synchronous composer that builds one platform permission
registry from Core's own declarations plus every already-discovered
module's, in deterministic order, reusing createPermissionRegistry
and rejecting any module-contributed permission in the reserved
core.* namespace. core/src/authorization remains independent of
core/src/modules; only the module integration layer depends on
authorization.

Updates the module template, module-development docs, authorization
docs, and existing manifest fixtures for manifestVersion 3. Does not
wire the combined registry into apps/api — that is pass 2.
2026-07-24 12:25:00 -05:00
..
2026-07-24 12:25:00 -05:00

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, and logical storage-bucket declarations. Migration execution, API routing, 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.
  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.

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.