@opengeni/db 5.0.1 → 6.0.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 (212) hide show
  1. package/dist/automations.d.ts +0 -2
  2. package/dist/canonical-human-identities.d.ts +4 -0
  3. package/dist/canonical-human-identities.js +3 -3
  4. package/dist/capability-components.d.ts +5 -13
  5. package/dist/capability-integrations.d.ts +23 -8
  6. package/dist/capability-reconciliation.d.ts +5 -0
  7. package/dist/capability-reconciliation.js +21 -0
  8. package/dist/capability-reconciliation.js.map +1 -0
  9. package/dist/{chunk-6T2GGYWE.js → chunk-4UJCXBR2.js} +4 -5800
  10. package/dist/chunk-4UJCXBR2.js.map +1 -0
  11. package/dist/{chunk-MWMXWHJD.js → chunk-7JCDSMX2.js} +2 -2
  12. package/dist/chunk-AJA2ZIUW.js +219 -0
  13. package/dist/chunk-AJA2ZIUW.js.map +1 -0
  14. package/dist/chunk-CDAT6EKW.js +247 -0
  15. package/dist/chunk-CDAT6EKW.js.map +1 -0
  16. package/dist/{chunk-DPONPYJD.js → chunk-CJI6G254.js} +70 -18
  17. package/dist/chunk-CJI6G254.js.map +1 -0
  18. package/dist/chunk-G32NVMRJ.js +276 -0
  19. package/dist/chunk-G32NVMRJ.js.map +1 -0
  20. package/dist/chunk-GABXCG3N.js +5811 -0
  21. package/dist/chunk-GABXCG3N.js.map +1 -0
  22. package/dist/{chunk-ERKVSPDX.js → chunk-LVY33EWL.js} +3 -3
  23. package/dist/{chunk-45CP2YKY.js → chunk-MAMBI2HR.js} +9 -3
  24. package/dist/{chunk-45CP2YKY.js.map → chunk-MAMBI2HR.js.map} +1 -1
  25. package/dist/{chunk-F73UKJY6.js → chunk-MN5PZMEK.js} +91 -108
  26. package/dist/chunk-MN5PZMEK.js.map +1 -0
  27. package/dist/chunk-PJI4MUZ7.js +131 -0
  28. package/dist/chunk-PJI4MUZ7.js.map +1 -0
  29. package/dist/{chunk-T6BWIGWJ.js → chunk-RIYHP2WU.js} +2 -2
  30. package/dist/{chunk-7HMK3B45.js → chunk-RL2MUXM3.js} +16 -7
  31. package/dist/chunk-RL2MUXM3.js.map +1 -0
  32. package/dist/{chunk-HQDVI2DB.js → chunk-SYKHLPTK.js} +4 -3
  33. package/dist/{chunk-HQDVI2DB.js.map → chunk-SYKHLPTK.js.map} +1 -1
  34. package/dist/{chunk-T6YLHJLS.js → chunk-XIXVVBW2.js} +198 -51
  35. package/dist/chunk-XIXVVBW2.js.map +1 -0
  36. package/dist/chunk-ZPJ6V2VG.js +156 -0
  37. package/dist/chunk-ZPJ6V2VG.js.map +1 -0
  38. package/dist/codex-capacity-recovery.d.ts +12 -0
  39. package/dist/codex-failure-eligibility.d.ts +9 -0
  40. package/dist/company-profile-schema.d.ts +4 -2
  41. package/dist/connect-attempts.d.ts +15 -0
  42. package/dist/connect-attempts.js +25 -0
  43. package/dist/connect-attempts.js.map +1 -0
  44. package/dist/connection-authority.d.ts +7 -63
  45. package/dist/connection-refresh-lock.d.ts +4 -0
  46. package/dist/connection-token-resolver.d.ts +8 -43
  47. package/dist/database-timing.d.ts +10 -0
  48. package/dist/database.d.ts +4 -0
  49. package/dist/editable-artifact-durable-export.js +2 -2
  50. package/dist/editable-artifacts.d.ts +9 -0
  51. package/dist/editable-artifacts.js +7 -5
  52. package/dist/index.d.ts +447 -78
  53. package/dist/index.js +12705 -12872
  54. package/dist/index.js.map +1 -1
  55. package/dist/insights-usage-bundle.d.ts +3 -0
  56. package/dist/integration-bindings.d.ts +1 -1
  57. package/dist/integration-facets.d.ts +18 -1
  58. package/dist/knowledge-entries-schema.d.ts +2 -0
  59. package/dist/knowledge-entries.d.ts +1 -0
  60. package/dist/knowledge-indexing.d.ts +1 -0
  61. package/dist/live-session-attempt.d.ts +35 -137
  62. package/dist/managed-auth-session-sets.js +3 -3
  63. package/dist/mcp-account-bindings.d.ts +4 -0
  64. package/dist/mcp-oauth.d.ts +11 -0
  65. package/dist/mcp-operations.js +2 -2
  66. package/dist/migrate.js +1 -1
  67. package/dist/organization-integration-policy.d.ts +51 -0
  68. package/dist/organization-integration-policy.js +18 -0
  69. package/dist/organization-integration-policy.js.map +1 -0
  70. package/dist/organization-usage.d.ts +20 -0
  71. package/dist/plugin-packages.d.ts +9 -12
  72. package/dist/pr-review.d.ts +0 -11
  73. package/dist/preference-registry-schema.d.ts +17 -0
  74. package/dist/provision-roles.js +1 -1
  75. package/dist/retained-provider-commands.d.ts +124 -6
  76. package/dist/retained-provider-commands.js +29 -97
  77. package/dist/retained-provider-commands.js.map +1 -1
  78. package/dist/retired-session-create-metadata.d.ts +4 -0
  79. package/dist/runtime-posture.d.ts +7 -5
  80. package/dist/schema.d.ts +876 -656
  81. package/dist/schema.js +5 -7
  82. package/dist/session-admission-block.d.ts +32 -0
  83. package/dist/session-attempt-writers.d.ts +4 -0
  84. package/dist/session-background-commands.js +5 -4
  85. package/dist/session-command-output.js +8 -126
  86. package/dist/session-command-output.js.map +1 -1
  87. package/dist/session-control.d.ts +5 -1
  88. package/dist/session-event-slices.d.ts +10 -0
  89. package/dist/session-event-slices.js +8 -222
  90. package/dist/session-event-slices.js.map +1 -1
  91. package/dist/session-file-attachments.d.ts +28 -0
  92. package/dist/session-goal-reports.d.ts +43 -0
  93. package/dist/session-mcp-approval.d.ts +4 -0
  94. package/dist/session-mcp-credential-rotation.js +5 -4
  95. package/dist/session-mcp-credential-rotation.js.map +1 -1
  96. package/dist/session-message-search.d.ts +22 -0
  97. package/dist/session-queue-commands.d.ts +2 -6
  98. package/dist/session-retry.d.ts +36 -0
  99. package/dist/session-tenancy.js +3 -3
  100. package/dist/skill-source-release-impact.d.ts +18 -0
  101. package/dist/skill-source-release.d.ts +9 -0
  102. package/dist/skills.d.ts +7 -1
  103. package/dist/user-resource-authority.d.ts +0 -8
  104. package/dist/video-generation.js +3 -3
  105. package/dist/workspace-tool-defaults.js +5 -4
  106. package/dist/workspace-tool-defaults.js.map +1 -1
  107. package/drizzle/0468_knowledge_relationship_projection.sql +30 -0
  108. package/drizzle/0469_knowledge_source_discovery.sql +85 -0
  109. package/drizzle/0470_organization_integration_policy.sql +151 -0
  110. package/drizzle/0471_usage_events_account_recent_index.sql +4 -0
  111. package/drizzle/0472_usage_events_workspace_recent_index.sql +4 -0
  112. package/drizzle/0473_organization_usage_analytical_capability.sql +237 -0
  113. package/drizzle/0474_goal_report_requirements.sql +156 -0
  114. package/drizzle/0475_session_event_history_statistics.sql +15 -0
  115. package/drizzle/0476_session_event_history_policy_planning.sql +29 -0
  116. package/drizzle/0477_managed_sign_in_methods.sql +303 -0
  117. package/drizzle/0478_sender_owned_connections.sql +2772 -0
  118. package/drizzle/0479_connection_create_idempotency.sql +16 -0
  119. package/drizzle/0480_private_session_organization_key_administration.sql +154 -0
  120. package/drizzle/0481_personal_connection_visibility_cleanup.sql +45 -0
  121. package/drizzle/0482_remove_packs.sql +417 -0
  122. package/drizzle/0483_preclaim_admission_block.sql +85 -0
  123. package/drizzle/0484_insights_usage_projection.sql +211 -0
  124. package/drizzle/0485_inherited_mcp_approval_policies.sql +6 -0
  125. package/drizzle/0486_reasoning_configuration_message_forks.sql +35 -0
  126. package/drizzle/0487_skill_catalog_message_forks.sql +26 -0
  127. package/drizzle/0488_permanent_skill_removal.sql +207 -0
  128. package/drizzle/0489_modal_command_byte_offsets.sql +17 -0
  129. package/drizzle/0490_periodic_capture_attempt_cadence.sql +6 -0
  130. package/drizzle/0491_warm_capture_holder_reclamation.sql +57 -0
  131. package/drizzle/0492_codex_accepted_source_authority.sql +249 -0
  132. package/drizzle/0493_stopping_command_error_containment.sql +58 -0
  133. package/drizzle/0494_mcp_account_bindings.sql +334 -0
  134. package/drizzle/0495_consented_sandbox_recovery.sql +220 -0
  135. package/drizzle/0496_supervised_command_settlement.sql +386 -0
  136. package/drizzle/0497_modal_inventory_owner_read_capability.sql +112 -0
  137. package/drizzle/0498_enrollment_membership_fence.sql +87 -0
  138. package/drizzle/0499_session_attachment_access.sql +224 -0
  139. package/drizzle/0500_session_execution_epoch.sql +37 -0
  140. package/drizzle/0501_session_sharing_execution.sql +591 -0
  141. package/drizzle/0502_active_message_boundary_forks.sql +30 -0
  142. package/package.json +17 -5
  143. package/src/automations.ts +17 -73
  144. package/src/canonical-human-identities.ts +17 -5
  145. package/src/capability-components.ts +7 -24
  146. package/src/capability-integrations.ts +301 -21
  147. package/src/capability-reconciliation.ts +19 -0
  148. package/src/codex-capacity-recovery.ts +47 -0
  149. package/src/codex-failure-eligibility.ts +93 -0
  150. package/src/connect-attempts.ts +49 -18
  151. package/src/connection-authority.ts +12 -158
  152. package/src/connection-refresh-lock.ts +22 -0
  153. package/src/connection-token-resolver.ts +58 -530
  154. package/src/database-timing.ts +43 -0
  155. package/src/database.ts +61 -26
  156. package/src/editable-artifacts.ts +1 -1
  157. package/src/index.ts +3578 -1273
  158. package/src/insights-model-bundle.ts +19 -7
  159. package/src/insights-usage-bundle.ts +16 -19
  160. package/src/integration-bindings.ts +2 -7
  161. package/src/integration-facets.ts +73 -6
  162. package/src/knowledge-entries.ts +8 -1
  163. package/src/live-session-attempt.ts +0 -22
  164. package/src/mcp-account-bindings.ts +12 -0
  165. package/src/mcp-oauth.ts +26 -0
  166. package/src/organization-integration-policy.ts +235 -0
  167. package/src/organization-usage.ts +83 -0
  168. package/src/plugin-packages.ts +226 -42
  169. package/src/pr-review.ts +7 -69
  170. package/src/preference-registry-schema.ts +1 -0
  171. package/src/provision-roles.ts +50 -37
  172. package/src/retained-provider-commands.ts +286 -9
  173. package/src/retired-session-create-metadata.ts +16 -0
  174. package/src/runtime-posture.ts +217 -13
  175. package/src/schema.ts +104 -120
  176. package/src/session-admission-block.ts +29 -0
  177. package/src/session-attempt-writers.ts +48 -0
  178. package/src/session-control.ts +21 -5
  179. package/src/session-event-slices.ts +76 -26
  180. package/src/session-file-attachments.ts +66 -0
  181. package/src/session-goal-reports.ts +255 -0
  182. package/src/session-mcp-approval.ts +30 -0
  183. package/src/session-message-search.ts +348 -0
  184. package/src/session-queue-commands.ts +60 -36
  185. package/src/session-retry.ts +319 -0
  186. package/src/skill-config-migration.ts +11 -2
  187. package/src/skill-source-release-impact.ts +33 -0
  188. package/src/skill-source-release.ts +67 -26
  189. package/src/skills.ts +44 -6
  190. package/src/user-resource-authority.ts +0 -56
  191. package/dist/chunk-6T2GGYWE.js.map +0 -1
  192. package/dist/chunk-7HMK3B45.js.map +0 -1
  193. package/dist/chunk-DPONPYJD.js.map +0 -1
  194. package/dist/chunk-F73UKJY6.js.map +0 -1
  195. package/dist/chunk-T6YLHJLS.js.map +0 -1
  196. package/dist/host-mcp-binding-match.d.ts +0 -5
  197. package/dist/host-mcp-bindings.d.ts +0 -79
  198. package/dist/host-mcp-resolvers.d.ts +0 -47
  199. package/dist/host-mcp-task-authority.d.ts +0 -43
  200. package/dist/host-selection-identity.d.ts +0 -6
  201. package/dist/pack-components.d.ts +0 -83
  202. package/dist/pack-installations.d.ts +0 -86
  203. package/src/host-mcp-binding-match.ts +0 -34
  204. package/src/host-mcp-bindings.ts +0 -777
  205. package/src/host-mcp-resolvers.ts +0 -266
  206. package/src/host-mcp-task-authority.ts +0 -384
  207. package/src/host-selection-identity.ts +0 -29
  208. package/src/pack-components.ts +0 -980
  209. package/src/pack-installations.ts +0 -950
  210. /package/dist/{chunk-MWMXWHJD.js.map → chunk-7JCDSMX2.js.map} +0 -0
  211. /package/dist/{chunk-ERKVSPDX.js.map → chunk-LVY33EWL.js.map} +0 -0
  212. /package/dist/{chunk-T6BWIGWJ.js.map → chunk-RIYHP2WU.js.map} +0 -0
@@ -540,6 +540,7 @@ async function grantAppRoleIfSchemaExists(
540
540
  "get_organization_administration_overview(uuid,text)",
541
541
  "get_workspace_kind(uuid,uuid)",
542
542
  "resolve_workspace_codex_subscription_source(uuid,uuid)",
543
+ "capture_legacy_codex_turn_sources(uuid,uuid)",
543
544
  "list_organization_workspace_ids(uuid)",
544
545
  "list_organization_codex_workspace_ids(uuid)",
545
546
  "organization_workspace_command(jsonb)",
@@ -588,6 +589,10 @@ async function grantAppRoleIfSchemaExists(
588
589
  .map(literal)
589
590
  .join(", ")}]`;
590
591
  const managedAuthSessionSetRoutines = `ARRAY[${[
592
+ "assert_managed_sign_in_recovery(text,text,uuid,jsonb)",
593
+ "replay_managed_sign_in_method(text,text,jsonb)",
594
+ "claim_managed_sign_in_notification(uuid,text,text,integer)",
595
+ "settle_managed_sign_in_notification(uuid,uuid,text)",
591
596
  "get_canonical_human_exact_login_binding(text,text)",
592
597
  "managed_auth_session_set_authority_state(text)",
593
598
  "managed_auth_session_set_snapshot(text,text,boolean,boolean,boolean)",
@@ -626,6 +631,9 @@ BEGIN
626
631
  EXECUTE format('GRANT EXECUTE ON FUNCTION %I.mcp_operation_command(jsonb,text,jsonb) TO %I', ${literal(schema)}, ${literal(role)});
627
632
  END IF;
628
633
  EXECUTE format('GRANT USAGE ON SCHEMA %I TO %I', ${literal(schema)}, ${literal(role)});
634
+ IF to_regprocedure('opengeni_private.codex_credential_serves_turn(uuid,uuid,uuid,uuid)') IS NOT NULL THEN
635
+ EXECUTE format('GRANT EXECUTE ON FUNCTION opengeni_private.codex_credential_serves_turn(uuid,uuid,uuid,uuid) TO %I', ${literal(role)});
636
+ END IF;
629
637
  EXECUTE format('REVOKE CREATE ON SCHEMA %I FROM %I', ${literal(schema)}, ${literal(role)});
630
638
  EXECUTE format('REVOKE ALL PRIVILEGES ON ALL TABLES IN SCHEMA %I FROM %I', ${literal(schema)}, ${literal(role)});
631
639
  FOREACH runtime_table IN ARRAY ${runtimeFullDmlTables} LOOP
@@ -1325,6 +1333,9 @@ BEGIN
1325
1333
  ${literal(role)}
1326
1334
  );
1327
1335
  END IF;
1336
+ IF to_regprocedure(format('%I.mutate_managed_sign_in_method(text,text,jsonb)', ${literal(schema)})) IS NOT NULL THEN
1337
+ EXECUTE format('GRANT EXECUTE ON FUNCTION %I.mutate_managed_sign_in_method(text,text,jsonb) TO %I', ${literal(schema)}, ${literal(role)});
1338
+ END IF;
1328
1339
  FOREACH routine_signature IN ARRAY ${managedAuthSessionSetRoutines} LOOP
1329
1340
  IF to_regprocedure(format('%I.%s', ${literal(schema)}, routine_signature)) IS NOT NULL THEN
1330
1341
  EXECUTE format(
@@ -1716,6 +1727,10 @@ BEGIN
1716
1727
  ${literal(role)}
1717
1728
  );
1718
1729
  END IF;
1730
+ IF to_regprocedure(format('%I.list_owned_connection_accounts(uuid,uuid)', ${literal(schema)})) IS NOT NULL THEN
1731
+ EXECUTE format('REVOKE ALL ON FUNCTION %I.list_owned_connection_accounts(uuid,uuid) FROM PUBLIC', ${literal(schema)});
1732
+ EXECUTE format('GRANT EXECUTE ON FUNCTION %I.list_owned_connection_accounts(uuid,uuid) TO %I', ${literal(schema)}, ${literal(role)});
1733
+ END IF;
1719
1734
  IF to_regprocedure(format('%I.list_self_user_resource_authorities(uuid,uuid,text,uuid,integer)', ${literal(schema)}))
1720
1735
  IS NOT NULL THEN
1721
1736
  EXECUTE format('REVOKE ALL ON FUNCTION %I.list_self_user_resource_authorities(uuid) FROM PUBLIC', ${literal(schema)});
@@ -1733,29 +1748,9 @@ BEGIN
1733
1748
  EXECUTE format('REVOKE ALL ON FUNCTION %I.authorize_session_attempt_personal_resource_reads(uuid, uuid, uuid) FROM PUBLIC', ${literal(schema)});
1734
1749
  EXECUTE format('GRANT EXECUTE ON FUNCTION %I.authorize_session_attempt_personal_resource_reads(uuid, uuid, uuid) TO %I', ${literal(schema)}, ${literal(role)});
1735
1750
  END IF;
1736
- IF to_regprocedure(format('%I.issue_self_local_connection_use_grant(uuid,uuid,uuid,text,boolean)', ${literal(schema)}))
1737
- IS NOT NULL THEN
1738
- EXECUTE format('REVOKE ALL ON FUNCTION %I.issue_self_local_connection_use_grant(uuid, uuid, uuid, text, boolean) FROM PUBLIC', ${literal(schema)});
1739
- EXECUTE format('GRANT EXECUTE ON FUNCTION %I.issue_self_local_connection_use_grant(uuid, uuid, uuid, text, boolean) TO %I', ${literal(schema)}, ${literal(role)});
1740
- END IF;
1741
- IF to_regprocedure(format('%I.resolve_connection_use_authority(uuid,uuid,uuid,jsonb)', ${literal(schema)}))
1742
- IS NOT NULL THEN
1743
- EXECUTE format('REVOKE ALL ON FUNCTION %I.list_self_connection_authorities(uuid) FROM PUBLIC', ${literal(schema)});
1744
- EXECUTE format('REVOKE ALL ON FUNCTION %I.list_self_connection_authorities(uuid) FROM %I', ${literal(schema)}, ${literal(role)});
1745
- EXECUTE format('REVOKE ALL ON FUNCTION %I.issue_self_connection_use_grant(uuid, uuid, uuid, text, text, uuid, boolean) FROM PUBLIC', ${literal(schema)});
1746
- EXECUTE format('REVOKE ALL ON FUNCTION %I.issue_self_connection_use_grant(uuid, uuid, uuid, text, text, uuid, boolean) FROM %I', ${literal(schema)}, ${literal(role)});
1747
- EXECUTE format('REVOKE ALL ON FUNCTION %I.revoke_self_connection_use_grant(uuid, uuid) FROM PUBLIC', ${literal(schema)});
1748
- EXECUTE format('REVOKE ALL ON FUNCTION %I.revoke_self_connection_use_grant(uuid, uuid) FROM %I', ${literal(schema)}, ${literal(role)});
1749
- EXECUTE format('REVOKE ALL ON FUNCTION %I.resolve_connection_use_authority(uuid, uuid, uuid, jsonb) FROM PUBLIC', ${literal(schema)});
1750
- EXECUTE format('GRANT EXECUTE ON FUNCTION %I.resolve_connection_use_authority(uuid, uuid, uuid, jsonb) TO %I', ${literal(schema)}, ${literal(role)});
1751
- IF to_regprocedure(format('%I.resolve_personal_connection_authority_selection(uuid,uuid,text,uuid,jsonb)', ${literal(schema)})) IS NOT NULL THEN
1752
- EXECUTE format('REVOKE ALL ON FUNCTION %I.resolve_personal_connection_authority_selection(uuid, uuid, text, uuid, jsonb) FROM PUBLIC', ${literal(schema)});
1753
- EXECUTE format('GRANT EXECUTE ON FUNCTION %I.resolve_personal_connection_authority_selection(uuid, uuid, text, uuid, jsonb) TO %I', ${literal(schema)}, ${literal(role)});
1754
- END IF;
1755
- IF to_regprocedure(format('%I.resolve_accepted_connection_use(uuid,uuid,uuid,uuid,uuid,integer,uuid,text,text,uuid,text,text,text,text)', ${literal(schema)})) IS NOT NULL THEN
1756
- EXECUTE format('REVOKE ALL ON FUNCTION %I.resolve_accepted_connection_use(uuid, uuid, uuid, uuid, uuid, integer, uuid, text, text, uuid, text, text, text, text) FROM PUBLIC', ${literal(schema)});
1757
- EXECUTE format('GRANT EXECUTE ON FUNCTION %I.resolve_accepted_connection_use(uuid, uuid, uuid, uuid, uuid, integer, uuid, text, text, uuid, text, text, text, text) TO %I', ${literal(schema)}, ${literal(role)});
1758
- END IF;
1751
+ IF to_regprocedure(format('%I.resolve_accepted_connection_use(uuid,uuid,uuid,uuid,uuid,integer,uuid,text,text,uuid,text,text,text,text)', ${literal(schema)})) IS NOT NULL THEN
1752
+ EXECUTE format('REVOKE ALL ON FUNCTION %I.resolve_accepted_connection_use(uuid, uuid, uuid, uuid, uuid, integer, uuid, text, text, uuid, text, text, text, text) FROM PUBLIC', ${literal(schema)});
1753
+ EXECUTE format('GRANT EXECUTE ON FUNCTION %I.resolve_accepted_connection_use(uuid, uuid, uuid, uuid, uuid, integer, uuid, text, text, uuid, text, text, text, text) TO %I', ${literal(schema)}, ${literal(role)});
1759
1754
  END IF;
1760
1755
  IF to_regprocedure(
1761
1756
  format('%I.get_self_personal_github_repository_selection(uuid,uuid,text,uuid)', ${literal(schema)})
@@ -1885,20 +1880,7 @@ BEGIN
1885
1880
  ${literal(schema)},
1886
1881
  ${literal(role)}
1887
1882
  );
1888
- IF to_regprocedure(
1889
- format(
1890
- '%I.refresh_scheduled_task_personal_resources_clone_connections(uuid,uuid,uuid,bigint,bigint)',
1891
- ${literal(schema)}
1892
- )
1893
- ) IS NOT NULL THEN
1894
- EXECUTE format(
1895
- 'REVOKE ALL ON FUNCTION %I.refresh_scheduled_task_personal_resources_clone_connections(uuid, uuid, uuid, bigint, bigint) FROM PUBLIC',
1896
- ${literal(schema)}
1897
- );
1898
- EXECUTE format(
1899
- 'GRANT EXECUTE ON FUNCTION %I.refresh_scheduled_task_personal_resources_clone_connections(uuid, uuid, uuid, bigint, bigint) TO %I',
1900
- ${literal(schema)}, ${literal(role)}
1901
- );
1883
+ IF to_regprocedure(format('%I.create_scheduled_agent_run_with_admission(uuid,uuid,uuid,uuid,bigint,text,text,text,timestamp with time zone,timestamp with time zone,jsonb)', ${literal(schema)})) IS NOT NULL THEN
1902
1884
  EXECUTE format(
1903
1885
  'REVOKE ALL ON FUNCTION %I.create_scheduled_agent_run_with_admission(uuid, uuid, uuid, uuid, bigint, text, text, text, timestamp with time zone, timestamp with time zone, jsonb) FROM PUBLIC',
1904
1886
  ${literal(schema)}
@@ -2089,6 +2071,34 @@ BEGIN
2089
2071
  EXECUTE format('GRANT USAGE ON SCHEMA opengeni_private TO %I', ${literal(role)});
2090
2072
  EXECUTE format('REVOKE CREATE ON SCHEMA opengeni_private FROM %I', ${literal(role)});
2091
2073
  EXECUTE format('GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA opengeni_private TO %I', ${literal(role)});
2074
+ IF to_regclass('opengeni_private.modal_inventory_read_capabilities') IS NOT NULL THEN
2075
+ -- Inventory is the only capability mint. Reprovisioning must repair
2076
+ -- accidental table and column grants, never expose its private ledger.
2077
+ EXECUTE format('REVOKE ALL ON TABLE opengeni_private.modal_inventory_read_capabilities FROM %I', ${literal(role)});
2078
+ EXECUTE format('REVOKE ALL (backend_pid, transaction_id, data_schema) ON TABLE opengeni_private.modal_inventory_read_capabilities FROM %I', ${literal(role)});
2079
+ REVOKE ALL ON TABLE opengeni_private.modal_inventory_read_capabilities FROM PUBLIC;
2080
+ REVOKE ALL (backend_pid, transaction_id, data_schema) ON TABLE opengeni_private.modal_inventory_read_capabilities FROM PUBLIC;
2081
+ REVOKE ALL ON FUNCTION opengeni_private.list_live_modal_sandbox_leases() FROM PUBLIC;
2082
+ END IF;
2083
+ IF to_regclass('opengeni_private.sandbox_recovery_rollout') IS NOT NULL THEN
2084
+ -- Migration may precede this role's creation. Converge only read access;
2085
+ -- runtime identities and PUBLIC never receive recovery activation writes.
2086
+ EXECUTE format('REVOKE ALL ON TABLE opengeni_private.sandbox_recovery_rollout FROM %I', ${literal(role)});
2087
+ EXECUTE format('REVOKE ALL (singleton, consent_enabled, release_evidence) ON TABLE opengeni_private.sandbox_recovery_rollout FROM %I', ${literal(role)});
2088
+ REVOKE ALL ON TABLE opengeni_private.sandbox_recovery_rollout FROM PUBLIC;
2089
+ REVOKE ALL (singleton, consent_enabled, release_evidence) ON TABLE opengeni_private.sandbox_recovery_rollout FROM PUBLIC;
2090
+ EXECUTE format('GRANT SELECT ON TABLE opengeni_private.sandbox_recovery_rollout TO %I', ${literal(role)});
2091
+ END IF;
2092
+ IF to_regclass('opengeni_private.organization_usage_read_capabilities') IS NOT NULL THEN
2093
+ EXECUTE format('REVOKE ALL ON TABLE opengeni_private.organization_usage_read_capabilities FROM %I', ${literal(role)});
2094
+ REVOKE ALL ON TABLE opengeni_private.organization_usage_read_capabilities FROM PUBLIC;
2095
+ REVOKE ALL ON FUNCTION opengeni_private.organization_usage_summary(uuid,timestamptz,timestamptz,text,uuid,boolean) FROM PUBLIC;
2096
+ END IF;
2097
+ IF to_regclass('opengeni_private.session_file_attachments') IS NOT NULL THEN
2098
+ EXECUTE format('REVOKE ALL ON TABLE opengeni_private.session_file_attachments, opengeni_private.session_file_read_capabilities FROM %I', ${literal(role)});
2099
+ REVOKE ALL ON TABLE opengeni_private.session_file_attachments, opengeni_private.session_file_read_capabilities FROM PUBLIC;
2100
+ REVOKE ALL ON FUNCTION opengeni_private.session_file_read_allowed(uuid,uuid,uuid), opengeni_private.accept_session_file_attachments(uuid,uuid,uuid,uuid,text,uuid[]), opengeni_private.read_session_file_attachments(uuid,uuid,uuid,integer,uuid[],jsonb) FROM PUBLIC;
2101
+ END IF;
2092
2102
  IF to_regclass('opengeni_private.sandbox_file_publications') IS NOT NULL THEN
2093
2103
  EXECUTE format('REVOKE ALL ON TABLE opengeni_private.sandbox_file_publications FROM %I', ${literal(role)});
2094
2104
  REVOKE ALL ON TABLE opengeni_private.sandbox_file_publications FROM PUBLIC;
@@ -2096,6 +2106,9 @@ BEGIN
2096
2106
  REVOKE ALL ON FUNCTION opengeni_private.list_sandbox_file_publications(uuid,uuid,jsonb) FROM PUBLIC;
2097
2107
  END IF;
2098
2108
  FOREACH routine_signature IN ARRAY ARRAY[
2109
+ 'read_sender_connection(uuid,uuid,uuid,text)',
2110
+ 'validate_mcp_account_bindings(jsonb,jsonb)',
2111
+ 'fence_mcp_account_bindings()',
2099
2112
  'guard_mcp_operation_immutable()',
2100
2113
  'mcp_operation_command_scoped(jsonb,text,jsonb)',
2101
2114
  'guard_workspace_owned_skill_head_delete()',
@@ -1,10 +1,17 @@
1
- import { and, eq } from "drizzle-orm";
1
+ import { and, eq, sql } from "drizzle-orm";
2
2
  import { isDeepStrictEqual } from "node:util";
3
- import { SandboxProviderCommand } from "@opengeni/contracts";
4
- import { withRlsContext, type Database } from "./database";
3
+ import {
4
+ SandboxProviderCommand,
5
+ ModalRouterProviderCommand,
6
+ CommandSupervisionReceipt,
7
+ type SessionEvent,
8
+ } from "@opengeni/contracts";
9
+ import { withRlsContext, withSessionActivityRlsContext, type Database } from "./database";
10
+ import { lockSessionEventWriteRows } from "./session-control";
11
+ import { appendSessionCommandOutput } from "./session-command-output";
5
12
  import * as schema from "./schema";
6
13
 
7
- type ProcessScope = {
14
+ export type ProcessScope = {
8
15
  accountId: string;
9
16
  workspaceId: string;
10
17
  sessionId: string;
@@ -12,12 +19,28 @@ type ProcessScope = {
12
19
  };
13
20
 
14
21
  /** Bound to an already-authorized exact process scope by runtime wiring. */
15
- export function retainedProviderCommandPersistence(db: Database, scope: ProcessScope) {
22
+ export function retainedProviderCommandPersistence(
23
+ db: Database,
24
+ scope: ProcessScope,
25
+ publish?: (events: SessionEvent[]) => Promise<void>,
26
+ ) {
16
27
  return {
28
+ recordSupervisionReceipt: (receipt: SupervisionReceipt) =>
29
+ recordRetainedSupervisionReceipt(db, scope, receipt),
30
+ loadSupervisionReceipt: () => loadRetainedSupervisionReceipt(db, scope),
31
+ requestCancellation: (reason: "provider_deadline" | "explicit_stop") =>
32
+ requestRetainedProcessCancellation(db, scope, reason),
33
+ cancellationRequested: () => retainedProcessCancellationRequested(db, scope),
17
34
  load: () => getRetainedProviderCommand(db, scope),
18
35
  acknowledge: (command: SandboxProviderCommand) =>
19
36
  acknowledgeRetainedProviderOutput(db, scope, command),
20
- reserveInput: () => reserveRetainedProviderInput(db, scope),
37
+ reserveInput: (byteLength?: number) => reserveRetainedProviderInput(db, scope, byteLength),
38
+ captureRouterPage: async (page: RetainedRouterOutputPage) => {
39
+ const result = await captureRetainedRouterOutput(db, scope, page);
40
+ // A committed capture is authoritative even if live fanout fails.
41
+ if (result.events.length && publish) await publish(result.events).catch(() => undefined);
42
+ return { command: result.command, captured: result.captured };
43
+ },
21
44
  };
22
45
  }
23
46
 
@@ -36,7 +59,8 @@ function sameExecution(a: SandboxProviderCommand, b: SandboxProviderCommand): bo
36
59
  a.sandboxId === b.sandboxId &&
37
60
  a.taskId === b.taskId &&
38
61
  a.execId === b.execId &&
39
- Boolean(a.pty) === Boolean(b.pty)
62
+ Boolean(a.pty) === Boolean(b.pty) &&
63
+ isDeepStrictEqual(supervisionDescriptor(a), supervisionDescriptor(b))
40
64
  );
41
65
  }
42
66
 
@@ -110,6 +134,8 @@ export async function acknowledgeRetainedProviderOutput(
110
134
  candidate: SandboxProviderCommand,
111
135
  ): Promise<SandboxProviderCommand> {
112
136
  const next = SandboxProviderCommand.parse(candidate);
137
+ if (next.kind !== "modal-control-v1")
138
+ throw new Error("Byte-offset command output requires atomic capture");
113
139
  return withRlsContext(db, scope, async (tx) => {
114
140
  const [row] = await tx
115
141
  .select()
@@ -119,6 +145,8 @@ export async function acknowledgeRetainedProviderOutput(
119
145
  .limit(1);
120
146
  if (!row?.providerCommand) throw new Error("Retained provider command is unavailable");
121
147
  const previous = SandboxProviderCommand.parse(row.providerCommand);
148
+ if (previous.kind !== "modal-control-v1")
149
+ throw new Error("Legacy acknowledgment cannot advance byte-offset output");
122
150
  if (!sameExecution(previous, next))
123
151
  throw new Error("Output acknowledgment changed provider execution identity");
124
152
  const merged = structuredClone(previous);
@@ -141,11 +169,119 @@ export async function acknowledgeRetainedProviderOutput(
141
169
  });
142
170
  }
143
171
 
172
+ export type RetainedRouterOutputPage = {
173
+ expected: ModalRouterProviderCommand;
174
+ command: ModalRouterProviderCommand;
175
+ stdout: string;
176
+ stderr: string;
177
+ };
178
+
179
+ export function validateRouterOutputAdvance(page: RetainedRouterOutputPage): void {
180
+ const before = ModalRouterProviderCommand.parse(page.expected);
181
+ const after = ModalRouterProviderCommand.parse(page.command);
182
+ if (!sameExecution(before, after)) throw new Error("Output capture changed execution identity");
183
+ for (const stream of ["stdout", "stderr"] as const) {
184
+ const oldCursor = before.streams[stream],
185
+ cursor = after.streams[stream];
186
+ if (
187
+ cursor.byteOffset < oldCursor.byteOffset ||
188
+ (oldCursor.eof && (!cursor.eof || cursor.byteOffset !== oldCursor.byteOffset)) ||
189
+ (oldCursor.exitCode !== null && !isDeepStrictEqual(oldCursor, cursor))
190
+ )
191
+ throw new Error("Output capture cannot regress or rewrite terminal evidence");
192
+ if (
193
+ cursor.byteOffset === oldCursor.byteOffset &&
194
+ !(!oldCursor.eof && cursor.eof) &&
195
+ (page[stream].length > 0 || cursor.utf8Remainder !== oldCursor.utf8Remainder)
196
+ )
197
+ throw new Error("Output without byte advancement requires the first EOF");
198
+ if (cursor.eof && cursor.utf8Remainder !== "")
199
+ throw new Error("EOF must flush pending UTF-8 bytes");
200
+ if (Buffer.byteLength(page[stream]) > 4 * 1024 * 1024)
201
+ throw new Error("Command output page exceeds its capture bound");
202
+ }
203
+ }
204
+
205
+ /** Capture and offsets commit atomically. The session lock is acquired before
206
+ * the process lock, matching the event-write lock order. A concurrent reader
207
+ * with a stale cursor discards its page and reloads; it never appends overlapping
208
+ * output or silently advances the other reader's cursor. */
209
+ export async function captureRetainedRouterOutput(
210
+ db: Database,
211
+ scope: ProcessScope,
212
+ page: RetainedRouterOutputPage,
213
+ ): Promise<{ command: ModalRouterProviderCommand; events: SessionEvent[]; captured: boolean }> {
214
+ validateRouterOutputAdvance(page);
215
+ return await withSessionActivityRlsContext(db, scope, async (tx) => {
216
+ const locks = await lockSessionEventWriteRows(tx, {
217
+ workspaceId: scope.workspaceId,
218
+ sessionIds: [scope.sessionId],
219
+ controlLock: "share",
220
+ });
221
+ if (locks.sessions[0]?.accountId !== scope.accountId)
222
+ throw new Error("Command output session not found");
223
+ const [row] = await tx
224
+ .select()
225
+ .from(schema.sandboxRetainedProcesses)
226
+ .where(processWhere(scope))
227
+ .for("update")
228
+ .limit(1);
229
+ if (!row?.providerCommand || row.providerBackend !== "modal")
230
+ throw new Error("Retained provider command is unavailable");
231
+ const current = ModalRouterProviderCommand.parse(row.providerCommand);
232
+ if (!sameExecution(current, page.expected))
233
+ throw new Error("Output capture does not own this execution");
234
+ if (!isDeepStrictEqual(current, page.expected))
235
+ return { command: current, events: [], captured: false };
236
+ const events: SessionEvent[] = [];
237
+ for (const stream of ["stdout", "stderr"] as const) {
238
+ const before = current.streams[stream],
239
+ after = page.command.streams[stream];
240
+ if (page[stream])
241
+ events.push(
242
+ ...(await appendSessionCommandOutput(tx, {
243
+ ...scope,
244
+ commandId: scope.processId,
245
+ stream,
246
+ streamFidelity: current.pty ? "merged" : "separate",
247
+ chunkId: `modal-router:${current.execId}:${stream}:${before.byteOffset}:${after.byteOffset}:${after.eof ? 1 : 0}`,
248
+ chunk: page[stream],
249
+ })),
250
+ );
251
+ }
252
+ if (supervisionDescriptor(page.command)) {
253
+ await tx.execute(
254
+ sql`select set_config('opengeni.supervised_output_capture_process_id', ${scope.processId}, true)`,
255
+ );
256
+ }
257
+ await tx
258
+ .update(schema.sandboxRetainedProcesses)
259
+ .set({
260
+ providerCommand: page.command,
261
+ ...(supervisionDescriptor(page.command) &&
262
+ page.command.streams.stdout.eof &&
263
+ page.command.streams.stderr.eof &&
264
+ page.command.streams.stdout.exitCode === 0 &&
265
+ page.command.streams.stderr.exitCode === 0
266
+ ? { supervisionOutputCaptured: true }
267
+ : {}),
268
+ })
269
+ .where(processWhere(scope));
270
+ if (supervisionDescriptor(page.command)) {
271
+ await tx.execute(
272
+ sql`select set_config('opengeni.supervised_output_capture_process_id', '', true)`,
273
+ );
274
+ }
275
+ return { command: page.command, events, captured: true };
276
+ });
277
+ }
278
+
144
279
  /** Reserve a strictly increasing provider stdin index before dispatch. An
145
280
  * ambiguous send consumes its index and is never silently replayed. */
146
281
  export async function reserveRetainedProviderInput(
147
282
  db: Database,
148
283
  scope: ProcessScope,
284
+ byteLength?: number,
149
285
  ): Promise<number> {
150
286
  return withRlsContext(db, scope, async (tx) => {
151
287
  const [row] = await tx
@@ -156,12 +292,153 @@ export async function reserveRetainedProviderInput(
156
292
  .limit(1);
157
293
  if (!row?.providerCommand || row.state !== "active")
158
294
  throw new Error("Active retained provider command is unavailable");
159
- const index = row.providerCommandInputIndex + 1;
295
+ if (row.cancellationRequestedAt || row.supervisionReceipt)
296
+ throw new Error("Retained command input is closed");
297
+ const router = row.providerCommand.kind === "modal-router-v1";
298
+ if (router && (!Number.isSafeInteger(byteLength) || byteLength! <= 0))
299
+ throw new Error("Byte-offset stdin requires a positive byte reservation");
300
+ const index = row.providerCommandInputIndex + (router ? byteLength! : 1);
160
301
  if (!Number.isSafeInteger(index)) throw new Error("Provider stdin sequence exhausted");
161
302
  await tx
162
303
  .update(schema.sandboxRetainedProcesses)
163
304
  .set({ providerCommandInputIndex: index })
164
305
  .where(processWhere(scope));
165
- return index;
306
+ return router ? row.providerCommandInputIndex : index;
307
+ });
308
+ }
309
+
310
+ export type SupervisionReceipt = CommandSupervisionReceipt;
311
+
312
+ function supervisionDescriptor(command: SandboxProviderCommand) {
313
+ return command.kind === "modal-router-v1" ? command.supervision : undefined;
314
+ }
315
+
316
+ /** Fail before provider start, not after discovering an unprotected DB at retention. */
317
+ export async function supervisedCommandProtocolReady(db: Database): Promise<boolean> {
318
+ const [row] = await db.execute<{ ready: boolean }>(sql`
319
+ select count(*) = 5 as ready from pg_catalog.pg_trigger
320
+ where (tgrelid, tgname) in (
321
+ ('sandbox_retained_processes'::regclass, 'supervised_command_guard'),
322
+ ('sandbox_retained_processes'::regclass, 'supervised_provider_loss_commit_guard'),
323
+ ('sandbox_workspace_mutation_admissions'::regclass, 'supervised_command_admission_guard'),
324
+ ('sandbox_lease_holders'::regclass, 'supervised_command_holder_guard'),
325
+ ('sandbox_leases'::regclass, 'supervised_command_capture_guard')
326
+ ) and tgenabled in ('O', 'A') and not tgisinternal
327
+ `);
328
+ return row?.ready === true;
329
+ }
330
+
331
+ /** Only an authenticated control-channel receipt; never parsed stdout/stderr.
332
+ * ACK the supervisor only after this transaction returns successfully. */
333
+ export async function recordRetainedSupervisionReceipt(
334
+ db: Database,
335
+ scope: ProcessScope,
336
+ receipt: SupervisionReceipt,
337
+ ): Promise<void> {
338
+ const proof = CommandSupervisionReceipt.parse(receipt);
339
+ await withRlsContext(db, scope, async (tx) => {
340
+ const [row] = await tx
341
+ .select()
342
+ .from(schema.sandboxRetainedProcesses)
343
+ .where(processWhere(scope))
344
+ .for("update")
345
+ .limit(1);
346
+ if (!row?.providerCommand || !supervisionDescriptor(row.providerCommand))
347
+ throw new Error("Supervised retained command is unavailable");
348
+ // Trigger validates invocation binding, immutable replay and unsettled input.
349
+ await tx
350
+ .update(schema.sandboxRetainedProcesses)
351
+ .set({ supervisionReceipt: proof })
352
+ .where(processWhere(scope));
353
+ });
354
+ }
355
+
356
+ export async function loadRetainedSupervisionReceipt(
357
+ db: Database,
358
+ scope: ProcessScope,
359
+ ): Promise<SupervisionReceipt | null> {
360
+ return withRlsContext(db, scope, async (tx) => {
361
+ const [row] = await tx
362
+ .select({ receipt: schema.sandboxRetainedProcesses.supervisionReceipt })
363
+ .from(schema.sandboxRetainedProcesses)
364
+ .where(processWhere(scope))
365
+ .limit(1);
366
+ if (!row) throw new Error("Retained command is unavailable");
367
+ return row.receipt ? CommandSupervisionReceipt.parse(row.receipt) : null;
368
+ });
369
+ }
370
+
371
+ export async function requestRetainedProcessCancellation(
372
+ db: Database,
373
+ scope: ProcessScope,
374
+ reason: "provider_deadline" | "explicit_stop",
375
+ ): Promise<void> {
376
+ if (reason !== "provider_deadline" && reason !== "explicit_stop")
377
+ throw new Error("Invalid cancellation reason");
378
+ await withRlsContext(db, scope, async (tx) => {
379
+ const [row] = await tx
380
+ .select()
381
+ .from(schema.sandboxRetainedProcesses)
382
+ .where(processWhere(scope))
383
+ .for("update")
384
+ .limit(1);
385
+ if (!row) throw new Error("Retained command is unavailable");
386
+ if (row.cancellationRequestedAt || row.state !== "active") return;
387
+ await tx
388
+ .update(schema.sandboxRetainedProcesses)
389
+ .set({ cancellationRequestedAt: new Date(), cancellationReason: reason })
390
+ .where(processWhere(scope));
391
+ });
392
+ }
393
+
394
+ export async function retainedProcessCancellationRequested(
395
+ db: Database,
396
+ scope: ProcessScope,
397
+ ): Promise<boolean> {
398
+ return withRlsContext(db, scope, async (tx) => {
399
+ const [row] = await tx
400
+ .select({ at: schema.sandboxRetainedProcesses.cancellationRequestedAt })
401
+ .from(schema.sandboxRetainedProcesses)
402
+ .where(processWhere(scope))
403
+ .limit(1);
404
+ if (!row) throw new Error("Retained command is unavailable");
405
+ return row.at !== null;
406
+ });
407
+ }
408
+
409
+ /** Called by the reaper for an exact retained command. Ordinary completed turns
410
+ * are intentionally irrelevant. Lock order remains process -> lease. */
411
+ export async function requestRetainedProcessDeadlineCancellation(
412
+ db: Database,
413
+ scope: ProcessScope,
414
+ ): Promise<boolean> {
415
+ return withRlsContext(db, scope, async (tx) => {
416
+ const [row] = await tx
417
+ .select()
418
+ .from(schema.sandboxRetainedProcesses)
419
+ .where(processWhere(scope))
420
+ .for("update")
421
+ .limit(1);
422
+ if (
423
+ !row ||
424
+ row.state !== "active" ||
425
+ !row.providerCommand ||
426
+ !supervisionDescriptor(row.providerCommand)
427
+ )
428
+ return false;
429
+ const [lease] = await tx.execute<{ id: string }>(sql`
430
+ select id from sandbox_leases where id = ${row.leaseId}
431
+ and account_id = ${row.accountId} and workspace_id = ${row.workspaceId}
432
+ and sandbox_group_id = ${row.sandboxGroupId} and lease_epoch = ${row.leaseEpoch}
433
+ and backend = ${row.providerBackend} and instance_id = ${row.providerInstanceId}
434
+ and rotation_requested_at is not null and rotation_reason = 'provider_deadline' for update
435
+ `);
436
+ if (!lease) return false;
437
+ if (!row.cancellationRequestedAt)
438
+ await tx
439
+ .update(schema.sandboxRetainedProcesses)
440
+ .set({ cancellationRequestedAt: new Date(), cancellationReason: "provider_deadline" })
441
+ .where(processWhere(scope));
442
+ return true;
166
443
  });
167
444
  }
@@ -0,0 +1,16 @@
1
+ const key = "_opengeni_session_create_host_delegations_v1";
2
+
3
+ /** New creates cannot write a retired authority-selection identity. */
4
+ export function withoutRetiredSessionCreateMetadata(
5
+ metadata: Record<string, unknown>,
6
+ ): Record<string, unknown> {
7
+ const next = { ...metadata };
8
+ delete next[key];
9
+ return next;
10
+ }
11
+
12
+ /** Historical nonempty or malformed selections must not replay as native creates. */
13
+ export function hasRetiredSessionCreateSelection(metadata: Record<string, unknown>): boolean {
14
+ const value = metadata[key];
15
+ return value != null && !(Array.isArray(value) && value.length === 0);
16
+ }