1/**
2 * Adds the nullable `provider_instance_id` routing column to
3 * `provider_session_runtime`.
4 *
5 * Slice D of the provider-array refactor splits "driver kind" from
6 * "configured instance". Existing rows have only the driver name in
7 * `provider_name`; new rows additionally carry the user-defined instance
8 * routing key. The column remains nullable so legacy rows can still decode;
9 * the persistence boundary is responsible for materializing a concrete
10 * instance id before any hot routing path sees the binding.
11 *
12 * The column is nullable on purpose — backfilling it during the migration
13 * would require knowing which configured instance "owned" each historical
14 * session, and that mapping is ambiguous when the user later configures
15 * multiple instances of the same driver. Keeping that compatibility at the
16 * persistence boundary keeps the fallback out of active routing code.
17 */
18import * as SqlClient from "effect/sql/SqlClient";
19import * as Effect from "effect/Effect";
20
21export default Effect.gen(function* () {
22 const sql = yield* SqlClient.SqlClient;
23
24 const columns = yield* sql<{ readonly name: string }>`
25 PRAGMA table_info(provider_session_runtime)
26 `;
27 if (!columns.some((column) => column.name === "provider_instance_id")) {
28 yield* sql`
29 ALTER TABLE provider_session_runtime
30 ADD COLUMN provider_instance_id TEXT
31 `;
32 }
33
34 yield* sql`
35 CREATE INDEX IF NOT EXISTS idx_provider_session_runtime_instance
36 ON provider_session_runtime(provider_instance_id)
37 `;
38});