# 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: 1. **`HostAdapters.ledgerDb: LedgerDb`** — host-private, narrow SQLite handle the `PluginLedger` keeps using. Renamed from the former `HostAdapters.db`. 2. **`HostAdapters.db?: AdminDatabaseLike`** — optional, consumer-facing. Populated by `createDbAdapter(...).admin` from `@suaveplan/api-db-adapter`. The host threads it onto `PluginContext.db` (admin-scoped) and applies `createTenantScopedWrapper(admin, tenantId)` per request to expose it on `RequestContext.db` (tenant-scoped). 3. **`PluginContext.db: AdminDatabaseLike | null`** + **`RequestContext.db: TenantScopedDatabaseLike | null`** added as top-level fields. `null` when (a) the host was booted without `adapters.db` configured, or (b) for `RequestContext` only, the tenant resolver chain returned `null` on this request. 4. **E2E foundation-stack** restores `createDbAdapter({ engine: "sqlite", url: ":memory:" })` as `adapters.db` and adds a `GET /api/db-ping` route exercising `ctx.db?.execute` + `ctx.db?.query` through the tenant-scoped wrapper. A companion test asserts 200 + non-empty rows. ## Impact ### Affected dependents - `@suaveplan/api-types` — `PluginContext` / `RequestContext` / `JobContext` / `ConnectionContext` each gain a `db` field. Source- incompatible for any consumer constructing a `PluginContext` literal — but the only in-tree literal consumer is the host's own test harness (`{} as never` mock), which already type-erases. - `@suaveplan/api-host` — - `HostAdapters.db` renamed to `ledgerDb`; new optional `HostAdapters.db: AdminDatabaseLike`. - Host config Zod schema updated. - `RequestPipelineOptions` gains optional `db: AdminDatabaseLike`. - `buildRequestContext` accepts + propagates `db`. - Request-pipeline driver applies `createTenantScopedWrapper` when both `adapters.db` is set AND a tenant is resolved. - New runtime dep `@suaveplan/api-db-adapter`. - `@suaveplan/e2e-foundation-stack` — wires `createDbAdapter` + registers an inline `bun:sqlite` engine factory; adds the `/api/db-ping` route + an E2E test. Blast radius (atomic update list in this commit): - `packages/api-stack/api/api-types/src/plugin-context/plugin-context.types.ts` - `packages/api-stack/api/api-host/src/host/host.types.ts` - `packages/api-stack/api/api-host/src/host/host.ts` - `packages/api-stack/api/api-host/src/host/host.test.ts` - `packages/api-stack/api/api-host/src/request-pipeline/request-pipeline.types.ts` - `packages/api-stack/api/api-host/src/request-pipeline/request-pipeline-driver.ts` - `packages/api-stack/api/api-host/src/request-pipeline/request-pipeline-helpers.ts` - `packages/api-stack/api/api-host/package.json` - `e2e/foundation-stack/src/server.ts` - `e2e/foundation-stack/src/fixture-plugin.ts` - `e2e/foundation-stack/tests/foundation.spec.ts` - `e2e/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.