@opengeni/db 0.6.1 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/dist/{chunk-OGCE6O2X.js → chunk-7LDU7F5P.js} +31 -3
  2. package/dist/chunk-7LDU7F5P.js.map +1 -0
  3. package/dist/chunk-B22X3IEZ.js +2634 -0
  4. package/dist/chunk-B22X3IEZ.js.map +1 -0
  5. package/dist/{chunk-57MLICFR.js → chunk-YFQ7SGE4.js} +18 -6
  6. package/dist/chunk-YFQ7SGE4.js.map +1 -0
  7. package/dist/index.d.ts +2 -2
  8. package/dist/index.js +16571 -5018
  9. package/dist/index.js.map +1 -1
  10. package/dist/migrate.js +1 -1
  11. package/dist/provision-roles.d.ts +2121 -248
  12. package/dist/provision-roles.js +1 -1
  13. package/dist/{schema-BUbuMteO.d.ts → schema-BN5mB9xZ.d.ts} +8716 -3432
  14. package/dist/schema.d.ts +1 -1
  15. package/dist/schema.js +43 -5
  16. package/drizzle/0044_reap_dead_turn_holders.sql +104 -0
  17. package/drizzle/0045_workspace_captures.sql +83 -0
  18. package/drizzle/0045_workspace_memory_v1.sql +71 -0
  19. package/drizzle/0046_variable_sets_rename.sql +56 -0
  20. package/drizzle/0047_rigs.sql +151 -0
  21. package/drizzle/0048_rig_runtime.sql +9 -0
  22. package/drizzle/0049_enrollment_went_offline.sql +28 -0
  23. package/drizzle/0050_enrollment_op_stream.sql +1 -0
  24. package/drizzle/0051_codex_pin_source.sql +48 -0
  25. package/drizzle/0052_file_upload_cleanup.sql +91 -0
  26. package/drizzle/0053_codex_credential_leases.sql +230 -0
  27. package/drizzle/0054_session_pins.sql +85 -0
  28. package/drizzle/0055_session_list_snapshots.sql +73 -0
  29. package/drizzle/0056_workspace_model_policies.sql +48 -0
  30. package/drizzle/0057_durable_queue_control.sql +536 -0
  31. package/drizzle/0058_turn_admission_usage_enrollment.sql +158 -0
  32. package/drizzle/0059_workspace_pause_control_kind.sql +12 -0
  33. package/drizzle/0060_session_system_update_deferral.sql +10 -0
  34. package/drizzle/0061_session_workflow_wake_outbox.sql +157 -0
  35. package/drizzle/0062_session_list_snapshot_reaper.sql +48 -0
  36. package/drizzle/0063_session_control_mega_foundation.sql +1324 -0
  37. package/package.json +13 -13
  38. package/src/codex-token-resolver.ts +58 -23
  39. package/src/connection-token-resolver.ts +146 -57
  40. package/src/environment-crypto.ts +5 -1
  41. package/src/event-payload-sanitizer.ts +29 -1
  42. package/src/index.ts +20990 -6465
  43. package/src/memory-domain.ts +218 -0
  44. package/src/migrate.ts +58 -3
  45. package/src/provision-roles.ts +46 -17
  46. package/src/schema.ts +2888 -1121
  47. package/src/session-control.ts +1759 -0
  48. package/src/session-queue-commands.ts +1753 -0
  49. package/src/session-tool-call-settlement.ts +269 -0
  50. package/dist/chunk-57MLICFR.js.map +0 -1
  51. package/dist/chunk-OGCE6O2X.js.map +0 -1
  52. package/dist/chunk-ZIUCA2IO.js +0 -1268
  53. package/dist/chunk-ZIUCA2IO.js.map +0 -1
@@ -4,12 +4,38 @@ import { dirname, join } from "path";
4
4
  import { fileURLToPath } from "url";
5
5
  import postgres from "postgres";
6
6
  var DEFAULT_DATABASE_URL = "postgres://opengeni:opengeni@127.0.0.1:5432/opengeni";
7
+ var concurrentIndexDirective = /^-- opengeni:concurrent-index lock-timeout=(\d+(?:ms|s|min))$/;
7
8
  function assertIdentifier(name, value) {
8
9
  if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(value)) {
9
10
  throw new Error(`${name} is not a valid Postgres identifier: ${value}`);
10
11
  }
11
12
  return value;
12
13
  }
14
+ async function executeMigrationFile(sql, file, sqlText) {
15
+ const [firstLine = "", ...remainingLines] = sqlText.replaceAll("\r\n", "\n").split("\n");
16
+ const directive = concurrentIndexDirective.exec(firstLine.trim());
17
+ if (!directive) {
18
+ if (firstLine.trim().startsWith("-- opengeni:")) {
19
+ throw new Error(`Unsupported OpenGeni migration directive in ${file}`);
20
+ }
21
+ await sql.unsafe(sqlText);
22
+ return;
23
+ }
24
+ const lockTimeout = directive[1];
25
+ const statement = remainingLines.join("\n").trim();
26
+ const withoutTrailingSemicolon = statement.endsWith(";") ? statement.slice(0, -1).trimEnd() : statement;
27
+ if (!/^CREATE\s+(?:UNIQUE\s+)?INDEX\s+CONCURRENTLY\b/is.test(withoutTrailingSemicolon) || withoutTrailingSemicolon.includes(";")) {
28
+ throw new Error(
29
+ `${file}: opengeni:concurrent-index requires exactly one CREATE [UNIQUE] INDEX CONCURRENTLY statement`
30
+ );
31
+ }
32
+ await sql`select set_config('lock_timeout', ${lockTimeout}, false)`;
33
+ try {
34
+ await sql.unsafe(statement);
35
+ } finally {
36
+ await sql`select set_config('lock_timeout', '0', false)`;
37
+ }
38
+ }
13
39
  async function migrate(databaseUrl = process.env.OPENGENI_MIGRATIONS_DATABASE_URL ?? process.env.OPENGENI_DATABASE_URL ?? DEFAULT_DATABASE_URL, schema = process.env.OPENGENI_DB_SCHEMA?.trim() || void 0) {
14
40
  const migrationsDir = join(dirname(fileURLToPath(import.meta.url)), "../drizzle");
15
41
  const files = (await readdir(migrationsDir)).filter((file) => file.endsWith(".sql")).sort();
@@ -22,7 +48,9 @@ async function migrate(databaseUrl = process.env.OPENGENI_MIGRATIONS_DATABASE_UR
22
48
  await sql.unsafe(`CREATE SCHEMA IF NOT EXISTS "opengeni_private"`);
23
49
  await sql.unsafe(`SET search_path = "${schema}", "opengeni_private", "public"`);
24
50
  }
25
- await sql.unsafe(`CREATE TABLE IF NOT EXISTS "schema_migrations" ("name" text PRIMARY KEY, "applied_at" timestamptz NOT NULL DEFAULT now())`);
51
+ await sql.unsafe(
52
+ `CREATE TABLE IF NOT EXISTS "schema_migrations" ("name" text PRIMARY KEY, "applied_at" timestamptz NOT NULL DEFAULT now())`
53
+ );
26
54
  const appliedRows = await sql`SELECT "name" FROM "schema_migrations"`;
27
55
  const applied = new Set(appliedRows.map((row) => row.name));
28
56
  for (const file of files) {
@@ -30,7 +58,7 @@ async function migrate(databaseUrl = process.env.OPENGENI_MIGRATIONS_DATABASE_UR
30
58
  continue;
31
59
  }
32
60
  const sqlText = await readFile(join(migrationsDir, file), "utf8");
33
- await sql.unsafe(sqlText);
61
+ await executeMigrationFile(sql, file, sqlText);
34
62
  await sql`INSERT INTO "schema_migrations" ("name") VALUES (${file}) ON CONFLICT DO NOTHING`;
35
63
  }
36
64
  } finally {
@@ -49,4 +77,4 @@ export {
49
77
  migrate,
50
78
  runMigrations
51
79
  };
52
- //# sourceMappingURL=chunk-OGCE6O2X.js.map
80
+ //# sourceMappingURL=chunk-7LDU7F5P.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/migrate.ts"],"sourcesContent":["import { readdir, readFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport postgres from \"postgres\";\n\nconst DEFAULT_DATABASE_URL = \"postgres://opengeni:opengeni@127.0.0.1:5432/opengeni\";\nconst concurrentIndexDirective = /^-- opengeni:concurrent-index lock-timeout=(\\d+(?:ms|s|min))$/;\n\n/** A bare Postgres identifier (schema/role name) safe to interpolate into DDL. */\nfunction assertIdentifier(name: string, value: string): string {\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(value)) {\n throw new Error(`${name} is not a valid Postgres identifier: ${value}`);\n }\n return value;\n}\n\n/**\n * Most migration files intentionally execute as one implicit transaction.\n * PostgreSQL forbids CREATE INDEX CONCURRENTLY there, so a migration may opt\n * into one narrowly validated transactionless statement with:\n *\n * -- opengeni:concurrent-index lock-timeout=5s\n * CREATE [UNIQUE] INDEX CONCURRENTLY ...;\n *\n * The directive is deliberately not a generic \"no transaction\" escape hatch:\n * only one concurrent-index statement is accepted, and lock acquisition is\n * always bounded. This keeps additive large-table indexes online without making\n * arbitrary partially-applied migration scripts possible.\n */\nasync function executeMigrationFile(\n sql: postgres.Sql,\n file: string,\n sqlText: string,\n): Promise<void> {\n const [firstLine = \"\", ...remainingLines] = sqlText.replaceAll(\"\\r\\n\", \"\\n\").split(\"\\n\");\n const directive = concurrentIndexDirective.exec(firstLine.trim());\n if (!directive) {\n if (firstLine.trim().startsWith(\"-- opengeni:\")) {\n throw new Error(`Unsupported OpenGeni migration directive in ${file}`);\n }\n await sql.unsafe(sqlText);\n return;\n }\n\n const lockTimeout = directive[1]!;\n const statement = remainingLines.join(\"\\n\").trim();\n const withoutTrailingSemicolon = statement.endsWith(\";\")\n ? statement.slice(0, -1).trimEnd()\n : statement;\n if (\n !/^CREATE\\s+(?:UNIQUE\\s+)?INDEX\\s+CONCURRENTLY\\b/is.test(withoutTrailingSemicolon) ||\n withoutTrailingSemicolon.includes(\";\")\n ) {\n throw new Error(\n `${file}: opengeni:concurrent-index requires exactly one CREATE [UNIQUE] INDEX CONCURRENTLY statement`,\n );\n }\n\n await sql`select set_config('lock_timeout', ${lockTimeout}, false)`;\n try {\n await sql.unsafe(statement);\n } finally {\n await sql`select set_config('lock_timeout', '0', false)`;\n }\n}\n\n/**\n * Apply the OpenGeni SQL migration chain.\n *\n * STANDALONE (default, unchanged): `migrate()` / `migrate(databaseUrl)` runs the\n * whole chain with NO search_path manipulation, so every unqualified\n * table/index/policy lands in the server default schema (`public`). This is the\n * byte-for-byte historical behavior — the migration test suite calls\n * `migrate(DB_URL)` and is unaffected.\n *\n * EMBEDDED (Step I, §7.8 runtime/SDK half): pass a `schema` (or set\n * `OPENGENI_DB_SCHEMA`). The migrate session then `CREATE SCHEMA IF NOT EXISTS`\n * for both `<schema>` and `opengeni_private`, and sets\n * `search_path = \"<schema>\", \"opengeni_private\", \"public\"`, so EVERY unqualified\n * DDL statement lands in the dedicated schema with NO per-statement SQL rewrite\n * (the SPIKE-1 F1 result). Two things make this work and stay idempotent:\n * 1. The policy-existence guards in the migration SQL use `current_schema()`\n * (not a hardcoded `'public'`) — so a re-run finds the policy it already\n * created in `<schema>` and DROP/CREATEs idempotently instead of failing\n * with \"policy already exists\". (This guard substitution is the migrate-\n * time enabler for the runtime search_path approach; without it the SDK\n * entry point silently fails on re-run — the Fork-6 hazard.)\n * 2. `public` stays LAST on the path so `gen_random_uuid()` (pgcrypto) and the\n * `vector` type — both installed into `public` by 0000 — still resolve. The\n * `opengeni_private.*` helpers are always called with an absolute prefix.\n *\n * `OPENGENI_DB_SCHEMA` defaults UNSET → `public` → standalone, so the default\n * binding never regresses.\n */\nexport async function migrate(\n databaseUrl = process.env.OPENGENI_MIGRATIONS_DATABASE_URL ??\n process.env.OPENGENI_DATABASE_URL ??\n DEFAULT_DATABASE_URL,\n schema: string | undefined = process.env.OPENGENI_DB_SCHEMA?.trim() || undefined,\n): Promise<void> {\n const migrationsDir = join(dirname(fileURLToPath(import.meta.url)), \"../drizzle\");\n const files = (await readdir(migrationsDir)).filter((file) => file.endsWith(\".sql\")).sort();\n const sql = postgres(databaseUrl, { max: 1 });\n try {\n // Serialize concurrent migrate() runs; the session-level lock is released\n // when the connection closes.\n await sql`SELECT pg_advisory_lock(727458)`;\n if (schema) {\n assertIdentifier(\"OPENGENI_DB_SCHEMA\", schema);\n await sql.unsafe(`CREATE SCHEMA IF NOT EXISTS \"${schema}\"`);\n // opengeni_private is also created by 0001 with an absolute prefix, but the\n // session search_path must already resolve it for the policy predicates\n // and the SECURITY DEFINER functions that inherit the caller's path.\n await sql.unsafe(`CREATE SCHEMA IF NOT EXISTS \"opengeni_private\"`);\n await sql.unsafe(`SET search_path = \"${schema}\", \"opengeni_private\", \"public\"`);\n }\n await sql.unsafe(\n `CREATE TABLE IF NOT EXISTS \"schema_migrations\" (\"name\" text PRIMARY KEY, \"applied_at\" timestamptz NOT NULL DEFAULT now())`,\n );\n const appliedRows = await sql`SELECT \"name\" FROM \"schema_migrations\"`;\n const applied = new Set(appliedRows.map((row) => row.name as string));\n for (const file of files) {\n if (applied.has(file)) {\n continue;\n }\n const sqlText = await readFile(join(migrationsDir, file), \"utf8\");\n await executeMigrationFile(sql, file, sqlText);\n await sql`INSERT INTO \"schema_migrations\" (\"name\") VALUES (${file}) ON CONFLICT DO NOTHING`;\n }\n } finally {\n await sql.end();\n }\n}\n\n/**\n * SDK entry point (Step I): run the migration chain over a host-supplied admin\n * connection string against an explicit target schema. This is the embedded\n * topology's named entry — a host calls `runMigrations(adminConnection,\n * targetSchema)` from its own provisioning code instead of relying on env vars.\n * `targetSchema` undefined → `public` → standalone behavior. Thin wrapper over\n * `migrate` so there is one migration engine.\n */\nexport async function runMigrations(adminConnection: string, targetSchema?: string): Promise<void> {\n await migrate(adminConnection, targetSchema);\n}\n\nif (import.meta.main) {\n await migrate();\n console.log(\"Applied Drizzle SQL migrations.\");\n}\n"],"mappings":";AAAA,SAAS,SAAS,gBAAgB;AAClC,SAAS,SAAS,YAAY;AAC9B,SAAS,qBAAqB;AAC9B,OAAO,cAAc;AAErB,IAAM,uBAAuB;AAC7B,IAAM,2BAA2B;AAGjC,SAAS,iBAAiB,MAAc,OAAuB;AAC7D,MAAI,CAAC,2BAA2B,KAAK,KAAK,GAAG;AAC3C,UAAM,IAAI,MAAM,GAAG,IAAI,wCAAwC,KAAK,EAAE;AAAA,EACxE;AACA,SAAO;AACT;AAeA,eAAe,qBACb,KACA,MACA,SACe;AACf,QAAM,CAAC,YAAY,IAAI,GAAG,cAAc,IAAI,QAAQ,WAAW,QAAQ,IAAI,EAAE,MAAM,IAAI;AACvF,QAAM,YAAY,yBAAyB,KAAK,UAAU,KAAK,CAAC;AAChE,MAAI,CAAC,WAAW;AACd,QAAI,UAAU,KAAK,EAAE,WAAW,cAAc,GAAG;AAC/C,YAAM,IAAI,MAAM,+CAA+C,IAAI,EAAE;AAAA,IACvE;AACA,UAAM,IAAI,OAAO,OAAO;AACxB;AAAA,EACF;AAEA,QAAM,cAAc,UAAU,CAAC;AAC/B,QAAM,YAAY,eAAe,KAAK,IAAI,EAAE,KAAK;AACjD,QAAM,2BAA2B,UAAU,SAAS,GAAG,IACnD,UAAU,MAAM,GAAG,EAAE,EAAE,QAAQ,IAC/B;AACJ,MACE,CAAC,mDAAmD,KAAK,wBAAwB,KACjF,yBAAyB,SAAS,GAAG,GACrC;AACA,UAAM,IAAI;AAAA,MACR,GAAG,IAAI;AAAA,IACT;AAAA,EACF;AAEA,QAAM,wCAAwC,WAAW;AACzD,MAAI;AACF,UAAM,IAAI,OAAO,SAAS;AAAA,EAC5B,UAAE;AACA,UAAM;AAAA,EACR;AACF;AA8BA,eAAsB,QACpB,cAAc,QAAQ,IAAI,oCACxB,QAAQ,IAAI,yBACZ,sBACF,SAA6B,QAAQ,IAAI,oBAAoB,KAAK,KAAK,QACxD;AACf,QAAM,gBAAgB,KAAK,QAAQ,cAAc,YAAY,GAAG,CAAC,GAAG,YAAY;AAChF,QAAM,SAAS,MAAM,QAAQ,aAAa,GAAG,OAAO,CAAC,SAAS,KAAK,SAAS,MAAM,CAAC,EAAE,KAAK;AAC1F,QAAM,MAAM,SAAS,aAAa,EAAE,KAAK,EAAE,CAAC;AAC5C,MAAI;AAGF,UAAM;AACN,QAAI,QAAQ;AACV,uBAAiB,sBAAsB,MAAM;AAC7C,YAAM,IAAI,OAAO,gCAAgC,MAAM,GAAG;AAI1D,YAAM,IAAI,OAAO,gDAAgD;AACjE,YAAM,IAAI,OAAO,sBAAsB,MAAM,iCAAiC;AAAA,IAChF;AACA,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AACA,UAAM,cAAc,MAAM;AAC1B,UAAM,UAAU,IAAI,IAAI,YAAY,IAAI,CAAC,QAAQ,IAAI,IAAc,CAAC;AACpE,eAAW,QAAQ,OAAO;AACxB,UAAI,QAAQ,IAAI,IAAI,GAAG;AACrB;AAAA,MACF;AACA,YAAM,UAAU,MAAM,SAAS,KAAK,eAAe,IAAI,GAAG,MAAM;AAChE,YAAM,qBAAqB,KAAK,MAAM,OAAO;AAC7C,YAAM,uDAAuD,IAAI;AAAA,IACnE;AAAA,EACF,UAAE;AACA,UAAM,IAAI,IAAI;AAAA,EAChB;AACF;AAUA,eAAsB,cAAc,iBAAyB,cAAsC;AACjG,QAAM,QAAQ,iBAAiB,YAAY;AAC7C;AAEA,IAAI,YAAY,MAAM;AACpB,QAAM,QAAQ;AACd,UAAQ,IAAI,iCAAiC;AAC/C;","names":[]}