4.6 KiB
foundation-fix-gap-4-db-split
- Status: PROPOSED
- Spec deltas:
- ./specs/api-host/spec.md
- ./specs/api-types/spec.md
What & why
The post-Stage-4 foundation-coherence audit (Gap #4) flagged that
HostAdapters.db was shaped for the narrow LedgerDb interface
(bun:sqlite-style prepare(sql) / run(sql)) consumed by the
host-internal PluginLedger, while @suaveplan/api-db-adapter
produces a multi-engine AdminDatabaseLike façade plugins consume.
The two surfaces are type-incompatible — there is no safe way to
share a single adapters.db slot. The E2E foundation-stack server
documented the gap explicitly (@suaveplan/api-db-adapter was
swapped out for a raw bun:sqlite handle to satisfy the ledger).
This change splits the slot:
HostAdapters.ledgerDb: LedgerDb— host-private, narrow SQLite handle thePluginLedgerkeeps using. Renamed from the formerHostAdapters.db.HostAdapters.db?: AdminDatabaseLike— optional, consumer-facing. Populated bycreateDbAdapter(...).adminfrom@suaveplan/api-db-adapter. The host threads it ontoPluginContext.db(admin-scoped) and appliescreateTenantScopedWrapper(admin, tenantId)per request to expose it onRequestContext.db(tenant-scoped).PluginContext.db: AdminDatabaseLike | null+RequestContext.db: TenantScopedDatabaseLike | nulladded as top-level fields.nullwhen (a) the host was booted withoutadapters.dbconfigured, or (b) forRequestContextonly, the tenant resolver chain returnednullon this request.- E2E foundation-stack restores
createDbAdapter({ engine: "sqlite", url: ":memory:" })asadapters.dband adds aGET /api/db-pingroute exercisingctx.db?.execute+ctx.db?.querythrough the tenant-scoped wrapper. A companion test asserts 200 + non-empty rows.
Impact
Affected dependents
@suaveplan/api-types—PluginContext/RequestContext/JobContext/ConnectionContexteach gain adbfield. Source- incompatible for any consumer constructing aPluginContextliteral — but the only in-tree literal consumer is the host's own test harness ({} as nevermock), which already type-erases.@suaveplan/api-host—HostAdapters.dbrenamed toledgerDb; new optionalHostAdapters.db: AdminDatabaseLike.- Host config Zod schema updated.
RequestPipelineOptionsgains optionaldb: AdminDatabaseLike.buildRequestContextaccepts + propagatesdb.- Request-pipeline driver applies
createTenantScopedWrapperwhen bothadapters.dbis set AND a tenant is resolved. - New runtime dep
@suaveplan/api-db-adapter.
@suaveplan/e2e-foundation-stack— wirescreateDbAdapter+ registers an inlinebun:sqliteengine factory; adds the/api/db-pingroute + an E2E test.
Blast radius (atomic update list in this commit):
packages/api-stack/api/api-types/src/plugin-context/plugin-context.types.tspackages/api-stack/api/api-host/src/host/host.types.tspackages/api-stack/api/api-host/src/host/host.tspackages/api-stack/api/api-host/src/host/host.test.tspackages/api-stack/api/api-host/src/request-pipeline/request-pipeline.types.tspackages/api-stack/api/api-host/src/request-pipeline/request-pipeline-driver.tspackages/api-stack/api/api-host/src/request-pipeline/request-pipeline-helpers.tspackages/api-stack/api/api-host/package.jsone2e/foundation-stack/src/server.tse2e/foundation-stack/src/fixture-plugin.tse2e/foundation-stack/tests/foundation.spec.tse2e/foundation-stack/package.json
Backward compatibility
The HostAdapters.db → HostAdapters.ledgerDb rename is a hard rename
(no compatibility shim) because the genesis branch has no shipped
consumers outside the in-tree atomic update list above.
PluginContext.db / RequestContext.db are NEW fields, additive at
the type level for any future consumer.
Parity Checklist
This is a genesis-original fix; no upstream parity table required.
Verification
bunx turbo lint typecheck test build --filter=@suaveplan/api-host --filter=@suaveplan/api-types --filter=@suaveplan/api-db-adapter --filter=@suaveplan/e2e-foundation-stack
→ green on api-host / api-types / api-db-adapter. (The e2e package's
typecheck error is a pre-existing module-resolution issue unrelated
to this change — confirmed via git-stash baseline.)
bunx turbo test:coverage --filter=@suaveplan/api-host --filter=@suaveplan/api-types
→ 100% lines on touched modules (statements/branches/functions
unchanged at baseline).
E2E suite: bun test:e2e → 11/11 pass, including the new
db adapter — ctx.db wired through tenant-scoped wrapper test.