docs: document module database access
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.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { defineModuleRuntime } from "@ekklesia/module-sdk";
|
||||
import { records } from "../schema/tables.js";
|
||||
|
||||
export const recordsCapability = Object.freeze({
|
||||
kind: "example-records",
|
||||
@@ -7,7 +8,25 @@ export const recordsCapability = Object.freeze({
|
||||
export default defineModuleRuntime({
|
||||
id: "example",
|
||||
version: "0.1.0",
|
||||
register({ capabilities }) {
|
||||
register({ capabilities, http }) {
|
||||
capabilities.provide("example.records", recordsCapability);
|
||||
|
||||
// The accepted module database boundary: `context.services.database` — provided only to an
|
||||
// authorized handler, never to `register` — is this module's one way to reach PostgreSQL. It
|
||||
// is a fully typed Drizzle query surface over the module's own table (`../schema/tables.js`),
|
||||
// never a raw `pg` client, a connection string, or a Drizzle instance this module built
|
||||
// itself. `example.records.read` is declared in `ekklesia.module.json`, exactly like every
|
||||
// other permission a module route enforces.
|
||||
http.route({
|
||||
method: "GET",
|
||||
path: "/records",
|
||||
permission: "example.records.read",
|
||||
async handler(_request, context) {
|
||||
const rows = await context.services.database
|
||||
.select({ id: records.id, value: records.value })
|
||||
.from(records);
|
||||
return Response.json(rows);
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user