@opengeni/db 3.1.0-canary.0 → 3.4.0-canary.0

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 (98) hide show
  1. package/dist/canonical-human-identities.js +3 -3
  2. package/dist/{chunk-SIBYBA2D.js → chunk-6DPJA36C.js} +30 -11
  3. package/dist/chunk-6DPJA36C.js.map +1 -0
  4. package/dist/{chunk-PR2WMLOQ.js → chunk-C2AFP7SB.js} +195 -6
  5. package/dist/chunk-C2AFP7SB.js.map +1 -0
  6. package/dist/{chunk-SCPUJS53.js → chunk-H7MXYG7R.js} +27 -15
  7. package/dist/chunk-H7MXYG7R.js.map +1 -0
  8. package/dist/{chunk-NJVZPWXY.js → chunk-HY3F5Q4E.js} +3 -3
  9. package/dist/{chunk-ZZ5LJEFX.js → chunk-O6FTELKH.js} +3 -3
  10. package/dist/{chunk-OF5OBB76.js → chunk-PYMY3AJW.js} +379 -12
  11. package/dist/chunk-PYMY3AJW.js.map +1 -0
  12. package/dist/{chunk-TIKF3KTI.js → chunk-TRBOWUG3.js} +107 -6
  13. package/dist/chunk-TRBOWUG3.js.map +1 -0
  14. package/dist/{chunk-EULAN2NP.js → chunk-V3TRUXFJ.js} +2 -2
  15. package/dist/{chunk-NMUBV7Z5.js → chunk-ZWRIPCTR.js} +2 -2
  16. package/dist/connection-tenancy-backfill.d.ts +44 -0
  17. package/dist/database.d.ts +4 -4
  18. package/dist/editable-artifact-durable-export.js +2 -2
  19. package/dist/editable-artifacts.js +3 -3
  20. package/dist/governed-learning-activation.d.ts +16 -0
  21. package/dist/index.d.ts +120 -8
  22. package/dist/index.js +3927 -1433
  23. package/dist/index.js.map +1 -1
  24. package/dist/insights-model-bundle.d.ts +30 -0
  25. package/dist/insights-usage-bundle.d.ts +32 -0
  26. package/dist/insights.d.ts +10 -2
  27. package/dist/lossless-json.d.ts +1 -1
  28. package/dist/managed-user-setup.d.ts +82 -0
  29. package/dist/memory-domain.d.ts +2 -2
  30. package/dist/migrate.d.ts +3 -1
  31. package/dist/migrate.js +1 -1
  32. package/dist/new-session-drafts.d.ts +4 -4
  33. package/dist/organization-membership-lifecycle.d.ts +60 -1
  34. package/dist/pr-review.d.ts +44 -3
  35. package/dist/provision-roles.js +1 -1
  36. package/dist/runtime-posture.d.ts +19 -7
  37. package/dist/schema.d.ts +839 -101
  38. package/dist/schema.js +9 -1
  39. package/dist/session-background-commands.js +3 -3
  40. package/dist/session-queue-commands.d.ts +2 -0
  41. package/dist/session-tenancy.d.ts +12 -1
  42. package/dist/session-tenancy.js +3 -3
  43. package/dist/slack-routing.d.ts +115 -0
  44. package/dist/slack-user-link-access.d.ts +27 -0
  45. package/dist/video-generation.js +3 -3
  46. package/drizzle/0342_slack_route_prompt_single_pending.sql +32 -0
  47. package/drizzle/0343_personal_document_force_rls_lock_repair.sql +146 -0
  48. package/drizzle/0344_private_session_visibility_transition_gate.sql +85 -0
  49. package/drizzle/0345_tenant_scoped_session_tenancy_fence.sql +2839 -0
  50. package/drizzle/0346_document_migration_audit_surface.sql +454 -0
  51. package/drizzle/0347_connection_authority_convergence_evidence.sql +396 -0
  52. package/drizzle/0348_named_signup_and_user_setup.sql +838 -0
  53. package/drizzle/0349_greenfield_session_tenancy_activation.sql +792 -0
  54. package/drizzle/0350_organization_shared_workspace_administration.sql +889 -0
  55. package/drizzle/0351_organization_user_setup_delivery.sql +978 -0
  56. package/drizzle/0352_session_variable_set_attachments.sql +1661 -0
  57. package/drizzle/0353_automatic_session_title_policy_fence.sql +476 -0
  58. package/drizzle/0354_automatic_session_title_quarantine_index.sql +9 -0
  59. package/drizzle/0355_automatic_session_title_quarantine.sql +92 -0
  60. package/drizzle/0356_set_based_insights_session_visibility.sql +237 -0
  61. package/drizzle/0357_rig_platform_base_only.sql +44 -0
  62. package/drizzle/0358_pr_review_managed_github_app.sql +108 -0
  63. package/drizzle/0359_insights_force_rls_read_capability.sql +936 -0
  64. package/drizzle/0360_organization_identity_confirmation_prompt.sql +103 -0
  65. package/drizzle/0361_remember_knowledge_memory_materialization.sql +249 -0
  66. package/package.json +6 -6
  67. package/src/connection-tenancy-backfill.ts +86 -0
  68. package/src/database.ts +24 -8
  69. package/src/governed-learning-activation.ts +74 -2
  70. package/src/index.ts +904 -94
  71. package/src/insights-model-bundle.ts +681 -0
  72. package/src/insights-usage-bundle.ts +240 -0
  73. package/src/insights.ts +265 -152
  74. package/src/lossless-json.ts +2 -1
  75. package/src/managed-user-setup.ts +316 -0
  76. package/src/memory-domain.ts +3 -3
  77. package/src/migrate.ts +38 -14
  78. package/src/new-session-drafts.ts +22 -15
  79. package/src/organization-membership-lifecycle.ts +268 -6
  80. package/src/pr-review.ts +449 -6
  81. package/src/provision-roles.ts +120 -0
  82. package/src/runtime-posture.ts +278 -5
  83. package/src/schema.ts +223 -4
  84. package/src/session-queue-commands.ts +4 -1
  85. package/src/session-realtime-context.ts +1 -3
  86. package/src/session-realtime-ledger.ts +6 -3
  87. package/src/session-tenancy.ts +127 -2
  88. package/src/slack-routing.ts +399 -1
  89. package/src/slack-user-link-access.ts +121 -10
  90. package/dist/chunk-OF5OBB76.js.map +0 -1
  91. package/dist/chunk-PR2WMLOQ.js.map +0 -1
  92. package/dist/chunk-SCPUJS53.js.map +0 -1
  93. package/dist/chunk-SIBYBA2D.js.map +0 -1
  94. package/dist/chunk-TIKF3KTI.js.map +0 -1
  95. /package/dist/{chunk-NJVZPWXY.js.map → chunk-HY3F5Q4E.js.map} +0 -0
  96. /package/dist/{chunk-ZZ5LJEFX.js.map → chunk-O6FTELKH.js.map} +0 -0
  97. /package/dist/{chunk-EULAN2NP.js.map → chunk-V3TRUXFJ.js.map} +0 -0
  98. /package/dist/{chunk-NMUBV7Z5.js.map → chunk-ZWRIPCTR.js.map} +0 -0
@@ -9,9 +9,9 @@ import {
9
9
  getCanonicalHumanIdentityProjection,
10
10
  synchronizeCanonicalHumanLoginBindings,
11
11
  validateCanonicalHumanSession
12
- } from "./chunk-EULAN2NP.js";
13
- import "./chunk-SCPUJS53.js";
14
- import "./chunk-PR2WMLOQ.js";
12
+ } from "./chunk-V3TRUXFJ.js";
13
+ import "./chunk-H7MXYG7R.js";
14
+ import "./chunk-C2AFP7SB.js";
15
15
  import "./chunk-PZ5AY32C.js";
16
16
  export {
17
17
  CanonicalHumanIdentityAuthorityError,
@@ -7,10 +7,7 @@ var DEFAULT_DATABASE_URL = "postgres://opengeni:opengeni@127.0.0.1:5432/opengeni
7
7
  var DEFAULT_MAX_NESTED_AGENT_DEPTH = 3;
8
8
  var MAX_NESTED_AGENT_DEPTH = 2147483647;
9
9
  var DEFAULT_APPLICATION_DATABASE_ROLE = "opengeni_app";
10
- var GOAL_REVISION_CUTOVER_MIGRATION = "0257_goal_revision_decisions_and_root_constraints.sql";
11
- var ATOMIC_PERSONAL_RESOURCE_CUTOVER_MIGRATION = "0306_atomic_personal_resource_attachments.sql";
12
- var UNREGISTERED_INVITATION_CUTOVER_MIGRATION = "0314_unregistered_organization_invitations.sql";
13
- var ATOMIC_CONNECTED_MACHINE_CUTOVER_MIGRATION = "0338_atomic_connected_machine_attachments.sql";
10
+ var MIGRATION_APPLICATION_ROLES_SETTING = "opengeni.migration_application_roles";
14
11
  var MAX_MIGRATION_APPLICATION_ROLES = 16;
15
12
  var batchedBackfillDirective = /^-- opengeni:batched-backfill batch-size=(\d+) lock-timeout=(\d+(?:ms|s|min)) statement-timeout=(\d+(?:ms|s|min))$/;
16
13
  var concurrentIndexDirective = /^-- opengeni:concurrent-index lock-timeout=(\d+(?:ms|s|min))$/;
@@ -94,7 +91,16 @@ async function executeMigrationFile(sql, file, sqlText) {
94
91
  await sql`select set_config('statement_timeout', ${batchedBackfill.statementTimeout}, false)`;
95
92
  try {
96
93
  for (; ; ) {
97
- const result = await sql.unsafe(batchedBackfill.statement);
94
+ const result = await sql.begin(async (transaction) => {
95
+ await transaction`select
96
+ pg_catalog.set_config('opengeni.sandbox_recovery_protocol_v2', '1', true),
97
+ pg_catalog.set_config(
98
+ 'opengeni.session_variable_set_attachments_v1',
99
+ '1',
100
+ true
101
+ )`;
102
+ return await transaction.unsafe(batchedBackfill.statement);
103
+ });
98
104
  if (result.length === 0) break;
99
105
  }
100
106
  } finally {
@@ -106,7 +112,9 @@ async function executeMigrationFile(sql, file, sqlText) {
106
112
  const concurrentIndex = parseConcurrentIndexMigration(file, sqlText);
107
113
  if (!concurrentIndex) {
108
114
  await sql.unsafe(
109
- `SELECT pg_catalog.set_config('opengeni.sandbox_recovery_protocol_v2', '1', true);
115
+ `SELECT
116
+ pg_catalog.set_config('opengeni.sandbox_recovery_protocol_v2', '1', true),
117
+ pg_catalog.set_config('opengeni.session_variable_set_attachments_v1', '1', true);
110
118
  ${sqlText}`
111
119
  );
112
120
  return;
@@ -155,7 +163,7 @@ function migrationApplicationRoles(schema, options) {
155
163
  ].filter((role) => Boolean(role) && role !== DEFAULT_APPLICATION_DATABASE_ROLE);
156
164
  if (schema || configuredRuntimeRoles.length > 0) {
157
165
  throw new Error(
158
- "Migration 0257 requires the exact application database roles via MigrationRuntimeOptions.applicationDatabaseRoles or OPENGENI_MIGRATION_APPLICATION_DATABASE_ROLES for dedicated-schema or custom-role deployments"
166
+ "Pending migrations require the exact application database roles via MigrationRuntimeOptions.applicationDatabaseRoles or OPENGENI_MIGRATION_APPLICATION_DATABASE_ROLES for dedicated-schema or custom-role deployments"
159
167
  );
160
168
  }
161
169
  return [DEFAULT_APPLICATION_DATABASE_ROLE];
@@ -214,10 +222,18 @@ async function migrate(databaseUrl = process.env.OPENGENI_MIGRATIONS_DATABASE_UR
214
222
  );
215
223
  const appliedRows = await sql`SELECT "name" FROM "schema_migrations"`;
216
224
  const applied = new Set(appliedRows.map((row) => row.name));
217
- if (!applied.has(GOAL_REVISION_CUTOVER_MIGRATION) || !applied.has(ATOMIC_PERSONAL_RESOURCE_CUTOVER_MIGRATION) || !applied.has(UNREGISTERED_INVITATION_CUTOVER_MIGRATION) || !applied.has(ATOMIC_CONNECTED_MACHINE_CUTOVER_MIGRATION)) {
225
+ const pendingMigrationSources = /* @__PURE__ */ new Map();
226
+ for (const file of files) {
227
+ if (!applied.has(file)) {
228
+ pendingMigrationSources.set(file, await readFile(join(migrationsDir, file), "utf8"));
229
+ }
230
+ }
231
+ if (Array.from(pendingMigrationSources.values()).some(
232
+ (source) => source.includes(MIGRATION_APPLICATION_ROLES_SETTING)
233
+ )) {
218
234
  const applicationRoles = migrationApplicationRoles(schema, runtimeOptions);
219
235
  await sql`select set_config(
220
- 'opengeni.migration_application_roles',
236
+ ${MIGRATION_APPLICATION_ROLES_SETTING},
221
237
  ${JSON.stringify(applicationRoles)},
222
238
  false
223
239
  )`;
@@ -226,7 +242,10 @@ async function migrate(databaseUrl = process.env.OPENGENI_MIGRATIONS_DATABASE_UR
226
242
  if (applied.has(file)) {
227
243
  continue;
228
244
  }
229
- const sqlText = await readFile(join(migrationsDir, file), "utf8");
245
+ const sqlText = pendingMigrationSources.get(file);
246
+ if (sqlText === void 0) {
247
+ throw new Error(`Pending migration source was not loaded: ${file}`);
248
+ }
230
249
  await executeMigrationFile(sql, file, sqlText);
231
250
  await sql`INSERT INTO "schema_migrations" ("name") VALUES (${file}) ON CONFLICT DO NOTHING`;
232
251
  }
@@ -248,4 +267,4 @@ export {
248
267
  migrate,
249
268
  runMigrations
250
269
  };
251
- //# sourceMappingURL=chunk-SIBYBA2D.js.map
270
+ //# sourceMappingURL=chunk-6DPJA36C.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 DEFAULT_MAX_NESTED_AGENT_DEPTH = 3;\nconst MAX_NESTED_AGENT_DEPTH = 2_147_483_647;\nconst DEFAULT_APPLICATION_DATABASE_ROLE = \"opengeni_app\";\nconst MIGRATION_APPLICATION_ROLES_SETTING = \"opengeni.migration_application_roles\";\nconst MAX_MIGRATION_APPLICATION_ROLES = 16;\nconst batchedBackfillDirective =\n /^-- opengeni:batched-backfill batch-size=(\\d+) lock-timeout=(\\d+(?:ms|s|min)) statement-timeout=(\\d+(?:ms|s|min))$/;\nconst concurrentIndexDirective = /^-- opengeni:concurrent-index lock-timeout=(\\d+(?:ms|s|min))$/;\nconst concurrentIndexStatement =\n /^CREATE\\s+(?:UNIQUE\\s+)?INDEX\\s+CONCURRENTLY\\s+(?:(IF\\s+NOT\\s+EXISTS)\\s+)?(?:\"((?:[^\"]|\"\")+)\"|([A-Za-z_][A-Za-z0-9_]*))\\s+ON\\b/is;\nconst governedLegacyConcurrentIndexMigrations = new Set([\n \"0066_session_interruption_attempt_lookup.sql\",\n \"0070_session_event_type_sequence_lookup.sql\",\n \"0071_session_event_monitoring_tail.sql\",\n \"0072_sessions_workspace_created_id_idx.sql\",\n \"0073_sessions_workspace_updated_id_idx.sql\",\n \"0075_sessions_workspace_activity_revision_idx.sql\",\n \"0077_session_attempt_latest_lookup.sql\",\n]);\n\nexport interface ConcurrentIndexMigration {\n indexName: string;\n lockTimeout: string;\n skipWhenValid: boolean;\n statement: string;\n}\n\nexport type MigrationRuntimeOptions = {\n maxNestedAgentDepth?: number;\n /**\n * Exact database login roles that may run an OpenGeni API or worker against\n * this target. Maintenance cutovers use this list to reject a live mixed-\n * version fleet, and rolling ACL migrations use it to preserve old-binary\n * readiness until later role provisioning converges. Dedicated-schema and\n * custom-role deployments must supply it.\n */\n applicationDatabaseRoles?: string[];\n};\n\ntype DeploymentDepthPolicy = {\n maxNestedAgentDepth: number;\n source: \"deployment\" | \"default\";\n};\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 IF NOT EXISTS ...;\n *\n * The directive is deliberately not a generic \"no transaction\" escape hatch:\n * only one idempotent concurrent-index statement is accepted, lock acquisition\n * is always bounded, and an invalid artifact left by a failed concurrent build\n * is removed before retry. Seven governed historical migrations predate the\n * IF NOT EXISTS rule; only those exact filenames may use their immutable bare\n * statements, and the runner makes their retries idempotent by skipping an\n * already-valid index. This keeps additive large-table indexes online without\n * rewriting shipped history or making arbitrary partially-applied migration\n * scripts possible.\n */\nexport function parseConcurrentIndexMigration(\n file: string,\n sqlText: string,\n): ConcurrentIndexMigration | null {\n const lines = sqlText.replaceAll(\"\\r\\n\", \"\\n\").split(\"\\n\");\n const firstLine = lines[0]?.trim() ?? \"\";\n const deploymentPrefixed = /^-- deployment-mode: (?:rolling|maintenance)$/.test(firstLine);\n const directiveIndex = deploymentPrefixed ? 1 : 0;\n const directiveLine = lines[directiveIndex]?.trim() ?? \"\";\n const directive = concurrentIndexDirective.exec(directiveLine);\n if (!directive) {\n if (directiveLine.startsWith(\"-- opengeni:\")) {\n throw new Error(`Unsupported OpenGeni migration directive in ${file}`);\n }\n return null;\n }\n\n const lockTimeout = directive[1]!;\n const statement = lines\n .slice(directiveIndex + 1)\n .join(\"\\n\")\n .trim();\n const withoutTrailingSemicolon = statement.endsWith(\";\")\n ? statement.slice(0, -1).trimEnd()\n : statement;\n const parsedStatement = concurrentIndexStatement.exec(withoutTrailingSemicolon);\n if (!parsedStatement || withoutTrailingSemicolon.includes(\";\")) {\n throw new Error(\n `${file}: opengeni:concurrent-index requires exactly one CREATE [UNIQUE] INDEX CONCURRENTLY IF NOT EXISTS statement with an unqualified index name`,\n );\n }\n const idempotentInSql = parsedStatement[1] !== undefined;\n if (!idempotentInSql && !governedLegacyConcurrentIndexMigrations.has(file)) {\n throw new Error(\n `${file}: opengeni:concurrent-index requires IF NOT EXISTS; bare statements are supported only for governed historical migrations`,\n );\n }\n return {\n indexName: (parsedStatement[2] ?? parsedStatement[3]!).replaceAll('\"\"', '\"'),\n lockTimeout,\n skipWhenValid: !idempotentInSql,\n statement,\n };\n}\n\nfunction parseBatchedBackfillMigration(\n file: string,\n sqlText: string,\n): { batchSize: number; lockTimeout: string; statementTimeout: string; statement: string } | null {\n const lines = sqlText.replaceAll(\"\\r\\n\", \"\\n\").split(\"\\n\");\n const directiveIndex = /^-- deployment-mode: (?:rolling|maintenance)$/.test(\n lines[0]?.trim() ?? \"\",\n )\n ? 1\n : 0;\n const directive = batchedBackfillDirective.exec(lines[directiveIndex]?.trim() ?? \"\");\n if (!directive) return null;\n const statement = lines\n .slice(directiveIndex + 1)\n .filter((line) => !line.trim().startsWith(\"--\"))\n .join(\"\\n\")\n .trim();\n const withoutTrailingSemicolon = statement.endsWith(\";\")\n ? statement.slice(0, -1).trimEnd()\n : statement;\n const batchSize = Number(directive[1]!);\n if (\n !Number.isSafeInteger(batchSize) ||\n batchSize < 1 ||\n batchSize > 10_000 ||\n !/^WITH\\b/is.test(withoutTrailingSemicolon) ||\n !/\\bUPDATE\\b/is.test(withoutTrailingSemicolon) ||\n !/\\bRETURNING\\b/is.test(withoutTrailingSemicolon) ||\n !new RegExp(`\\\\bLIMIT\\\\s+${batchSize}\\\\b`, \"i\").test(withoutTrailingSemicolon) ||\n withoutTrailingSemicolon.includes(\";\")\n ) {\n throw new Error(\n `${file}: opengeni:batched-backfill requires one bounded WITH ... UPDATE ... RETURNING statement whose LIMIT matches batch-size`,\n );\n }\n return {\n batchSize,\n lockTimeout: directive[2]!,\n statementTimeout: directive[3]!,\n statement,\n };\n}\n\nasync function executeMigrationFile(\n sql: postgres.Sql,\n file: string,\n sqlText: string,\n): Promise<void> {\n const batchedBackfill = parseBatchedBackfillMigration(file, sqlText);\n if (batchedBackfill) {\n await sql`select set_config('lock_timeout', ${batchedBackfill.lockTimeout}, false)`;\n await sql`select set_config('statement_timeout', ${batchedBackfill.statementTimeout}, false)`;\n try {\n for (;;) {\n const result = await sql.begin(async (transaction) => {\n await transaction`select\n pg_catalog.set_config('opengeni.sandbox_recovery_protocol_v2', '1', true),\n pg_catalog.set_config(\n 'opengeni.session_variable_set_attachments_v1',\n '1',\n true\n )`;\n return await transaction.unsafe(batchedBackfill.statement);\n });\n if (result.length === 0) break;\n }\n } finally {\n await sql`select set_config('statement_timeout', '0', false)`;\n await sql`select set_config('lock_timeout', '0', false)`;\n }\n return;\n }\n const concurrentIndex = parseConcurrentIndexMigration(file, sqlText);\n if (!concurrentIndex) {\n // Migration SQL is the only writer allowed to cross protocol generations.\n // Keep the authority transaction-local and inside the same PostgreSQL simple\n // query as the migration body: setting it in a prior statement would end\n // that implicit transaction and silently lose the LOCAL value. This also\n // makes a fresh database capable of applying maintenance migration 0138\n // and later migrations capable of crossing the 0352 sessions policy\n // without a process-global PGOPTIONS escape hatch.\n await sql.unsafe(\n `SELECT\n pg_catalog.set_config('opengeni.sandbox_recovery_protocol_v2', '1', true),\n pg_catalog.set_config('opengeni.session_variable_set_attachments_v1', '1', true);\\n${sqlText}`,\n );\n return;\n }\n\n await sql`select set_config('lock_timeout', ${concurrentIndex.lockTimeout}, false)`;\n try {\n const [existing] = await sql<Array<{ valid: boolean; ready: boolean }>>`\n select i.indisvalid as valid, i.indisready as ready\n from pg_catalog.pg_class c\n join pg_catalog.pg_namespace n on n.oid = c.relnamespace\n join pg_catalog.pg_index i on i.indexrelid = c.oid\n where n.nspname = current_schema() and c.relname = ${concurrentIndex.indexName}\n `;\n if (existing && (!existing.valid || !existing.ready)) {\n const quotedIndexName = `\"${concurrentIndex.indexName.replaceAll('\"', '\"\"')}\"`;\n await sql.unsafe(`DROP INDEX CONCURRENTLY ${quotedIndexName}`);\n } else if (existing && concurrentIndex.skipWhenValid) {\n return;\n }\n await sql.unsafe(concurrentIndex.statement);\n } finally {\n await sql`select set_config('lock_timeout', '0', false)`;\n }\n}\n\nfunction deploymentDepthPolicy(\n options: MigrationRuntimeOptions | undefined,\n): DeploymentDepthPolicy {\n const raw =\n options === undefined\n ? process.env.OPENGENI_MAX_NESTED_AGENT_DEPTH?.trim() || undefined\n : options.maxNestedAgentDepth;\n if (raw === undefined) {\n return { maxNestedAgentDepth: DEFAULT_MAX_NESTED_AGENT_DEPTH, source: \"default\" };\n }\n const value = typeof raw === \"number\" ? raw : Number(raw);\n if (\n !Number.isSafeInteger(value) ||\n value < 0 ||\n value > MAX_NESTED_AGENT_DEPTH ||\n (typeof raw === \"string\" && !/^(0|[1-9][0-9]*)$/.test(raw))\n ) {\n throw new Error(\n `OPENGENI_MAX_NESTED_AGENT_DEPTH must be a non-negative 32-bit integer: ${raw}`,\n );\n }\n return { maxNestedAgentDepth: value, source: \"deployment\" };\n}\n\nfunction migrationApplicationRoles(\n schema: string | undefined,\n options: MigrationRuntimeOptions | undefined,\n): string[] {\n const configured = options?.applicationDatabaseRoles;\n const environment = process.env.OPENGENI_MIGRATION_APPLICATION_DATABASE_ROLES?.trim();\n const explicit =\n configured !== undefined\n ? configured\n : environment\n ? environment.split(\",\").map((role) => role.trim())\n : undefined;\n\n if (!explicit) {\n const configuredRuntimeRoles = [\n process.env.OPENGENI_APP_DATABASE_USER?.trim(),\n process.env.OPENGENI_RUNTIME_DATABASE_ROLE?.trim(),\n ].filter((role): role is string => Boolean(role) && role !== DEFAULT_APPLICATION_DATABASE_ROLE);\n if (schema || configuredRuntimeRoles.length > 0) {\n throw new Error(\n \"Pending migrations require the exact application database roles via \" +\n \"MigrationRuntimeOptions.applicationDatabaseRoles or \" +\n \"OPENGENI_MIGRATION_APPLICATION_DATABASE_ROLES for dedicated-schema or custom-role deployments\",\n );\n }\n return [DEFAULT_APPLICATION_DATABASE_ROLE];\n }\n\n if (explicit.length < 1 || explicit.length > MAX_MIGRATION_APPLICATION_ROLES) {\n throw new Error(\n `Migration application database roles must contain 1-${MAX_MIGRATION_APPLICATION_ROLES} entries`,\n );\n }\n const normalized = [...new Set(explicit)].sort((left, right) =>\n Buffer.compare(Buffer.from(left, \"utf8\"), Buffer.from(right, \"utf8\")),\n );\n if (\n normalized.length !== explicit.length ||\n normalized.some((role) => role.length === 0 || Buffer.byteLength(role, \"utf8\") > 63)\n ) {\n throw new Error(\n \"Migration application database roles must be unique, non-empty Postgres role names of at most 63 UTF-8 bytes\",\n );\n }\n return normalized;\n}\n\nasync function persistDeploymentDepthPolicy(\n sql: postgres.Sql,\n policy: DeploymentDepthPolicy,\n): Promise<void> {\n const [relation] = await sql<{ exists: boolean }[]>`\n select to_regclass('nested_agent_depth_configuration') is not null as exists\n `;\n if (!relation?.exists) return;\n await sql`\n insert into \"nested_agent_depth_configuration\" (\n \"singleton\", \"max_nested_agent_depth\", \"policy_source\", \"updated_at\"\n ) values (true, ${policy.maxNestedAgentDepth}, ${policy.source}, now())\n on conflict (\"singleton\") do update\n set \"max_nested_agent_depth\" = excluded.\"max_nested_agent_depth\",\n \"policy_source\" = excluded.\"policy_source\",\n \"updated_at\" = now()\n where \"nested_agent_depth_configuration\".\"max_nested_agent_depth\"\n is distinct from excluded.\"max_nested_agent_depth\"\n or \"nested_agent_depth_configuration\".\"policy_source\"\n is distinct from excluded.\"policy_source\"\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 SCHEMA MODE: 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 schema-isolation contract). 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 migration replay 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 * Dedicated-schema callers must also pass the exact API/worker database login\n * identities in `applicationDatabaseRoles`; maintenance cutovers cannot infer\n * host-managed or scoped runtime roles from the admin connection.\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 runtimeOptions?: MigrationRuntimeOptions,\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 depthPolicy = deploymentDepthPolicy(runtimeOptions);\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`select set_config('opengeni.max_nested_agent_depth', ${String(depthPolicy.maxNestedAgentDepth)}, false)`;\n await sql`select set_config('opengeni.nested_agent_depth_policy_source', ${depthPolicy.source}, false)`;\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 const pendingMigrationSources = new Map<string, string>();\n for (const file of files) {\n if (!applied.has(file)) {\n pendingMigrationSources.set(file, await readFile(join(migrationsDir, file), \"utf8\"));\n }\n }\n // Initialize this session GUC for every pending migration that consumes it,\n // instead of maintaining a second filename list that can silently lag the\n // shipped migration chain. The conservative source marker is intentional:\n // setting the bounded role list for a migration that only mentions the GUC\n // is harmless, while omitting it makes an otherwise valid upgrade fail.\n if (\n Array.from(pendingMigrationSources.values()).some((source) =>\n source.includes(MIGRATION_APPLICATION_ROLES_SETTING),\n )\n ) {\n const applicationRoles = migrationApplicationRoles(schema, runtimeOptions);\n await sql`select set_config(\n ${MIGRATION_APPLICATION_ROLES_SETTING},\n ${JSON.stringify(applicationRoles)},\n false\n )`;\n }\n for (const file of files) {\n if (applied.has(file)) {\n continue;\n }\n const sqlText = pendingMigrationSources.get(file);\n if (sqlText === undefined) {\n throw new Error(`Pending migration source was not loaded: ${file}`);\n }\n await executeMigrationFile(sql, file, sqlText);\n await sql`INSERT INTO \"schema_migrations\" (\"name\") VALUES (${file}) ON CONFLICT DO NOTHING`;\n }\n // Reconcile even when all migration names were already recorded. This is\n // the only supported way to change deployment policy in a live database.\n await persistDeploymentDepthPolicy(sql, depthPolicy);\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, { applicationDatabaseRoles })` from its own provisioning code\n * 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(\n adminConnection: string,\n targetSchema?: string,\n runtimeOptions?: MigrationRuntimeOptions,\n): Promise<void> {\n await migrate(adminConnection, targetSchema, runtimeOptions);\n}\n\nif (import.meta.main) {\n await migrate();\n console.log(\"Applied Drizzle SQL migrations.\");\n}\n"],"mappings":"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","names":[]}
@@ -12,6 +12,7 @@ __export(schema_exports, {
12
12
  attachedBrowserInventories: () => attachedBrowserInventories,
13
13
  auditEvents: () => auditEvents,
14
14
  authRuns: () => authRuns,
15
+ automaticSessionTitleFanoutOutboxV1: () => automaticSessionTitleFanoutOutboxV1,
15
16
  automationRunEventLinks: () => automationRunEventLinks,
16
17
  automationRuns: () => automationRuns,
17
18
  automationSources: () => automationSources,
@@ -178,6 +179,8 @@ __export(schema_exports, {
178
179
  personalGitHubRepositorySelectionOperations: () => personalGitHubRepositorySelectionOperations,
179
180
  personalGitHubRepositorySelections: () => personalGitHubRepositorySelections,
180
181
  prReviewAppRegistrations: () => prReviewAppRegistrations,
182
+ prReviewManagedGithubAuthorityNonces: () => prReviewManagedGithubAuthorityNonces,
183
+ prReviewManagedGithubRoutes: () => prReviewManagedGithubRoutes,
181
184
  prReviewRepositoryBindings: () => prReviewRepositoryBindings,
182
185
  preferenceRegistryEvents: () => preferenceRegistryEvents,
183
186
  preferenceRegistryPreferences: () => preferenceRegistryPreferences,
@@ -233,6 +236,7 @@ __export(schema_exports, {
233
236
  sessionTurnAttempts: () => sessionTurnAttempts,
234
237
  sessionTurnStartupMilestones: () => sessionTurnStartupMilestones,
235
238
  sessionTurns: () => sessionTurns,
239
+ sessionVariableSetAttachments: () => sessionVariableSetAttachments,
236
240
  sessionWorkflowWakeOutbox: () => sessionWorkflowWakeOutbox,
237
241
  sessions: () => sessions,
238
242
  siteAuthConnections: () => siteAuthConnections,
@@ -325,6 +329,7 @@ import {
325
329
  integer as integer15,
326
330
  jsonb as jsonb13,
327
331
  numeric,
332
+ pgSchema,
328
333
  pgTable as pgTable16,
329
334
  primaryKey as primaryKey5,
330
335
  text as text16,
@@ -343,7 +348,7 @@ var JSON_KEY_PREFIX = "opengeni_lossless_json_key_v2_7ca6071d:";
343
348
  var TEXT_PREFIX = "opengeni_lossless_text_v2_c4100a62:";
344
349
  var MAX_JSON_DEPTH = 512;
345
350
  var LOSSLESS_CONTENT_CODEC_VERSION = 1;
346
- var LOSSLESS_CONTENT_WRITER_APPLICATION_NAME = "opengeni-lossless-v1";
351
+ var LOSSLESS_CONTENT_WRITER_APPLICATION_NAME = "opengeni-lossless-v1-session-variable-sets-v1";
347
352
  function withLosslessContentWriteVersion(value, contentKey, versionKey) {
348
353
  const stamp = (entry) => {
349
354
  if (!Object.hasOwn(entry, contentKey)) {
@@ -5644,6 +5649,7 @@ var bytea2 = customType4({
5644
5649
  return "bytea";
5645
5650
  }
5646
5651
  });
5652
+ var opengeniPrivateSchema = pgSchema("opengeni_private");
5647
5653
  var managedAccounts = pgTable16(
5648
5654
  "managed_accounts",
5649
5655
  {
@@ -7346,6 +7352,17 @@ var slackRoutePrompts = pgTable16(
7346
7352
  foreignColumns: [workspaces.id, workspaces.accountId]
7347
7353
  }).onDelete("cascade"),
7348
7354
  pending: index16("slack_route_prompts_pending_idx").on(table.expiresAt, table.id).where(sql13`${table.status} = 'pending'`),
7355
+ // One live card per person per conversation. The existing uniques are keyed
7356
+ // to the originating event, so they stop Slack's retries of ONE event from
7357
+ // posting twice but not two different messages. `slackUserId` is in the key
7358
+ // on purpose: a shared channel has many people in it, and asking one of them
7359
+ // must not swallow another's request. A direct message is already one
7360
+ // channel per person, so the same index covers both surfaces.
7361
+ //
7362
+ // Expiry is not in the predicate because `now()` is not immutable. A
7363
+ // timed-out row is settled `expired` by the writer before it opens a new
7364
+ // prompt.
7365
+ pendingConversation: uniqueIndex16("slack_route_prompts_pending_conversation_uq").on(table.connectionId, table.slackChannelId, table.slackUserId).where(sql13`${table.status} = 'pending'`),
7349
7366
  statusValid: check11(
7350
7367
  "slack_route_prompts_status_check",
7351
7368
  sql13`${table.status} in ('pending', 'answered', 'expired', 'cancelled')`
@@ -8756,6 +8773,10 @@ var sessions = pgTable16(
8756
8773
  // write the result through the epoch-fenced setActiveSandbox CAS. Legacy
8757
8774
  // rows may still be null/relative and are resolved at establishment.
8758
8775
  workingDir: text16("working_dir"),
8776
+ // Ordered low-to-high precedence source for public/session/runtime reads.
8777
+ // session_variable_set_attachments is the FK-backed lifecycle projection;
8778
+ // the session trigger maintains it and the legacy singular alias atomically.
8779
+ variableSetIds: jsonb13("variable_set_ids").$type().notNull().default([]),
8759
8780
  variableSetId: uuid16("variable_set_id").references(() => workspaceVariableSets.id, {
8760
8781
  onDelete: "set null"
8761
8782
  }),
@@ -8982,6 +9003,58 @@ var sessions = pgTable16(
8982
9003
  )
8983
9004
  })
8984
9005
  );
9006
+ var sessionVariableSetAttachments = pgTable16(
9007
+ "session_variable_set_attachments",
9008
+ {
9009
+ id: uuid16("id").primaryKey().defaultRandom(),
9010
+ accountId: uuid16("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
9011
+ workspaceId: uuid16("workspace_id").notNull(),
9012
+ sessionId: uuid16("session_id").notNull(),
9013
+ variableSetId: uuid16("variable_set_id").notNull().references(() => workspaceVariableSets.id, { onDelete: "cascade" }),
9014
+ position: integer15("position").notNull(),
9015
+ sessionStatus: text16("session_status").notNull(),
9016
+ createdAt: timestamp16("created_at", { withTimezone: true }).notNull().defaultNow()
9017
+ },
9018
+ (table) => ({
9019
+ workspaceAccount: foreignKey({
9020
+ name: "session_variable_set_attachments_workspace_account_fk",
9021
+ columns: [table.workspaceId, table.accountId],
9022
+ foreignColumns: [workspaces.id, workspaces.accountId]
9023
+ }).onDelete("cascade"),
9024
+ session: foreignKey({
9025
+ name: "session_variable_set_attachments_session_fk",
9026
+ columns: [table.workspaceId, table.sessionId],
9027
+ foreignColumns: [sessions.workspaceId, sessions.id]
9028
+ }).onDelete("cascade"),
9029
+ sessionPosition: uniqueIndex16("session_variable_set_attachments_session_position_uq").on(
9030
+ table.workspaceId,
9031
+ table.sessionId,
9032
+ table.position
9033
+ ),
9034
+ sessionVariableSet: uniqueIndex16("session_variable_set_attachments_session_set_uq").on(
9035
+ table.workspaceId,
9036
+ table.sessionId,
9037
+ table.variableSetId
9038
+ ),
9039
+ variableSetSessions: index16("session_variable_set_attachments_set_sessions_idx").on(
9040
+ table.variableSetId,
9041
+ table.sessionStatus,
9042
+ table.workspaceId,
9043
+ table.sessionId
9044
+ ),
9045
+ positionValid: check11(
9046
+ "session_variable_set_attachments_position_check",
9047
+ sql13`${table.position} >= 0 and ${table.position} < 25`
9048
+ ),
9049
+ statusValid: check11(
9050
+ "session_variable_set_attachments_status_check",
9051
+ sql13`${table.sessionStatus} in (
9052
+ 'queued', 'running', 'idle', 'requires_action', 'recovering',
9053
+ 'waiting_capacity', 'failed', 'cancelled'
9054
+ )`
9055
+ )
9056
+ })
9057
+ );
8985
9058
  var organizationUserResourceGrants = pgTable16(
8986
9059
  "organization_user_resource_grants",
8987
9060
  {
@@ -10713,7 +10786,7 @@ var turnPersonalResourceAttachmentReceipts = pgTable16(
10713
10786
  sql13`${table.sessionAuthorityEpoch} > 0
10714
10787
  and octet_length(${table.initiatingHumanSubjectId}) between 1 and 512
10715
10788
  and ${table.membershipAuthorizationRevision} > 0
10716
- and ${table.resourceCount} between 1 and 28
10789
+ and ${table.resourceCount} between 1 and 52
10717
10790
  and ${table.grantMode} in ('once', 'session', 'always')
10718
10791
  and ${table.sessionVisibility} in ('user_private', 'workspace_shared')
10719
10792
  and ${table.sharedOutputWarningVersion} = 1
@@ -10777,7 +10850,7 @@ var turnPersonalResourceSnapshots = pgTable16(
10777
10850
  sql13`${table.membershipAuthorizationRevision} > 0
10778
10851
  and ${table.authorityGeneration} > 0
10779
10852
  and ${table.grantGeneration} > 0
10780
- and cardinality(${table.selectionSources}) between 1 and 26`
10853
+ and cardinality(${table.selectionSources}) between 1 and 50`
10781
10854
  ),
10782
10855
  grantShape: check11(
10783
10856
  "turn_personal_resource_snapshots_grant_chk",
@@ -12338,6 +12411,41 @@ var sessionEvents = pgTable16(
12338
12411
  )
12339
12412
  })
12340
12413
  );
12414
+ var automaticSessionTitleFanoutOutboxV1 = opengeniPrivateSchema.table(
12415
+ "automatic_session_title_fanout_outbox_v1",
12416
+ {
12417
+ id: uuid16("id").primaryKey().defaultRandom(),
12418
+ accountId: uuid16("account_id").notNull(),
12419
+ workspaceId: uuid16("workspace_id").notNull(),
12420
+ sessionId: uuid16("session_id").notNull(),
12421
+ eventId: uuid16("event_id").notNull(),
12422
+ attempts: integer15("attempts").notNull().default(0),
12423
+ lastError: text16("last_error"),
12424
+ deliveredAt: timestamp16("delivered_at", { withTimezone: true }),
12425
+ createdAt: timestamp16("created_at", { withTimezone: true }).notNull().defaultNow(),
12426
+ updatedAt: timestamp16("updated_at", { withTimezone: true }).notNull().defaultNow()
12427
+ },
12428
+ (table) => ({
12429
+ attemptsValid: check11("automatic_title_fanout_attempts_chk", sql13`${table.attempts} >= 0`),
12430
+ workspaceAccount: foreignKey({
12431
+ name: "automatic_title_fanout_workspace_account_fk",
12432
+ columns: [table.workspaceId, table.accountId],
12433
+ foreignColumns: [workspaces.id, workspaces.accountId]
12434
+ }).onDelete("cascade"),
12435
+ workspaceSession: foreignKey({
12436
+ name: "automatic_title_fanout_workspace_session_fk",
12437
+ columns: [table.workspaceId, table.sessionId],
12438
+ foreignColumns: [sessions.workspaceId, sessions.id]
12439
+ }).onDelete("cascade"),
12440
+ workspaceEvent: foreignKey({
12441
+ name: "automatic_title_fanout_workspace_event_fk",
12442
+ columns: [table.workspaceId, table.eventId],
12443
+ foreignColumns: [sessionEvents.workspaceId, sessionEvents.id]
12444
+ }).onDelete("cascade"),
12445
+ event: uniqueIndex16("automatic_title_fanout_event_uq").on(table.eventId),
12446
+ pending: index16("automatic_title_fanout_pending_idx").on(table.createdAt, table.id).where(sql13`${table.deliveredAt} is null`)
12447
+ })
12448
+ );
12341
12449
  var agentRunStates = pgTable16("agent_run_states", {
12342
12450
  id: uuid16("id").primaryKey().defaultRandom(),
12343
12451
  accountId: uuid16("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
@@ -14466,6 +14574,14 @@ var prReviewAppRegistrations = pgTable16(
14466
14574
  provider: text16("provider").notNull(),
14467
14575
  providerBaseUrl: text16("provider_base_url").notNull(),
14468
14576
  appId: text16("app_id"),
14577
+ installationId: text16("installation_id"),
14578
+ providerAccountLogin: text16("provider_account_login"),
14579
+ providerAccountType: text16("provider_account_type"),
14580
+ githubActorId: text16("github_actor_id"),
14581
+ authorityKind: text16("authority_kind"),
14582
+ authorityCheckedAt: timestamp16("authority_checked_at", { withTimezone: true }),
14583
+ authorityExpiresAt: timestamp16("authority_expires_at", { withTimezone: true }),
14584
+ authorityNonce: text16("authority_nonce"),
14469
14585
  credentialKind: text16("credential_kind").notNull(),
14470
14586
  credentialEncrypted: text16("credential_encrypted"),
14471
14587
  accessTokenExpiresAt: timestamp16("access_token_expires_at", { withTimezone: true }),
@@ -14493,6 +14609,8 @@ var prReviewAppRegistrations = pgTable16(
14493
14609
  table.workspaceId,
14494
14610
  table.status
14495
14611
  ),
14612
+ managedGithubInstallation: uniqueIndex16("pr_review_managed_github_workspace_installation_uq").on(table.workspaceId, table.installationId).where(sql13`${table.credentialKind} = 'managed_github_app'`),
14613
+ managedGithubAuthorityNonce: uniqueIndex16("pr_review_managed_github_authority_nonce_uq").on(table.authorityNonce).where(sql13`${table.authorityNonce} is not null`),
14496
14614
  providerCheck: check11(
14497
14615
  "pr_review_app_registrations_provider_chk",
14498
14616
  sql13`${table.provider} in ('github', 'gitlab', 'azure_devops')`
@@ -14500,9 +14618,11 @@ var prReviewAppRegistrations = pgTable16(
14500
14618
  credentialCheck: check11(
14501
14619
  "pr_review_app_registrations_credential_chk",
14502
14620
  sql13`(
14503
- (${table.provider} = 'github' and ${table.credentialKind} = 'github_app' and ${table.credentialEncrypted} is not null and ${table.appId} is not null)
14621
+ (${table.provider} = 'github' and ${table.credentialKind} = 'github_app' and ${table.credentialEncrypted} is not null and ${table.appId} is not null and ${table.installationId} is null)
14622
+ or
14623
+ (${table.provider} = 'github' and ${table.credentialKind} = 'managed_github_app' and ${table.credentialEncrypted} is null and ${table.appId} is not null and ${table.installationId} is not null and ${table.providerAccountType} in ('User', 'Organization') and ${table.githubActorId} ~ '^[1-9][0-9]*$' and ${table.authorityKind} in ('personal_owner', 'organization_owner') and ${table.authorityCheckedAt} is not null and ${table.authorityExpiresAt} is not null and ${table.authorityExpiresAt} > ${table.authorityCheckedAt} and octet_length(${table.authorityNonce}) between 16 and 256)
14504
14624
  or
14505
- (${table.provider} in ('gitlab', 'azure_devops') and ${table.credentialKind} = 'provider_token' and ${table.credentialEncrypted} is not null)
14625
+ (${table.provider} in ('gitlab', 'azure_devops') and ${table.credentialKind} = 'provider_token' and ${table.credentialEncrypted} is not null and ${table.installationId} is null)
14506
14626
  )`
14507
14627
  ),
14508
14628
  webhookAuthCheck: check11(
@@ -14586,6 +14706,69 @@ var prReviewRepositoryBindings = pgTable16(
14586
14706
  }).onDelete("cascade")
14587
14707
  })
14588
14708
  );
14709
+ var prReviewManagedGithubAuthorityNonces = pgTable16(
14710
+ "pr_review_managed_github_authority_nonces",
14711
+ {
14712
+ authorityNonce: text16("authority_nonce").primaryKey(),
14713
+ accountId: uuid16("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
14714
+ workspaceId: uuid16("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
14715
+ installationId: text16("installation_id").notNull(),
14716
+ authorityExpiresAt: timestamp16("authority_expires_at", { withTimezone: true }).notNull(),
14717
+ consumedAt: timestamp16("consumed_at", { withTimezone: true }).notNull().defaultNow()
14718
+ },
14719
+ (table) => ({
14720
+ identityCheck: check11(
14721
+ "pr_review_managed_github_authority_nonces_identity_chk",
14722
+ sql13`octet_length(${table.authorityNonce}) between 16 and 256
14723
+ and ${table.installationId} ~ '^[1-9][0-9]*$'
14724
+ and ${table.authorityExpiresAt} > ${table.consumedAt}`
14725
+ ),
14726
+ workspaceAccount: foreignKey({
14727
+ columns: [table.workspaceId, table.accountId],
14728
+ foreignColumns: [workspaces.id, workspaces.accountId],
14729
+ name: "pr_review_managed_github_authority_nonces_workspace_account_fk"
14730
+ }).onDelete("cascade")
14731
+ })
14732
+ );
14733
+ var prReviewManagedGithubRoutes = pgTable16(
14734
+ "pr_review_managed_github_routes",
14735
+ {
14736
+ bindingId: uuid16("binding_id").primaryKey().references(() => prReviewRepositoryBindings.id, { onDelete: "cascade" }),
14737
+ accountId: uuid16("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
14738
+ workspaceId: uuid16("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
14739
+ registrationId: uuid16("registration_id").notNull(),
14740
+ sourceId: uuid16("source_id").notNull(),
14741
+ installationId: text16("installation_id").notNull(),
14742
+ providerRepositoryId: text16("provider_repository_id").notNull(),
14743
+ createdAt: timestamp16("created_at", { withTimezone: true }).notNull().defaultNow()
14744
+ },
14745
+ (table) => ({
14746
+ routeIdentity: uniqueIndex16("pr_review_managed_github_route_identity_uq").on(
14747
+ table.installationId,
14748
+ table.providerRepositoryId
14749
+ ),
14750
+ identityCheck: check11(
14751
+ "pr_review_managed_github_routes_identity_chk",
14752
+ sql13`${table.installationId} ~ '^[1-9][0-9]*$'
14753
+ and ${table.providerRepositoryId} ~ '^[1-9][0-9]*$'`
14754
+ ),
14755
+ workspaceAccount: foreignKey({
14756
+ columns: [table.workspaceId, table.accountId],
14757
+ foreignColumns: [workspaces.id, workspaces.accountId],
14758
+ name: "pr_review_managed_github_routes_workspace_account_fk"
14759
+ }).onDelete("cascade"),
14760
+ registration: foreignKey({
14761
+ columns: [table.workspaceId, table.registrationId],
14762
+ foreignColumns: [prReviewAppRegistrations.workspaceId, prReviewAppRegistrations.id],
14763
+ name: "pr_review_managed_github_routes_registration_fk"
14764
+ }).onDelete("cascade"),
14765
+ source: foreignKey({
14766
+ columns: [table.workspaceId, table.sourceId],
14767
+ foreignColumns: [automationSources.workspaceId, automationSources.id],
14768
+ name: "pr_review_managed_github_routes_source_fk"
14769
+ }).onDelete("cascade")
14770
+ })
14771
+ );
14589
14772
  var usageEvents = pgTable16(
14590
14773
  "usage_events",
14591
14774
  {
@@ -16087,6 +16270,8 @@ var rigVersions = pgTable16(
16087
16270
  workspaceId: uuid16("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
16088
16271
  rigId: uuid16("rig_id").notNull().references(() => rigs.id, { onDelete: "cascade" }),
16089
16272
  version: integer15("version").notNull(),
16273
+ // Legacy audit field only. Migration 0356 rejects new non-null values;
16274
+ // runtime always uses the deployment platform sandbox image.
16090
16275
  image: text16("image"),
16091
16276
  setupScript: text16("setup_script"),
16092
16277
  // Self-declared health checks: [{ name, command }].
@@ -16328,6 +16513,7 @@ export {
16328
16513
  xaiCredentialLeases,
16329
16514
  channels,
16330
16515
  sessions,
16516
+ sessionVariableSetAttachments,
16331
16517
  organizationUserResourceGrants,
16332
16518
  sessionRealtimeModes,
16333
16519
  sessionRealtimeConnections,
@@ -16377,6 +16563,7 @@ export {
16377
16563
  xaiSessionAccountPins,
16378
16564
  xaiCapacityWaiters,
16379
16565
  sessionEvents,
16566
+ automaticSessionTitleFanoutOutboxV1,
16380
16567
  agentRunStates,
16381
16568
  sessionHumanInputRequests,
16382
16569
  sessionHistoryItems,
@@ -16420,6 +16607,8 @@ export {
16420
16607
  githubInstallationRepositories,
16421
16608
  prReviewAppRegistrations,
16422
16609
  prReviewRepositoryBindings,
16610
+ prReviewManagedGithubAuthorityNonces,
16611
+ prReviewManagedGithubRoutes,
16423
16612
  usageEvents,
16424
16613
  modelCallFacts,
16425
16614
  hostExportConfig,
@@ -16468,4 +16657,4 @@ export {
16468
16657
  rigChanges,
16469
16658
  schema_exports
16470
16659
  };
16471
- //# sourceMappingURL=chunk-PR2WMLOQ.js.map
16660
+ //# sourceMappingURL=chunk-C2AFP7SB.js.map