# Storage Migration Notes (PR #262 — sdk-refactor-inplace) ## What was done ### 1. DBSchema alignment with better-auth - Vendored better-auth's `BetterAuthPluginDBSchema` pattern into `storage-core/src/schema.ts` - Made `modelName` optional (falls back to the key), renamed `disableMigrations` → `disableMigration`, dropped `order` - Removed explicit `modelName` from all plugin schemas (core-schema, openapi, mcp, graphql, google-discovery, workos-vault) — keys already match table names ### 2. @executor-js/cli package (packages/core/cli/) - Mirrors better-auth's CLI approach: load config → collect plugin schemas → generate drizzle TS - `executor generate --config ./executor.config.ts --output ./src/services/executor-schema.ts` - Generator ported from better-auth's drizzle generator, adapted for our DBSchema - Handles pg/sqlite/mysql dialects, indexes, references, relations, default values - Uses jiti for config loading (supports TS configs) ### 3. apps/cloud wired up - `executor.config.ts` defines plugins with stub credentials (only used for schema shape) - `drizzle.config.ts` points at both `schema.ts` (cloud tables) and `executor-schema.ts` (executor tables) - Fresh `drizzle/0000_initial.sql` with all tables (cloud + core + plugin + blob), indexes, FKs ### 4. apps/local wired up - `executor.config.ts` defines plugins + dialect sqlite - `drizzle.config.ts` for drizzle-kit generate/push - Generated `executor-schema.ts` with all sqlite tables + blob table - `drizzle/0000_*.sql` initial migration - At startup: `migrate(db, { migrationsFolder })` from `drizzle-orm/bun-sqlite/migrator` applies pending migrations before constructing the adapter ### 5. Adapter DDL removed - `makeSqliteAdapter` and `makePostgresAdapter` no longer run DDL — they return `DBAdapter` directly (not `Effect.Effect`) - `makeSqliteBlobStore` and `makePostgresBlobStore` no longer run DDL — they return `BlobStore` directly - `buildCreateTableStatements` deleted from `storage-file/compile.ts` - Blob table included in both local and cloud generated schemas — managed by drizzle-kit alongside all other tables ## Migration path — what's next ### The plan: re-derive sources from executor.jsonc The `@executor-js/config` package already maintains `executor.jsonc` as a source of truth for source configurations. The `config-store.ts` decorator intercepts `putSource`/`removeSource` on each plugin and mirrors to this file. So for existing users, `executor.jsonc` already has everything. ### Local app migration 1. On first run, `migrate()` creates all tables from the initial migration 2. Add a **sync-from-config step** after executor creation: - `loadConfig(configPath)` reads `executor.jsonc` - For each source, call the plugin's add method (`executor.openapi.addSpec()`, `executor.mcp.addSource()`, etc.) - This re-fetches specs, re-parses tools, populates typed tables 3. Secrets survive untouched — they live in keychain/1password/file-secrets, not in the DB. The `secret` routing table gets re-populated when sources are added. ### What won't survive (acceptable losses) - Tool invocation history / blobs (old KV format) - OAuth sessions (ephemeral, users re-auth) - Stale source state (re-fetching is actually a benefit) ### Cloud migration - Only ~2 users, just drop old tables and re-add manually - Or write a one-off SQL migration ## Key files | File | Role | | --------------------------------------------- | ----------------------------------------- | | `packages/core/cli/src/commands/generate.ts` | CLI generate command | | `packages/core/cli/src/generators/drizzle.ts` | Drizzle schema generator | | `packages/core/sdk/src/config.ts` | `defineExecutorConfig` helper | | `packages/core/config/src/schema.ts` | `executor.jsonc` schema | | `packages/core/config/src/config-store.ts` | Plugin store → config file decorator | | `packages/core/config/src/load.ts` | Config loading | | `apps/cloud/executor.config.ts` | Cloud config for CLI | | `apps/cloud/src/services/executor-schema.ts` | Generated drizzle schema | | `apps/cloud/drizzle/0000_*.sql` | Fresh migration | | `apps/local/executor.config.ts` | Local config for CLI | | `apps/local/src/server/executor-schema.ts` | Generated drizzle schema | | `apps/local/drizzle/0000_*.sql` | Fresh migration | | `apps/local/src/server/executor.ts` | Local executor bootstrap with `migrate()` |