@opengeni/db 1.0.1 → 3.2.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 (271) hide show
  1. package/dist/attached-browser-devices.d.ts +7 -0
  2. package/dist/automations.d.ts +154 -0
  3. package/dist/canonical-human-identities.js +3 -3
  4. package/dist/capability-integrations.d.ts +13 -0
  5. package/dist/child-lifecycle-notices.d.ts +68 -0
  6. package/dist/{chunk-4SR4HKKA.js → chunk-2EH4WRHL.js} +19 -11
  7. package/dist/chunk-2EH4WRHL.js.map +1 -0
  8. package/dist/{chunk-CUPM3FGB.js → chunk-2PRS4J5Q.js} +3 -3
  9. package/dist/chunk-6HMM2R5T.js +390 -0
  10. package/dist/chunk-6HMM2R5T.js.map +1 -0
  11. package/dist/{chunk-ZWREYEWA.js → chunk-AZHW7R5V.js} +56 -11
  12. package/dist/chunk-AZHW7R5V.js.map +1 -0
  13. package/dist/{chunk-LTG3S6ZY.js → chunk-E6CLMKEE.js} +2 -2
  14. package/dist/{chunk-6ZYKCRFO.js → chunk-KRLPEMLH.js} +7591 -4417
  15. package/dist/chunk-KRLPEMLH.js.map +1 -0
  16. package/dist/chunk-NAB6FKFN.js +516 -0
  17. package/dist/chunk-NAB6FKFN.js.map +1 -0
  18. package/dist/{chunk-SK7YYHBI.js → chunk-SIBYBA2D.js} +46 -1
  19. package/dist/chunk-SIBYBA2D.js.map +1 -0
  20. package/dist/chunk-UZNXG44K.js +4508 -0
  21. package/dist/chunk-UZNXG44K.js.map +1 -0
  22. package/dist/codemode-operations.d.ts +1 -6
  23. package/dist/company-brain-context-selection-schema.d.ts +705 -0
  24. package/dist/company-brain-context-selection.d.ts +94 -0
  25. package/dist/company-brain-governed-writes.d.ts +24 -0
  26. package/dist/company-brain.d.ts +55 -0
  27. package/dist/company-profile-agent-admin.d.ts +15 -0
  28. package/dist/company-profile-schema.d.ts +619 -2
  29. package/dist/company-profile.d.ts +9 -4
  30. package/dist/connection-authority.d.ts +95 -0
  31. package/dist/connection-scopes.d.ts +8 -0
  32. package/dist/connection-tenancy-backfill.d.ts +85 -0
  33. package/dist/connection-token-resolver.d.ts +30 -1
  34. package/dist/database.d.ts +23 -4
  35. package/dist/editable-artifact-durable-export.js +2 -2
  36. package/dist/editable-artifacts.d.ts +2 -2
  37. package/dist/editable-artifacts.js +3 -3
  38. package/dist/governed-learning-activation-schema.d.ts +984 -0
  39. package/dist/governed-learning-activation.d.ts +98 -0
  40. package/dist/governed-learning-evaluator-schema.d.ts +633 -0
  41. package/dist/governed-learning-evaluator.d.ts +28 -0
  42. package/dist/index.d.ts +1606 -81
  43. package/dist/index.js +21898 -8147
  44. package/dist/index.js.map +1 -1
  45. package/dist/insights.d.ts +18 -0
  46. package/dist/integration-bindings.d.ts +1 -0
  47. package/dist/integration-facets.d.ts +30 -0
  48. package/dist/interaction-placement-loss.d.ts +22 -0
  49. package/dist/managed-human-provisioning.d.ts +25 -0
  50. package/dist/memory-domain.d.ts +3 -3
  51. package/dist/migrate.d.ts +11 -1
  52. package/dist/migrate.js +1 -1
  53. package/dist/new-session-drafts.d.ts +43 -5
  54. package/dist/organization-membership-backfill.d.ts +174 -0
  55. package/dist/organization-membership-lifecycle.d.ts +162 -0
  56. package/dist/pr-review.d.ts +107 -0
  57. package/dist/preference-registry-schema.d.ts +2 -0
  58. package/dist/preference-registry.d.ts +2 -0
  59. package/dist/provision-roles.js +1 -1
  60. package/dist/runtime-posture.d.ts +29 -8
  61. package/dist/schema.d.ts +24914 -13703
  62. package/dist/schema.js +99 -1
  63. package/dist/scoped-knowledge-schema.d.ts +52 -1
  64. package/dist/session-background-commands.d.ts +125 -0
  65. package/dist/session-background-commands.js +34 -0
  66. package/dist/session-background-commands.js.map +1 -0
  67. package/dist/session-control.d.ts +156 -3
  68. package/dist/session-goal-pacing.d.ts +68 -0
  69. package/dist/session-queue-commands.d.ts +43 -4
  70. package/dist/session-realtime-ledger.d.ts +2 -0
  71. package/dist/session-tenancy.d.ts +71 -1
  72. package/dist/session-tenancy.js +25 -3
  73. package/dist/session-tool-call-settlement.d.ts +9 -4
  74. package/dist/slack-routing-personal-workspace.d.ts +23 -0
  75. package/dist/slack-routing.d.ts +268 -0
  76. package/dist/slack-task-policy-schema.d.ts +34 -0
  77. package/dist/slack-task-policy.d.ts +8 -0
  78. package/dist/slack-user-link-access.d.ts +28 -0
  79. package/dist/task-notes-schema.d.ts +594 -0
  80. package/dist/task-notes.d.ts +39 -0
  81. package/dist/turn-initiator.d.ts +2 -0
  82. package/dist/user-resource-authority.d.ts +109 -0
  83. package/dist/video-generation.js +3 -3
  84. package/dist/workspace-authority.d.ts +81 -0
  85. package/dist/workspace-instruction-policies-schema.d.ts +279 -0
  86. package/dist/workspace-instruction-policies.d.ts +62 -0
  87. package/dist/workspace-learning-policy.d.ts +1 -0
  88. package/dist/workspace-membership-permissions.d.ts +2 -0
  89. package/drizzle/0240_enrollment_connection_authority.sql +39 -0
  90. package/drizzle/0241_atomic_personal_resource_delegation.sql +1000 -0
  91. package/drizzle/0241_enrollment_agent_runtime.sql +70 -0
  92. package/drizzle/0244_slack_app_home_refresh_queue.sql +120 -0
  93. package/drizzle/0245_model_context_contribution_facts.sql +88 -0
  94. package/drizzle/0246_integration_personal_instance_authority.sql +70 -0
  95. package/drizzle/0247_terraform_stacks_provenance_repair.sql +428 -0
  96. package/drizzle/0248_terraform_stacks_component_resolution_fence.sql +83 -0
  97. package/drizzle/0249_personal_resource_delegation_authority_correction.sql +662 -0
  98. package/drizzle/0250_direct_retained_process_owner_liveness.sql +199 -0
  99. package/drizzle/0251_connected_machine_operation_policy.sql +45 -0
  100. package/drizzle/0252_scheduled_personal_resource_delegation.sql +1867 -0
  101. package/drizzle/0253_common_user_resource_authority_lifecycle.sql +1555 -0
  102. package/drizzle/0254_scoped_variable_set_authority.sql +1255 -0
  103. package/drizzle/0255_company_brain_governed_write_proposals.sql +524 -0
  104. package/drizzle/0256_connection_authority_delegation.sql +703 -0
  105. package/drizzle/0257_goal_revision_decisions_and_root_constraints.sql +436 -0
  106. package/drizzle/0258_three_scope_document_knowledge_authority.sql +1273 -0
  107. package/drizzle/0259_company_brain_context_selection_receipts.sql +869 -0
  108. package/drizzle/0260_task_note_knowledge_promotion.sql +820 -0
  109. package/drizzle/0261_preference_knowledge_proposal_actor_binding.sql +471 -0
  110. package/drizzle/0262_scoped_connected_machines_and_rigs.sql +1700 -0
  111. package/drizzle/0263_organization_membership_lifecycle.sql +3284 -0
  112. package/drizzle/0264_connection_authority_runtime_activation.sql +1084 -0
  113. package/drizzle/0266_company_brain_context_receipt_inspection.sql +156 -0
  114. package/drizzle/0268_governed_learning_decision_receipts.sql +825 -0
  115. package/drizzle/0269_governed_learning_activation_controller.sql +1874 -0
  116. package/drizzle/0270_governed_learning_history_inspection.sql +170 -0
  117. package/drizzle/0271_company_brain_retrieval_only_default.sql +524 -0
  118. package/drizzle/0272_human_confirmed_learning_activation.sql +591 -0
  119. package/drizzle/0273_scheduled_variable_set_materialization.sql +268 -0
  120. package/drizzle/0274_human_confirmed_knowledge_review.sql +310 -0
  121. package/drizzle/0275_scheduled_connection_authority.sql +5527 -0
  122. package/drizzle/0276_onboarding_proposal_initiating_human_guc.sql +198 -0
  123. package/drizzle/0277_workspace_writer_authority_attribution.sql +393 -0
  124. package/drizzle/0278_workspace_membership_removal_fencing.sql +1174 -0
  125. package/drizzle/0279_workspace_connection_use_lane.sql +343 -0
  126. package/drizzle/0280_connection_and_variable_set_audit_attribution.sql +773 -0
  127. package/drizzle/0281_viewer_holder_authority_claims.sql +52 -0
  128. package/drizzle/0282_variable_set_session_attach_attribution.sql +178 -0
  129. package/drizzle/0283_editable_spreadsheet_authored_state.sql +82 -0
  130. package/drizzle/0284_truthful_human_confirmed_review_reason.sql +930 -0
  131. package/drizzle/0285_organization_tenancy_inventory.sql +329 -0
  132. package/drizzle/0286_widen_task_note_expiry_ceiling.sql +391 -0
  133. package/drizzle/0287_open_suffix_pending_tool_calls.sql +18 -0
  134. package/drizzle/0288_attached_browser_reenrollment.sql +64 -0
  135. package/drizzle/0289_session_composer_policy_authority.sql +597 -0
  136. package/drizzle/0290_organization_membership_backfill.sql +268 -0
  137. package/drizzle/0291_resource_authority_classification_assertion.sql +371 -0
  138. package/drizzle/0292_truthful_tenancy_inventory_counters.sql +291 -0
  139. package/drizzle/0293_confirm_time_rule_rebaseline.sql +615 -0
  140. package/drizzle/0294_preference_activation_authority.sql +237 -0
  141. package/drizzle/0295_retire_legacy_standing_memory_mode.sql +476 -0
  142. package/drizzle/0296_force_rls_backfill_noop_repair.sql +215 -0
  143. package/drizzle/0297_session_ownership_classification_and_backfill.sql +752 -0
  144. package/drizzle/0298_organization_tenancy_parity.sql +609 -0
  145. package/drizzle/0299_organization_membership_lock_order.sql +291 -0
  146. package/drizzle/0300_tenancy_backfill_ledger.sql +459 -0
  147. package/drizzle/0301_session_snapshot_and_pin_visibility.sql +181 -0
  148. package/drizzle/0302_personal_workspace_session_ownership.sql +303 -0
  149. package/drizzle/0303_session_tenancy_product_activation.sql +919 -0
  150. package/drizzle/0304_personal_workspace_private_session_reads.sql +97 -0
  151. package/drizzle/0305_personal_resource_grant_management.sql +584 -0
  152. package/drizzle/0306_atomic_personal_resource_attachments.sql +1374 -0
  153. package/drizzle/0307_session_attention_state.sql +51 -0
  154. package/drizzle/0308_session_archives.sql +35 -0
  155. package/drizzle/0309_channel_project_pins.sql +6 -0
  156. package/drizzle/0310_channel_project_order.sql +27 -0
  157. package/drizzle/0311_company_scope_and_private_session_create.sql +656 -0
  158. package/drizzle/0312_quiescent_session_tree_deletion.sql +39 -0
  159. package/drizzle/0313_private_child_session_authority.sql +365 -0
  160. package/drizzle/0314_unregistered_organization_invitations.sql +606 -0
  161. package/drizzle/0315_personal_github_repository_selection.sql +624 -0
  162. package/drizzle/0316_human_confirmed_activation_resumed_generation.sql +869 -0
  163. package/drizzle/0317_session_goal_continuation_hold.sql +64 -0
  164. package/drizzle/0318_session_turn_startup_milestones.sql +115 -0
  165. package/drizzle/0319_event_triggered_automations.sql +254 -0
  166. package/drizzle/0320_pr_review_pack.sql +113 -0
  167. package/drizzle/0321_slack_bot_environment_display_name.sql +15 -0
  168. package/drizzle/0322_session_turns_unclaimed_prompt_trigger_index.sql +5 -0
  169. package/drizzle/0323_organization_private_session_enablement.sql +489 -0
  170. package/drizzle/0324_human_confirmed_company_profile_agent_admin.sql +856 -0
  171. package/drizzle/0325_child_lifecycle_notices.sql +44 -0
  172. package/drizzle/0326_interaction_operation_error_codes.sql +62 -0
  173. package/drizzle/0327_slack_first_task_hint.sql +29 -0
  174. package/drizzle/0328_session_background_commands.sql +590 -0
  175. package/drizzle/0329_slack_orchestration_delivery_events.sql +91 -0
  176. package/drizzle/0330_api_key_descriptions.sql +20 -0
  177. package/drizzle/0331_managed_organization_creation.sql +163 -0
  178. package/drizzle/0332_organization_shared_workspace_control_plane.sql +539 -0
  179. package/drizzle/0333_session_turn_prompt_routing.sql +45 -0
  180. package/drizzle/0334_connected_machine_workspace_root.sql +99 -0
  181. package/drizzle/0335_slack_workspace_routing.sql +460 -0
  182. package/drizzle/0336_atomic_session_fork_visibility.sql +667 -0
  183. package/drizzle/0337_slack_routed_action_handles.sql +189 -0
  184. package/drizzle/0338_atomic_connected_machine_attachments.sql +410 -0
  185. package/drizzle/0339_document_authority_reclassification.sql +1153 -0
  186. package/drizzle/0340_tenancy_backfill_activation_evidence.sql +1347 -0
  187. package/drizzle/0341_slack_routing_probe_organization_fence.sql +109 -0
  188. package/drizzle/0342_slack_route_prompt_single_pending.sql +32 -0
  189. package/drizzle/0343_personal_document_force_rls_lock_repair.sql +146 -0
  190. package/drizzle/0344_private_session_visibility_transition_gate.sql +85 -0
  191. package/drizzle/0345_tenant_scoped_session_tenancy_fence.sql +2839 -0
  192. package/drizzle/0346_document_migration_audit_surface.sql +454 -0
  193. package/drizzle/0347_connection_authority_convergence_evidence.sql +396 -0
  194. package/package.json +10 -6
  195. package/src/attached-browser-devices.ts +233 -5
  196. package/src/automations.ts +911 -0
  197. package/src/browser-sessions.ts +10 -0
  198. package/src/capability-integrations.ts +175 -1
  199. package/src/child-lifecycle-notices.ts +241 -0
  200. package/src/codemode-operations.ts +1 -35
  201. package/src/company-brain-context-selection-schema.ts +100 -0
  202. package/src/company-brain-context-selection.ts +359 -0
  203. package/src/company-brain-governed-writes.ts +1170 -0
  204. package/src/company-brain.ts +309 -0
  205. package/src/company-profile-agent-admin.ts +225 -0
  206. package/src/company-profile-schema.ts +121 -1
  207. package/src/company-profile.ts +21 -0
  208. package/src/computer-sessions.ts +10 -1
  209. package/src/connection-authority.ts +290 -0
  210. package/src/connection-scopes.ts +20 -0
  211. package/src/connection-tenancy-backfill.ts +167 -0
  212. package/src/connection-token-resolver.ts +263 -31
  213. package/src/database.ts +87 -2
  214. package/src/editable-artifacts-schema.ts +10 -5
  215. package/src/editable-artifacts.ts +21 -11
  216. package/src/governed-learning-activation-schema.ts +121 -0
  217. package/src/governed-learning-activation.ts +588 -0
  218. package/src/governed-learning-evaluator-schema.ts +72 -0
  219. package/src/governed-learning-evaluator.ts +217 -0
  220. package/src/index.ts +11676 -1550
  221. package/src/insights.ts +107 -0
  222. package/src/integration-bindings.ts +88 -6
  223. package/src/integration-facets.ts +287 -84
  224. package/src/interaction-placement-loss.ts +234 -0
  225. package/src/managed-human-provisioning.ts +116 -0
  226. package/src/memory-domain.ts +27 -32
  227. package/src/migrate.ts +77 -1
  228. package/src/new-session-drafts.ts +229 -35
  229. package/src/organization-membership-backfill.ts +735 -0
  230. package/src/organization-membership-lifecycle.ts +995 -0
  231. package/src/pr-review.ts +890 -0
  232. package/src/preference-registry.ts +31 -1
  233. package/src/provision-roles.ts +905 -6
  234. package/src/runtime-posture-cli.ts +2 -0
  235. package/src/runtime-posture.ts +1317 -72
  236. package/src/schema.ts +3316 -428
  237. package/src/scoped-knowledge-schema.ts +16 -8
  238. package/src/scoped-knowledge.ts +1 -1
  239. package/src/session-background-commands.ts +759 -0
  240. package/src/session-control.ts +640 -74
  241. package/src/session-goal-pacing.ts +126 -0
  242. package/src/session-queue-commands.ts +441 -85
  243. package/src/session-realtime-context.ts +4 -6
  244. package/src/session-realtime-ledger.ts +28 -14
  245. package/src/session-realtime-mirror.ts +1 -1
  246. package/src/session-tenancy.ts +410 -49
  247. package/src/session-tool-call-settlement.ts +38 -29
  248. package/src/slack-routing-personal-workspace.ts +67 -0
  249. package/src/slack-routing.ts +867 -0
  250. package/src/slack-task-policy-schema.ts +5 -0
  251. package/src/slack-task-policy.ts +18 -0
  252. package/src/slack-user-link-access.ts +138 -11
  253. package/src/task-notes-schema.ts +74 -0
  254. package/src/task-notes.ts +124 -2
  255. package/src/turn-initiator.ts +8 -0
  256. package/src/user-resource-authority.ts +377 -0
  257. package/src/workspace-authority.ts +160 -0
  258. package/src/workspace-instruction-policies-schema.ts +53 -1
  259. package/src/workspace-instruction-policies.ts +528 -77
  260. package/src/workspace-learning-policy.ts +21 -5
  261. package/src/workspace-membership-permissions.ts +9 -0
  262. package/dist/chunk-4SR4HKKA.js.map +0 -1
  263. package/dist/chunk-6ZYKCRFO.js.map +0 -1
  264. package/dist/chunk-NXAFLCQX.js +0 -2468
  265. package/dist/chunk-NXAFLCQX.js.map +0 -1
  266. package/dist/chunk-SK7YYHBI.js.map +0 -1
  267. package/dist/chunk-WD5ROSLL.js +0 -117
  268. package/dist/chunk-WD5ROSLL.js.map +0 -1
  269. package/dist/chunk-ZWREYEWA.js.map +0 -1
  270. /package/dist/{chunk-CUPM3FGB.js.map → chunk-2PRS4J5Q.js.map} +0 -0
  271. /package/dist/{chunk-LTG3S6ZY.js.map → chunk-E6CLMKEE.js.map} +0 -0
@@ -0,0 +1,64 @@
1
+ -- deployment-mode: rolling
2
+ SET lock_timeout = '5s';
3
+ SET statement_timeout = '10min';
4
+
5
+ -- Agent-declared goal continuation hold.
6
+ --
7
+ -- An orchestrator whose active goal depends on child sessions or an external
8
+ -- event can call the first-party `goal_wait` tool instead of busy-polling. The
9
+ -- hold is additive state on the goal row: the exact turn that declared it, the
10
+ -- mandatory deadline, a bounded reason, and when it was recorded. The
11
+ -- continuation materializer honors the hold only while the declaring turn is
12
+ -- still the latest finished turn and the deadline has not passed; it never
13
+ -- consumes the wake/observed revision ledger, so a crash cannot lose the
14
+ -- obligation. Any newer finished turn, a passed deadline, or a human/API/agent
15
+ -- goal mutation clears all four columns together.
16
+ --
17
+ -- An old worker that ignores these columns keeps the prior behaviour
18
+ -- (immediate continuation), so this is a rolling, additive change with no
19
+ -- backfill.
20
+
21
+ ALTER TABLE "session_goals"
22
+ ADD COLUMN IF NOT EXISTS "continuation_hold_turn_id" uuid,
23
+ ADD COLUMN IF NOT EXISTS "continuation_hold_until" timestamptz,
24
+ ADD COLUMN IF NOT EXISTS "continuation_hold_reason" text,
25
+ ADD COLUMN IF NOT EXISTS "continuation_hold_set_at" timestamptz;
26
+
27
+ DO $constraints$
28
+ BEGIN
29
+ IF NOT EXISTS (
30
+ SELECT 1 FROM pg_constraint
31
+ WHERE conname = 'session_goals_continuation_hold_check'
32
+ AND conrelid = 'session_goals'::regclass
33
+ ) THEN
34
+ ALTER TABLE "session_goals"
35
+ ADD CONSTRAINT "session_goals_continuation_hold_check"
36
+ CHECK (
37
+ (
38
+ "continuation_hold_turn_id" IS NULL
39
+ AND "continuation_hold_until" IS NULL
40
+ AND "continuation_hold_reason" IS NULL
41
+ AND "continuation_hold_set_at" IS NULL
42
+ )
43
+ OR (
44
+ "continuation_hold_turn_id" IS NOT NULL
45
+ AND "continuation_hold_until" IS NOT NULL
46
+ AND "continuation_hold_set_at" IS NOT NULL
47
+ AND (
48
+ "continuation_hold_reason" IS NULL
49
+ OR octet_length("continuation_hold_reason") <= 2048
50
+ )
51
+ )
52
+ );
53
+ END IF;
54
+ END
55
+ $constraints$;
56
+
57
+ COMMENT ON COLUMN "session_goals"."continuation_hold_turn_id" IS
58
+ 'Exact turn that declared the goal_wait hold; the hold applies only while this is the latest finished turn.';
59
+ COMMENT ON COLUMN "session_goals"."continuation_hold_until" IS
60
+ 'Mandatory hold deadline; the materializer re-arms a delayed workflow wake at this time and clears the hold once it passes.';
61
+ COMMENT ON COLUMN "session_goals"."continuation_hold_reason" IS
62
+ 'Bounded (2 KiB) agent-declared reason for the hold.';
63
+ COMMENT ON COLUMN "session_goals"."continuation_hold_set_at" IS
64
+ 'When the hold was recorded.';
@@ -0,0 +1,115 @@
1
+ -- deployment-mode: rolling
2
+ -- Per-turn startup-milestone ledger.
3
+ --
4
+ -- The turn-startup SLO receipts (queue, provider_dispatch, first_byte) used to
5
+ -- be decided by re-reading the turn's `session_events` rows on every inserted
6
+ -- `turn.started`, `agent.model.request started|first_byte|first_event`, and
7
+ -- `turn.failed` event: "is the event this transaction just inserted the
8
+ -- lowest-sequence canonical checkpoint of its kind in the turn?". That lookup
9
+ -- is O(events in the turn) per model request, each examined row pays the
10
+ -- session-events RLS predicate, and it runs inside the event-append
11
+ -- transaction that holds the workspace inference-control row FOR SHARE. On a
12
+ -- long orchestrator turn it held that row for tens of seconds per model
13
+ -- request and starved every FOR UPDATE taker (Send/Steer/Pause).
14
+ --
15
+ -- This table makes "the first inserter of each checkpoint wins" a single
16
+ -- primary-key probe: the transaction that appends a checkpoint event performs
17
+ -- `INSERT ... ON CONFLICT DO NOTHING RETURNING`, and only a returned row is a
18
+ -- metric receipt. Ordinary attempt recovery and callback replay conflict and
19
+ -- stay no-ops, exactly as before. Writers already hold the turn row FOR UPDATE
20
+ -- (the canonical event-write lock order), so the conflict clause is
21
+ -- idempotency, not a race resolver.
22
+ --
23
+ -- Rollout: turns whose `turn.started` was already durable before a
24
+ -- ledger-aware writer touched them (in flight across the deploy, or claimed by
25
+ -- a pre-ledger worker during the rolling window) are recognised at their next
26
+ -- `turn.started` claim through one bounded index probe for an earlier current
27
+ -- `turn.started` row, and sealed with `pre_ledger_history` sentinel rows for
28
+ -- every completed checkpoint. Such a turn emits no further startup receipts
29
+ -- (it already observed them, or may have) instead of re-observing a checkpoint
30
+ -- with a duration equal to its age. No migration-time backfill over
31
+ -- FORCE-RLS tables is required.
32
+
33
+ SET LOCAL lock_timeout = '5s';
34
+ SET LOCAL statement_timeout = '10min';
35
+
36
+ CREATE TABLE "session_turn_startup_milestones" (
37
+ "account_id" uuid NOT NULL,
38
+ "workspace_id" uuid NOT NULL,
39
+ "session_id" uuid NOT NULL,
40
+ "turn_id" uuid NOT NULL,
41
+ "milestone" text NOT NULL,
42
+ "outcome" text NOT NULL,
43
+ "canonical_source" text NOT NULL,
44
+ "event_id" uuid,
45
+ "occurred_at" timestamptz,
46
+ "created_at" timestamptz NOT NULL DEFAULT now(),
47
+ CONSTRAINT "session_turn_startup_milestones_pkey"
48
+ PRIMARY KEY ("workspace_id", "turn_id", "milestone", "outcome"),
49
+ CONSTRAINT "session_turn_startup_milestones_workspace_account_fk"
50
+ FOREIGN KEY ("workspace_id", "account_id")
51
+ REFERENCES "workspaces"("id", "account_id") ON DELETE CASCADE,
52
+ CONSTRAINT "session_turn_startup_milestones_workspace_session_fk"
53
+ FOREIGN KEY ("workspace_id", "session_id")
54
+ REFERENCES "sessions"("workspace_id", "id") ON DELETE CASCADE,
55
+ CONSTRAINT "session_turn_startup_milestones_workspace_turn_fk"
56
+ FOREIGN KEY ("workspace_id", "turn_id")
57
+ REFERENCES "session_turns"("workspace_id", "id") ON DELETE CASCADE,
58
+ CONSTRAINT "session_turn_startup_milestones_milestone_chk"
59
+ CHECK ("milestone" IN ('queue', 'provider_dispatch', 'first_byte')),
60
+ CONSTRAINT "session_turn_startup_milestones_outcome_chk"
61
+ CHECK ("outcome" IN ('completed', 'failed')),
62
+ CONSTRAINT "session_turn_startup_milestones_checkpoint_chk"
63
+ CHECK ("outcome" = 'completed' OR "milestone" = 'first_byte'),
64
+ CONSTRAINT "session_turn_startup_milestones_canonical_source_chk" CHECK (
65
+ (
66
+ "canonical_source" = 'inserted_event'
67
+ AND "event_id" IS NOT NULL
68
+ AND "occurred_at" IS NOT NULL
69
+ )
70
+ OR (
71
+ "canonical_source" = 'pre_ledger_history'
72
+ AND "outcome" = 'completed'
73
+ AND "event_id" IS NULL
74
+ AND "occurred_at" IS NULL
75
+ )
76
+ )
77
+ );
78
+
79
+ -- The session FK cascade must not sequentially scan the ledger per deleted
80
+ -- session; the turn and workspace FKs are covered by the primary-key prefix.
81
+ CREATE INDEX "session_turn_startup_milestones_workspace_session_idx"
82
+ ON "session_turn_startup_milestones" ("workspace_id", "session_id");
83
+
84
+ ALTER TABLE "session_turn_startup_milestones" ENABLE ROW LEVEL SECURITY;
85
+ ALTER TABLE "session_turn_startup_milestones" FORCE ROW LEVEL SECURITY;
86
+ CREATE POLICY workspace_isolation ON "session_turn_startup_milestones"
87
+ USING (opengeni_private.workspace_rls_visible("account_id", "workspace_id"))
88
+ WITH CHECK (opengeni_private.workspace_rls_visible("account_id", "workspace_id"));
89
+ CREATE POLICY session_visibility_isolation ON "session_turn_startup_milestones"
90
+ AS RESTRICTIVE
91
+ USING (session_reference_visible(
92
+ "account_id", "workspace_id", "session_id"
93
+ ))
94
+ WITH CHECK (session_reference_visible(
95
+ "account_id", "workspace_id", "session_id"
96
+ ));
97
+
98
+ -- The runtime role claims (INSERT), fences (SELECT), and seals pre-ledger turns
99
+ -- (UPDATE of the turn's own queue row); rows leave only through the turn
100
+ -- cascade. `db:provision-roles` re-converges the same posture.
101
+ DO $grants$
102
+ BEGIN
103
+ IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'opengeni_app') THEN
104
+ GRANT SELECT, INSERT, UPDATE ON "session_turn_startup_milestones" TO opengeni_app;
105
+ REVOKE DELETE ON "session_turn_startup_milestones" FROM opengeni_app;
106
+ END IF;
107
+ END
108
+ $grants$;
109
+
110
+ COMMENT ON TABLE "session_turn_startup_milestones" IS
111
+ 'Per-turn startup SLO checkpoint ledger: one row per (turn, milestone, outcome). The transaction whose INSERT ... ON CONFLICT DO NOTHING returns the row is the canonical inserter and the sole metric receipt; recovery and replay conflict. pre_ledger_history rows seal a turn whose startup predates the ledger so it never re-observes a checkpoint.';
112
+ COMMENT ON COLUMN "session_turn_startup_milestones"."canonical_source" IS
113
+ 'inserted_event: event_id/occurred_at name the canonical checkpoint event inserted by the claiming transaction. pre_ledger_history: the checkpoint was (or may have been) durable before any ledger-aware writer touched the turn; identity is deliberately not recovered from session_events.';
114
+ COMMENT ON COLUMN "session_turn_startup_milestones"."occurred_at" IS
115
+ 'The canonical event''s own occurred_at; the receipt duration is measured from session_turns.created_at to this instant.';
@@ -0,0 +1,254 @@
1
+ -- deployment-mode: rolling
2
+ -- Generic event-triggered automations. Sources authenticate ingress, immutable
3
+ -- trigger revisions own matching/session templates, events retain normalized
4
+ -- occurrence truth, and runs freeze the exact session execution admitted for
5
+ -- one logical occurrence. Agent execution remains an ordinary session.
6
+
7
+ SET LOCAL lock_timeout = '5s';
8
+ SET LOCAL statement_timeout = '10min';
9
+
10
+ CREATE UNIQUE INDEX IF NOT EXISTS pack_installations_workspace_id_uq
11
+ ON pack_installations(workspace_id, id);
12
+
13
+ CREATE TABLE automation_sources (
14
+ id uuid PRIMARY KEY DEFAULT pg_catalog.gen_random_uuid(),
15
+ endpoint_id uuid NOT NULL DEFAULT pg_catalog.gen_random_uuid(),
16
+ account_id uuid NOT NULL REFERENCES managed_accounts(id) ON DELETE CASCADE,
17
+ workspace_id uuid NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
18
+ name text NOT NULL,
19
+ adapter_id text NOT NULL,
20
+ configuration jsonb NOT NULL DEFAULT '{}'::jsonb,
21
+ webhook_secret_encrypted text NOT NULL,
22
+ status text NOT NULL DEFAULT 'active',
23
+ version integer NOT NULL DEFAULT 1,
24
+ pack_installation_id uuid,
25
+ pack_connector_id text,
26
+ created_by_subject_id text NOT NULL,
27
+ created_at timestamptz NOT NULL DEFAULT now(),
28
+ updated_at timestamptz NOT NULL DEFAULT now(),
29
+ CONSTRAINT automation_sources_workspace_account_fk FOREIGN KEY (workspace_id, account_id)
30
+ REFERENCES workspaces(id, account_id) ON DELETE CASCADE,
31
+ CONSTRAINT automation_sources_pack_installation_fk
32
+ FOREIGN KEY (workspace_id, pack_installation_id)
33
+ REFERENCES pack_installations(workspace_id, id) ON DELETE CASCADE,
34
+ CONSTRAINT automation_sources_shape_chk CHECK (
35
+ status IN ('active', 'disabled') AND version > 0
36
+ AND octet_length(name) BETWEEN 1 AND 512
37
+ AND octet_length(adapter_id) BETWEEN 1 AND 128
38
+ AND octet_length(created_by_subject_id) BETWEEN 1 AND 4096
39
+ AND jsonb_typeof(configuration) = 'object'
40
+ AND ((pack_installation_id IS NULL AND pack_connector_id IS NULL)
41
+ OR (pack_installation_id IS NOT NULL
42
+ AND octet_length(pack_connector_id) BETWEEN 1 AND 128))
43
+ )
44
+ );
45
+ CREATE UNIQUE INDEX automation_sources_endpoint_uq ON automation_sources(endpoint_id);
46
+ CREATE UNIQUE INDEX automation_sources_workspace_id_uq ON automation_sources(workspace_id, id);
47
+ CREATE INDEX automation_sources_workspace_status_idx ON automation_sources(workspace_id, status);
48
+
49
+ -- Credential-free routing only. The endpoint UUID discovers the tenant/source;
50
+ -- the FORCE-RLS source row and its encrypted secret still authenticate ingress.
51
+ CREATE TABLE automation_webhook_endpoints (
52
+ endpoint_id uuid PRIMARY KEY,
53
+ account_id uuid NOT NULL REFERENCES managed_accounts(id) ON DELETE CASCADE,
54
+ workspace_id uuid NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
55
+ source_id uuid NOT NULL UNIQUE REFERENCES automation_sources(id) ON DELETE CASCADE,
56
+ created_at timestamptz NOT NULL DEFAULT now(),
57
+ CONSTRAINT automation_webhook_endpoints_workspace_account_fk FOREIGN KEY (workspace_id, account_id)
58
+ REFERENCES workspaces(id, account_id) ON DELETE CASCADE
59
+ );
60
+
61
+ CREATE TABLE automation_triggers (
62
+ id uuid PRIMARY KEY DEFAULT pg_catalog.gen_random_uuid(),
63
+ account_id uuid NOT NULL REFERENCES managed_accounts(id) ON DELETE CASCADE,
64
+ workspace_id uuid NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
65
+ source_id uuid NOT NULL,
66
+ name text NOT NULL,
67
+ status text NOT NULL DEFAULT 'active',
68
+ current_revision integer NOT NULL DEFAULT 1,
69
+ pack_installation_id uuid,
70
+ pack_template_id text,
71
+ created_by_subject_id text NOT NULL,
72
+ created_at timestamptz NOT NULL DEFAULT now(),
73
+ updated_at timestamptz NOT NULL DEFAULT now(),
74
+ CONSTRAINT automation_triggers_workspace_account_fk FOREIGN KEY (workspace_id, account_id)
75
+ REFERENCES workspaces(id, account_id) ON DELETE CASCADE,
76
+ CONSTRAINT automation_triggers_source_fk FOREIGN KEY (workspace_id, source_id)
77
+ REFERENCES automation_sources(workspace_id, id) ON DELETE CASCADE,
78
+ CONSTRAINT automation_triggers_pack_installation_fk
79
+ FOREIGN KEY (workspace_id, pack_installation_id)
80
+ REFERENCES pack_installations(workspace_id, id) ON DELETE CASCADE,
81
+ CONSTRAINT automation_triggers_shape_chk CHECK (
82
+ status IN ('active', 'paused', 'disabled') AND current_revision > 0
83
+ AND octet_length(name) BETWEEN 1 AND 512
84
+ AND octet_length(created_by_subject_id) BETWEEN 1 AND 4096
85
+ AND ((pack_installation_id IS NULL AND pack_template_id IS NULL)
86
+ OR (pack_installation_id IS NOT NULL AND octet_length(pack_template_id) BETWEEN 1 AND 128))
87
+ )
88
+ );
89
+ CREATE UNIQUE INDEX automation_triggers_workspace_id_uq ON automation_triggers(workspace_id, id);
90
+ CREATE UNIQUE INDEX automation_triggers_workspace_source_id_uq
91
+ ON automation_triggers(workspace_id, id, source_id);
92
+ CREATE INDEX automation_triggers_workspace_status_idx ON automation_triggers(workspace_id, status);
93
+
94
+ CREATE TABLE automation_trigger_revisions (
95
+ trigger_id uuid NOT NULL,
96
+ revision integer NOT NULL,
97
+ account_id uuid NOT NULL,
98
+ workspace_id uuid NOT NULL,
99
+ adapter_id text NOT NULL,
100
+ event_types jsonb NOT NULL,
101
+ configuration jsonb NOT NULL DEFAULT '{}'::jsonb,
102
+ parameters jsonb NOT NULL DEFAULT '{}'::jsonb,
103
+ session_template jsonb NOT NULL,
104
+ created_by_subject_id text NOT NULL,
105
+ created_at timestamptz NOT NULL DEFAULT now(),
106
+ PRIMARY KEY (trigger_id, revision),
107
+ CONSTRAINT automation_trigger_revisions_trigger_fk FOREIGN KEY (workspace_id, trigger_id)
108
+ REFERENCES automation_triggers(workspace_id, id) ON DELETE CASCADE,
109
+ CONSTRAINT automation_trigger_revisions_workspace_account_fk FOREIGN KEY (workspace_id, account_id)
110
+ REFERENCES workspaces(id, account_id) ON DELETE CASCADE,
111
+ CONSTRAINT automation_trigger_revisions_shape_chk CHECK (
112
+ revision > 0 AND octet_length(adapter_id) BETWEEN 1 AND 128
113
+ AND jsonb_typeof(event_types) = 'array' AND jsonb_array_length(event_types) BETWEEN 1 AND 64
114
+ AND jsonb_typeof(configuration) = 'object'
115
+ AND jsonb_typeof(parameters) = 'object'
116
+ AND jsonb_typeof(session_template) = 'object'
117
+ )
118
+ );
119
+
120
+ CREATE TABLE automation_trigger_events (
121
+ id uuid PRIMARY KEY DEFAULT pg_catalog.gen_random_uuid(),
122
+ account_id uuid NOT NULL,
123
+ workspace_id uuid NOT NULL,
124
+ source_id uuid NOT NULL,
125
+ source_version integer NOT NULL,
126
+ source_configuration jsonb NOT NULL,
127
+ matched_trigger_revisions jsonb NOT NULL,
128
+ delivery_key text NOT NULL,
129
+ request_digest text NOT NULL,
130
+ adapter_id text NOT NULL,
131
+ event_type text NOT NULL,
132
+ occurrence_key text NOT NULL,
133
+ normalized_event jsonb NOT NULL,
134
+ status text NOT NULL DEFAULT 'accepted',
135
+ ignored_reason text,
136
+ error_code text,
137
+ created_at timestamptz NOT NULL DEFAULT now(),
138
+ updated_at timestamptz NOT NULL DEFAULT now(),
139
+ CONSTRAINT automation_trigger_events_source_fk FOREIGN KEY (workspace_id, source_id)
140
+ REFERENCES automation_sources(workspace_id, id) ON DELETE CASCADE,
141
+ CONSTRAINT automation_trigger_events_workspace_account_fk FOREIGN KEY (workspace_id, account_id)
142
+ REFERENCES workspaces(id, account_id) ON DELETE CASCADE,
143
+ CONSTRAINT automation_trigger_events_shape_chk CHECK (
144
+ status IN ('accepted', 'ignored', 'failed')
145
+ AND source_version > 0
146
+ AND jsonb_typeof(source_configuration) = 'object'
147
+ AND jsonb_typeof(matched_trigger_revisions) = 'array'
148
+ AND jsonb_array_length(matched_trigger_revisions) <= 32
149
+ AND request_digest ~ '^[0-9a-f]{64}$'
150
+ AND octet_length(delivery_key) BETWEEN 1 AND 1024
151
+ AND octet_length(event_type) BETWEEN 1 AND 256
152
+ AND octet_length(occurrence_key) BETWEEN 1 AND 1024
153
+ AND jsonb_typeof(normalized_event) = 'object'
154
+ )
155
+ );
156
+ CREATE UNIQUE INDEX automation_trigger_events_source_delivery_uq
157
+ ON automation_trigger_events(source_id, delivery_key);
158
+ CREATE INDEX automation_trigger_events_workspace_created_idx
159
+ ON automation_trigger_events(workspace_id, created_at);
160
+ CREATE UNIQUE INDEX automation_trigger_events_workspace_source_id_uq
161
+ ON automation_trigger_events(workspace_id, source_id, id);
162
+
163
+ CREATE TABLE automation_runs (
164
+ id uuid PRIMARY KEY DEFAULT pg_catalog.gen_random_uuid(),
165
+ account_id uuid NOT NULL,
166
+ workspace_id uuid NOT NULL,
167
+ source_id uuid NOT NULL,
168
+ trigger_id uuid NOT NULL,
169
+ trigger_revision integer NOT NULL,
170
+ event_id uuid NOT NULL,
171
+ occurrence_key text NOT NULL,
172
+ accepted_execution jsonb NOT NULL,
173
+ status text NOT NULL DEFAULT 'queued',
174
+ session_id uuid REFERENCES sessions(id) ON DELETE SET NULL,
175
+ error_code text,
176
+ created_at timestamptz NOT NULL DEFAULT now(),
177
+ updated_at timestamptz NOT NULL DEFAULT now(),
178
+ CONSTRAINT automation_runs_trigger_revision_fk FOREIGN KEY (trigger_id, trigger_revision)
179
+ REFERENCES automation_trigger_revisions(trigger_id, revision) ON DELETE RESTRICT,
180
+ CONSTRAINT automation_runs_source_fk FOREIGN KEY (workspace_id, source_id)
181
+ REFERENCES automation_sources(workspace_id, id) ON DELETE RESTRICT,
182
+ CONSTRAINT automation_runs_trigger_source_fk FOREIGN KEY (workspace_id, trigger_id, source_id)
183
+ REFERENCES automation_triggers(workspace_id, id, source_id) ON DELETE RESTRICT,
184
+ CONSTRAINT automation_runs_event_fk FOREIGN KEY (workspace_id, source_id, event_id)
185
+ REFERENCES automation_trigger_events(workspace_id, source_id, id) ON DELETE RESTRICT,
186
+ CONSTRAINT automation_runs_workspace_account_fk FOREIGN KEY (workspace_id, account_id)
187
+ REFERENCES workspaces(id, account_id) ON DELETE CASCADE,
188
+ CONSTRAINT automation_runs_shape_chk CHECK (
189
+ trigger_revision > 0
190
+ AND status IN ('queued', 'dispatching', 'dispatched', 'skipped', 'failed')
191
+ AND octet_length(occurrence_key) BETWEEN 1 AND 1024
192
+ AND jsonb_typeof(accepted_execution) = 'object'
193
+ )
194
+ );
195
+ CREATE UNIQUE INDEX automation_runs_trigger_occurrence_uq
196
+ ON automation_runs(trigger_id, occurrence_key);
197
+ CREATE INDEX automation_runs_workspace_status_idx
198
+ ON automation_runs(workspace_id, status, created_at);
199
+ CREATE UNIQUE INDEX automation_runs_workspace_trigger_id_uq
200
+ ON automation_runs(workspace_id, trigger_id, id);
201
+
202
+ CREATE TABLE automation_run_event_links (
203
+ run_id uuid NOT NULL REFERENCES automation_runs(id) ON DELETE CASCADE,
204
+ event_id uuid NOT NULL REFERENCES automation_trigger_events(id) ON DELETE CASCADE,
205
+ account_id uuid NOT NULL,
206
+ workspace_id uuid NOT NULL,
207
+ source_id uuid NOT NULL,
208
+ trigger_id uuid NOT NULL,
209
+ created_at timestamptz NOT NULL DEFAULT now(),
210
+ PRIMARY KEY (run_id, event_id),
211
+ CONSTRAINT automation_run_event_links_workspace_account_fk FOREIGN KEY (workspace_id, account_id)
212
+ REFERENCES workspaces(id, account_id) ON DELETE CASCADE,
213
+ CONSTRAINT automation_run_event_links_run_fk FOREIGN KEY (workspace_id, trigger_id, run_id)
214
+ REFERENCES automation_runs(workspace_id, trigger_id, id) ON DELETE CASCADE,
215
+ CONSTRAINT automation_run_event_links_event_fk FOREIGN KEY (workspace_id, source_id, event_id)
216
+ REFERENCES automation_trigger_events(workspace_id, source_id, id) ON DELETE CASCADE
217
+ );
218
+ CREATE UNIQUE INDEX automation_run_event_links_event_trigger_uq
219
+ ON automation_run_event_links(event_id, trigger_id);
220
+
221
+ ALTER TABLE automation_sources ENABLE ROW LEVEL SECURITY;
222
+ ALTER TABLE automation_sources FORCE ROW LEVEL SECURITY;
223
+ ALTER TABLE automation_triggers ENABLE ROW LEVEL SECURITY;
224
+ ALTER TABLE automation_triggers FORCE ROW LEVEL SECURITY;
225
+ ALTER TABLE automation_trigger_revisions ENABLE ROW LEVEL SECURITY;
226
+ ALTER TABLE automation_trigger_revisions FORCE ROW LEVEL SECURITY;
227
+ ALTER TABLE automation_trigger_events ENABLE ROW LEVEL SECURITY;
228
+ ALTER TABLE automation_trigger_events FORCE ROW LEVEL SECURITY;
229
+ ALTER TABLE automation_runs ENABLE ROW LEVEL SECURITY;
230
+ ALTER TABLE automation_runs FORCE ROW LEVEL SECURITY;
231
+ ALTER TABLE automation_run_event_links ENABLE ROW LEVEL SECURITY;
232
+ ALTER TABLE automation_run_event_links FORCE ROW LEVEL SECURITY;
233
+
234
+ CREATE POLICY automation_sources_tenant ON automation_sources
235
+ USING (opengeni_private.workspace_rls_visible(account_id, workspace_id))
236
+ WITH CHECK (opengeni_private.workspace_rls_visible(account_id, workspace_id));
237
+ CREATE POLICY automation_triggers_tenant ON automation_triggers
238
+ USING (opengeni_private.workspace_rls_visible(account_id, workspace_id))
239
+ WITH CHECK (opengeni_private.workspace_rls_visible(account_id, workspace_id));
240
+ CREATE POLICY automation_trigger_revisions_tenant ON automation_trigger_revisions
241
+ USING (opengeni_private.workspace_rls_visible(account_id, workspace_id))
242
+ WITH CHECK (opengeni_private.workspace_rls_visible(account_id, workspace_id));
243
+ CREATE POLICY automation_trigger_events_tenant ON automation_trigger_events
244
+ USING (opengeni_private.workspace_rls_visible(account_id, workspace_id))
245
+ WITH CHECK (opengeni_private.workspace_rls_visible(account_id, workspace_id));
246
+ CREATE POLICY automation_runs_tenant ON automation_runs
247
+ USING (opengeni_private.workspace_rls_visible(account_id, workspace_id))
248
+ WITH CHECK (opengeni_private.workspace_rls_visible(account_id, workspace_id));
249
+ CREATE POLICY automation_run_event_links_tenant ON automation_run_event_links
250
+ USING (opengeni_private.workspace_rls_visible(account_id, workspace_id))
251
+ WITH CHECK (opengeni_private.workspace_rls_visible(account_id, workspace_id));
252
+ CREATE POLICY session_visibility_isolation ON automation_runs AS RESTRICTIVE
253
+ USING (session_reference_visible(account_id, workspace_id, session_id))
254
+ WITH CHECK (session_reference_visible(account_id, workspace_id, session_id));
@@ -0,0 +1,113 @@
1
+ -- deployment-mode: rolling
2
+ SET lock_timeout = '5s';
3
+ SET statement_timeout = '60s';
4
+
5
+ -- The PR Review Pack is a provider-neutral adapter over the generic automation
6
+ -- substrate. App registrations own only provider action credentials; generic
7
+ -- automation sources own webhook authentication and generic triggers/runs own
8
+ -- event matching, idempotency, and ordinary-session dispatch.
9
+
10
+ CREATE TABLE "pr_review_app_registrations" (
11
+ "id" uuid PRIMARY KEY DEFAULT pg_catalog.gen_random_uuid(),
12
+ "source_id" uuid NOT NULL,
13
+ "account_id" uuid NOT NULL REFERENCES "managed_accounts"("id") ON DELETE CASCADE,
14
+ "workspace_id" uuid NOT NULL REFERENCES "workspaces"("id") ON DELETE CASCADE,
15
+ "name" text NOT NULL,
16
+ "provider" text NOT NULL,
17
+ "provider_base_url" text NOT NULL,
18
+ "app_id" text,
19
+ "credential_kind" text NOT NULL,
20
+ "credential_encrypted" text,
21
+ "access_token_expires_at" timestamptz,
22
+ "webhook_auth_kind" text NOT NULL,
23
+ "webhook_username" text,
24
+ "status" text NOT NULL DEFAULT 'active',
25
+ "created_by_subject_id" text NOT NULL,
26
+ "created_at" timestamptz NOT NULL DEFAULT now(),
27
+ "updated_at" timestamptz NOT NULL DEFAULT now(),
28
+ CONSTRAINT "pr_review_app_registrations_workspace_account_fk"
29
+ FOREIGN KEY ("workspace_id", "account_id")
30
+ REFERENCES "workspaces"("id", "account_id") ON DELETE CASCADE,
31
+ CONSTRAINT "pr_review_app_registrations_source_fk"
32
+ FOREIGN KEY ("workspace_id", "source_id")
33
+ REFERENCES "automation_sources"("workspace_id", "id") ON DELETE CASCADE,
34
+ CONSTRAINT "pr_review_app_registrations_provider_chk"
35
+ CHECK ("provider" IN ('github', 'gitlab', 'azure_devops')),
36
+ CONSTRAINT "pr_review_app_registrations_credential_chk" CHECK (
37
+ ("provider" = 'github' AND "credential_kind" = 'github_app' AND "credential_encrypted" IS NOT NULL AND "app_id" IS NOT NULL)
38
+ OR
39
+ ("provider" IN ('gitlab', 'azure_devops') AND "credential_kind" = 'provider_token' AND "credential_encrypted" IS NOT NULL)
40
+ ),
41
+ CONSTRAINT "pr_review_app_registrations_webhook_auth_chk" CHECK (
42
+ ("provider" = 'github' AND "webhook_auth_kind" = 'hmac_sha256')
43
+ OR ("provider" = 'gitlab' AND "webhook_auth_kind" = 'shared_token')
44
+ OR ("provider" = 'azure_devops' AND "webhook_auth_kind" = 'basic' AND "webhook_username" IS NOT NULL)
45
+ ),
46
+ CONSTRAINT "pr_review_app_registrations_status_chk"
47
+ CHECK ("status" IN ('active', 'disabled'))
48
+ );
49
+ CREATE UNIQUE INDEX "pr_review_app_registrations_workspace_id_uq"
50
+ ON "pr_review_app_registrations" ("workspace_id", "id");
51
+ CREATE UNIQUE INDEX "pr_review_app_registrations_workspace_id_provider_uq"
52
+ ON "pr_review_app_registrations" ("workspace_id", "id", "provider");
53
+ CREATE UNIQUE INDEX "pr_review_app_registrations_workspace_provider_name_uq"
54
+ ON "pr_review_app_registrations" ("workspace_id", "provider", "name");
55
+ CREATE INDEX "pr_review_app_registrations_workspace_status_idx"
56
+ ON "pr_review_app_registrations" ("workspace_id", "status");
57
+ CREATE UNIQUE INDEX "pr_review_app_registrations_source_uq"
58
+ ON "pr_review_app_registrations" ("source_id");
59
+
60
+ CREATE TABLE "pr_review_repository_bindings" (
61
+ "id" uuid PRIMARY KEY DEFAULT pg_catalog.gen_random_uuid(),
62
+ "trigger_id" uuid NOT NULL,
63
+ "account_id" uuid NOT NULL REFERENCES "managed_accounts"("id") ON DELETE CASCADE,
64
+ "workspace_id" uuid NOT NULL REFERENCES "workspaces"("id") ON DELETE CASCADE,
65
+ "registration_id" uuid NOT NULL,
66
+ "provider" text NOT NULL,
67
+ "repository_uri" text NOT NULL,
68
+ "repository_full_name" text NOT NULL,
69
+ "provider_repository_id" text NOT NULL,
70
+ "installation_id" text,
71
+ "project_id" text,
72
+ "model" text,
73
+ "additional_instructions" text,
74
+ "status" text NOT NULL DEFAULT 'active',
75
+ "created_by_subject_id" text NOT NULL,
76
+ "created_at" timestamptz NOT NULL DEFAULT now(),
77
+ "updated_at" timestamptz NOT NULL DEFAULT now(),
78
+ CONSTRAINT "pr_review_repository_bindings_workspace_account_fk"
79
+ FOREIGN KEY ("workspace_id", "account_id")
80
+ REFERENCES "workspaces"("id", "account_id") ON DELETE CASCADE,
81
+ CONSTRAINT "pr_review_repository_bindings_trigger_fk"
82
+ FOREIGN KEY ("workspace_id", "trigger_id")
83
+ REFERENCES "automation_triggers"("workspace_id", "id") ON DELETE CASCADE,
84
+ CONSTRAINT "pr_review_repository_bindings_registration_fk"
85
+ FOREIGN KEY ("workspace_id", "registration_id", "provider")
86
+ REFERENCES "pr_review_app_registrations"("workspace_id", "id", "provider") ON DELETE CASCADE,
87
+ CONSTRAINT "pr_review_repository_bindings_provider_chk"
88
+ CHECK ("provider" IN ('github', 'gitlab', 'azure_devops')),
89
+ CONSTRAINT "pr_review_repository_bindings_status_chk"
90
+ CHECK ("status" IN ('active', 'disabled'))
91
+ );
92
+ CREATE UNIQUE INDEX "pr_review_repository_bindings_workspace_id_uq"
93
+ ON "pr_review_repository_bindings" ("workspace_id", "id");
94
+ CREATE UNIQUE INDEX "pr_review_repo_workspace_registration_provider_uq"
95
+ ON "pr_review_repository_bindings" ("workspace_id", "id", "registration_id", "provider");
96
+ CREATE UNIQUE INDEX "pr_review_repository_bindings_registration_repo_uq"
97
+ ON "pr_review_repository_bindings" ("registration_id", "provider_repository_id");
98
+ CREATE INDEX "pr_review_repository_bindings_workspace_status_idx"
99
+ ON "pr_review_repository_bindings" ("workspace_id", "status");
100
+ CREATE UNIQUE INDEX "pr_review_repository_bindings_trigger_uq"
101
+ ON "pr_review_repository_bindings" ("trigger_id");
102
+
103
+ ALTER TABLE "pr_review_app_registrations" ENABLE ROW LEVEL SECURITY;
104
+ ALTER TABLE "pr_review_app_registrations" FORCE ROW LEVEL SECURITY;
105
+ CREATE POLICY pr_review_app_registrations_tenant ON "pr_review_app_registrations"
106
+ USING (opengeni_private.workspace_rls_visible("account_id", "workspace_id"))
107
+ WITH CHECK (opengeni_private.workspace_rls_visible("account_id", "workspace_id"));
108
+
109
+ ALTER TABLE "pr_review_repository_bindings" ENABLE ROW LEVEL SECURITY;
110
+ ALTER TABLE "pr_review_repository_bindings" FORCE ROW LEVEL SECURITY;
111
+ CREATE POLICY pr_review_repository_bindings_tenant ON "pr_review_repository_bindings"
112
+ USING (opengeni_private.workspace_rls_visible("account_id", "workspace_id"))
113
+ WITH CHECK (opengeni_private.workspace_rls_visible("account_id", "workspace_id"));
@@ -0,0 +1,15 @@
1
+ -- deployment-mode: rolling
2
+ -- Slack app and bot names are environment-scoped human-facing identity. Keep
3
+ -- the accepted set closed while allowing the managed staging principal to be
4
+ -- visibly distinct from production in a shared Slack workspace.
5
+ ALTER TABLE slack_installation_bindings
6
+ DROP CONSTRAINT slack_installation_bindings_identity_check;
7
+
8
+ ALTER TABLE slack_installation_bindings
9
+ ADD CONSTRAINT slack_installation_bindings_identity_check CHECK (
10
+ octet_length(slack_team_id) BETWEEN 1 AND 64
11
+ AND octet_length(slack_team_name) BETWEEN 1 AND 256
12
+ AND octet_length(bot_id) BETWEEN 1 AND 64
13
+ AND octet_length(bot_user_id) BETWEEN 1 AND 64
14
+ AND bot_display_name IN ('OpenGeni', 'OpenGeni Staging')
15
+ );
@@ -0,0 +1,5 @@
1
+ -- deployment-mode: rolling
2
+ -- opengeni:concurrent-index lock-timeout=5s
3
+ CREATE INDEX CONCURRENTLY IF NOT EXISTS "session_turns_unclaimed_prompt_trigger_idx"
4
+ ON "session_turns" ("workspace_id", "session_id", "trigger_event_id")
5
+ WHERE "started_at" IS NULL;