feat(storage): pgvector adapter support gated on tier=federated (FED-M1-03) #472

Merged
jason.woltje merged 1 commits from feat/federation-m1-pgvector into main 2026-04-19 23:42:19 +00:00
Owner

Summary

FED-M1-03 — pgvector support in the postgres storage adapter, gated on enableVector flag (set automatically for federated tier). Local and standalone tiers are untouched.

Adapter changes:

  • StorageConfig postgres variant gains optional enableVector?: boolean.
  • PostgresAdapter.migrate() runs CREATE EXTENSION IF NOT EXISTS vector via db.execute(sql) BEFORE migrations when the flag is true. Idempotent — safe to re-run on an already-installed extension. Order matters: the extension must exist before any migration that creates a vector(...) column runs.
  • The constructor still does NOT touch the database (preserves current behavior).

Schema export:

  • vector custom type in @mosaicstack/db/schema is now exported (it was internal, used by preferences.embedding). Downstream packages can now declare vector('col', { dimensions: N }) in their own schemas.

Config wiring:

  • DEFAULT_FEDERATED_CONFIG.storage.enableVector = true so the federated default flows through to the adapter.
  • detectFromEnv() restructured so MOSAIC_STORAGE_TIER is checked BEFORE the DATABASE_URL guard. Setting MOSAIC_STORAGE_TIER=federated alone now returns the federated default config instead of silently misrouting to local (footgun fix raised in code review). Same applies to MOSAIC_STORAGE_TIER=standalone. With DATABASE_URL set, the URL is honored and enableVector is preserved.
  • detectFromEnv is now exported for direct test access.

Tests added:

  • 4 PostgresAdapter unit tests covering the gating + ordering. SQL-content assertion uses Drizzle's toSQL() (public API) with a documented fallback for older Drizzle versions.
  • 4 detectFromEnv tests covering each env-var permutation (no vars / federated alone / federated+DATABASE_URL / standalone alone).
  • 1 DEFAULT_FEDERATED_CONFIG constant test confirming enableVector=true.

Review chain:

  • Implementation: sonnet subagent on feat/federation-m1-pgvector
  • Independent review: feature-dev:code-reviewer (sonnet) — verdict ship-with-followup, raised 2 issues (silent misroute, brittle test assertion)
  • Both issues fixed pre-merge in the same branch
  • Independent haiku verifier confirmed both fixes + regression suite

Out of scope (deferred)

  • Tier-detector with fail-fast assertions → FED-M1-04
  • Migration script → FED-M1-05
  • Real-Postgres integration test (compose+vector boot) → FED-M1-07

Refs #460

Test plan

  • pnpm --filter @mosaicstack/storage test (31/31)
  • pnpm --filter @mosaicstack/config test (15/15)
  • pnpm typecheck (38/38)
  • pnpm lint (21/21)
  • pnpm format:check
  • CI green on merge

Generated with Claude Code

## Summary FED-M1-03 — pgvector support in the postgres storage adapter, gated on `enableVector` flag (set automatically for federated tier). Local and standalone tiers are untouched. **Adapter changes:** - `StorageConfig` postgres variant gains optional `enableVector?: boolean`. - `PostgresAdapter.migrate()` runs `CREATE EXTENSION IF NOT EXISTS vector` via `db.execute(sql)` BEFORE migrations when the flag is true. Idempotent — safe to re-run on an already-installed extension. Order matters: the extension must exist before any migration that creates a `vector(...)` column runs. - The constructor still does NOT touch the database (preserves current behavior). **Schema export:** - `vector` custom type in `@mosaicstack/db/schema` is now exported (it was internal, used by `preferences.embedding`). Downstream packages can now declare `vector('col', { dimensions: N })` in their own schemas. **Config wiring:** - `DEFAULT_FEDERATED_CONFIG.storage.enableVector = true` so the federated default flows through to the adapter. - `detectFromEnv()` restructured so `MOSAIC_STORAGE_TIER` is checked BEFORE the `DATABASE_URL` guard. Setting `MOSAIC_STORAGE_TIER=federated` alone now returns the federated default config instead of silently misrouting to local (footgun fix raised in code review). Same applies to `MOSAIC_STORAGE_TIER=standalone`. With `DATABASE_URL` set, the URL is honored and `enableVector` is preserved. - `detectFromEnv` is now exported for direct test access. **Tests added:** - 4 PostgresAdapter unit tests covering the gating + ordering. SQL-content assertion uses Drizzle's `toSQL()` (public API) with a documented fallback for older Drizzle versions. - 4 `detectFromEnv` tests covering each env-var permutation (no vars / federated alone / federated+DATABASE_URL / standalone alone). - 1 `DEFAULT_FEDERATED_CONFIG` constant test confirming `enableVector=true`. **Review chain:** - Implementation: sonnet subagent on `feat/federation-m1-pgvector` - Independent review: `feature-dev:code-reviewer` (sonnet) — verdict `ship-with-followup`, raised 2 issues (silent misroute, brittle test assertion) - Both issues fixed pre-merge in the same branch - Independent haiku verifier confirmed both fixes + regression suite ## Out of scope (deferred) - Tier-detector with fail-fast assertions → FED-M1-04 - Migration script → FED-M1-05 - Real-Postgres integration test (compose+vector boot) → FED-M1-07 **Refs** #460 ## Test plan - [x] `pnpm --filter @mosaicstack/storage test` (31/31) - [x] `pnpm --filter @mosaicstack/config test` (15/15) - [x] `pnpm typecheck` (38/38) - [x] `pnpm lint` (21/21) - [x] `pnpm format:check` - [ ] CI green on merge Generated with Claude Code
jason.woltje added 1 commit 2026-04-19 23:38:33 +00:00
feat(storage): pgvector adapter support gated on tier=federated (FED-M1-03)
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
9050ccacba
Adds pgvector support to the postgres storage adapter without affecting
local or standalone tiers:

- `StorageConfig` postgres variant gains optional `enableVector: boolean`
- `PostgresAdapter.migrate()` runs `CREATE EXTENSION IF NOT EXISTS vector`
  via `db.execute(sql)` BEFORE migrations when `enableVector === true`
  (so vector-typed columns are creatable in the same migration pass).
  Idempotent — safe to re-run on already-installed extension.
- `vector` custom type in `@mosaicstack/db/schema` is now exported so
  downstream packages can declare vector columns in their own schemas.
- `DEFAULT_FEDERATED_CONFIG.storage.enableVector = true` so the federated
  default flows through the adapter.
- `detectFromEnv()` restructured: `MOSAIC_STORAGE_TIER` is now checked
  BEFORE the `DATABASE_URL` guard so `MOSAIC_STORAGE_TIER=federated`
  alone returns the federated default config instead of silently
  misrouting to local. Same applies to `=standalone`. With
  `DATABASE_URL` set, the URL is honored and `enableVector` is preserved
  on federated.
- `detectFromEnv` is now exported for direct test access.

Tests:
- 4 PostgresAdapter unit tests cover: extension SQL issued when enabled,
  not issued when disabled or unset, ordering (extension before
  runMigrations). Assertion uses Drizzle's `toSQL()` with documented
  fallback for older versions.
- 4 detectFromEnv tests cover the four env-var permutations.
- 1 federated default constant test.

No behavior change for local or standalone tier deployments.

Refs #460

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
jason.woltje merged commit 58169f9979 into main 2026-04-19 23:42:19 +00:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mosaicstack/stack#472