@ekklesia/contracts still emitted a type-only import of
drizzle-orm/node-postgres for the legacy ModuleDatabase facade, so a
standalone module type-checked only because skipLibCheck hid it.
- ModuleDatabase, LegacyModuleRuntimeServices and
AnyModuleRuntimeServices move to core/src/modules/database.ts, beside
the facade Core builds; the facade itself is unchanged.
- contracts' runtime, route, and services generics no longer name an
ORM: the database type is a plain parameter defaulting to the ABI v1
executor, and the legacy definition's database is opaque until Core
specializes it. Core and apps/api name the legacy types from Core.
- contracts drops its drizzle-orm optional peer and devDependency;
Drizzle stays public only through @ekklesia/module-database/drizzle.
- The facade's type-level test moves from contracts to Core.
- Regression proof: the standalone fixture type-checks with
skipLibCheck: false against the packed tarballs, with no drizzle-orm
installed (the smoke asserts both). Against the previous contracts
tarball the same check fails with TS2307 on drizzle-orm/node-postgres.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Introduce ModuleDatabase (a typed, restricted Drizzle query surface) and the frozen
ModuleRuntimeServices boundary in @ekklesia/contracts, and thread the same services object
through Core's module start/stop lifecycle hooks and apps/api's authorized module HTTP handler
context. apps/api builds the facade via a new core/src/modules/database.ts view (createModuleDatabaseView)
over the one existing shared PostgreSQL pool, alongside the identity and authorization views, and
wires it into startApi's fixed startup order ahead of Identity/Authorization construction.
Registration stays database-free; a module reaches its database only through an authorized start,
stop, or HTTP handler invocation.