@opengeni/db 0.31.1 → 0.36.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 (122) hide show
  1. package/dist/browser-auth.d.ts +209 -1
  2. package/dist/browser-downloads.d.ts +51 -0
  3. package/dist/browser-identities.d.ts +11 -2
  4. package/dist/browser-sessions.d.ts +83 -1
  5. package/dist/browser-state-artifacts.d.ts +75 -1
  6. package/dist/canonical-human-identities.d.ts +48 -0
  7. package/dist/canonical-human-identities.js +28 -0
  8. package/dist/canonical-human-identities.js.map +1 -0
  9. package/dist/capability-integrations.d.ts +8 -6
  10. package/dist/{chunk-MWDVXQOL.js → chunk-5KTIEDX7.js} +5773 -4212
  11. package/dist/chunk-5KTIEDX7.js.map +1 -0
  12. package/dist/{chunk-NBE6CHRI.js → chunk-CQZ4QSP5.js} +49 -9
  13. package/dist/chunk-CQZ4QSP5.js.map +1 -0
  14. package/dist/chunk-F32YT7MP.js +117 -0
  15. package/dist/chunk-F32YT7MP.js.map +1 -0
  16. package/dist/{chunk-ISI2TIUG.js → chunk-JC5QPLUM.js} +30 -3
  17. package/dist/chunk-JC5QPLUM.js.map +1 -0
  18. package/dist/{chunk-F5FT7BEZ.js → chunk-P3RE4D2B.js} +2 -2
  19. package/dist/chunk-TAUTWOS5.js +259 -0
  20. package/dist/chunk-TAUTWOS5.js.map +1 -0
  21. package/dist/{chunk-YHZXQ7HP.js → chunk-VKLB2ZGI.js} +446 -19
  22. package/dist/chunk-VKLB2ZGI.js.map +1 -0
  23. package/dist/database.d.ts +5 -0
  24. package/dist/editable-artifact-durable-export.js +2 -2
  25. package/dist/editable-artifacts.js +3 -3
  26. package/dist/index.d.ts +438 -29
  27. package/dist/index.js +35640 -28969
  28. package/dist/index.js.map +1 -1
  29. package/dist/insights.d.ts +23 -7
  30. package/dist/integration-bindings.d.ts +24 -24
  31. package/dist/integration-facets.d.ts +99 -0
  32. package/dist/interaction-revisions.d.ts +11 -0
  33. package/dist/interaction-schema.d.ts +698 -34
  34. package/dist/provision-roles.js +1 -1
  35. package/dist/runtime-posture.d.ts +8 -7
  36. package/dist/schema.d.ts +9464 -5412
  37. package/dist/schema.js +51 -9
  38. package/dist/session-control.d.ts +29 -3
  39. package/dist/session-tenancy.d.ts +44 -0
  40. package/dist/session-tenancy.js +16 -0
  41. package/dist/session-tenancy.js.map +1 -0
  42. package/dist/slack-task-policy-schema.d.ts +847 -0
  43. package/dist/slack-task-policy.d.ts +65 -0
  44. package/dist/task-notes-schema.d.ts +924 -0
  45. package/dist/task-notes.d.ts +85 -0
  46. package/dist/video-generation.d.ts +9 -0
  47. package/dist/video-generation.js +5 -3
  48. package/dist/xai-subscription.d.ts +326 -0
  49. package/drizzle/0212_browser_state_transfer_hardening.sql +560 -0
  50. package/drizzle/0213_browser_interaction_authority.sql +67 -0
  51. package/drizzle/0214_browser_download_saves.sql +34 -0
  52. package/drizzle/0215_browser_controller_host.sql +385 -0
  53. package/drizzle/0216_browser_auth_health_evidence.sql +137 -0
  54. package/drizzle/0217_external_browser_auth_operations.sql +22 -0
  55. package/drizzle/0218_organization_tenancy_foundation.sql +299 -0
  56. package/drizzle/0219_organization_tenancy_managed_human_provisioning.sql +317 -0
  57. package/drizzle/0219_site_auth_maintenance_sessions.sql +234 -0
  58. package/drizzle/0220_memory_slack_append_only_cascade.sql +38 -0
  59. package/drizzle/0220_session_channels.sql +54 -0
  60. package/drizzle/0221_sessions_channel_index.sql +5 -0
  61. package/drizzle/0222_session_visibility_authority_epochs.sql +158 -0
  62. package/drizzle/0222_sessions_channel_fk.sql +89 -0
  63. package/drizzle/0223_pending_tool_event_output.sql +55 -0
  64. package/drizzle/0223_sessions_channel_fk_validate.sql +118 -0
  65. package/drizzle/0224_slack_post_outcome_reconciliation.sql +123 -0
  66. package/drizzle/0225_session_visibility_fork_activation.sql +1363 -0
  67. package/drizzle/0226_personal_codex_authority_foundation.sql +365 -0
  68. package/drizzle/0227_slack_native_actions.sql +145 -0
  69. package/drizzle/0228_interaction_controller_data_plane.sql +14 -0
  70. package/drizzle/0228_slack_task_policy.sql +400 -0
  71. package/drizzle/0229_slack_inbox_file_fact.sql +10 -0
  72. package/drizzle/0230_user_scoped_variable_sets_rigs.sql +84 -0
  73. package/drizzle/0231_integration_definition_identity_cutover.sql +271 -0
  74. package/drizzle/0232_integration_facet_authority_cutover.sql +610 -0
  75. package/drizzle/0233_skill_and_integration_authority_cutover.sql +1162 -0
  76. package/drizzle/0234_xai_subscription_authority.sql +1139 -0
  77. package/drizzle/0235_canonical_human_login_bindings.sql +920 -0
  78. package/drizzle/0236_browser_identity_lifecycle.sql +39 -0
  79. package/drizzle/0236_session_visibility_slack_policy.sql +72 -0
  80. package/drizzle/0237_interaction_transition_reaper.sql +263 -0
  81. package/drizzle/0238_goal_persistence_policy.sql +471 -0
  82. package/drizzle/0238_supergrok_realtime_model.sql +29 -0
  83. package/drizzle/0239_supergrok_video_funding.sql +50 -0
  84. package/drizzle/0239_task_tree_notes.sql +990 -0
  85. package/package.json +13 -5
  86. package/src/browser-auth.ts +2600 -123
  87. package/src/browser-downloads.ts +517 -0
  88. package/src/browser-identities.ts +220 -3
  89. package/src/browser-sessions.ts +334 -45
  90. package/src/browser-state-artifacts.ts +402 -12
  91. package/src/canonical-human-identities.ts +317 -0
  92. package/src/capability-integrations.ts +121 -213
  93. package/src/database.ts +41 -1
  94. package/src/index.ts +4157 -394
  95. package/src/insights.ts +109 -28
  96. package/src/integration-bindings.ts +101 -101
  97. package/src/{integration-features.ts → integration-facets.ts} +187 -184
  98. package/src/interaction-revisions.ts +33 -3
  99. package/src/interaction-schema.ts +311 -8
  100. package/src/pack-components.ts +43 -43
  101. package/src/pack-installations.ts +0 -43
  102. package/src/plugin-packages.ts +9 -9
  103. package/src/provision-roles.ts +232 -0
  104. package/src/runtime-posture.ts +227 -14
  105. package/src/schema.ts +1188 -75
  106. package/src/session-control.ts +122 -37
  107. package/src/session-queue-commands.ts +78 -1
  108. package/src/session-tenancy.ts +188 -0
  109. package/src/session-tool-call-settlement.ts +9 -3
  110. package/src/slack-task-policy-schema.ts +130 -0
  111. package/src/slack-task-policy.ts +341 -0
  112. package/src/task-notes-schema.ts +135 -0
  113. package/src/task-notes.ts +178 -0
  114. package/src/video-generation.ts +90 -12
  115. package/src/workspace-artifacts.ts +1 -1
  116. package/src/xai-subscription.ts +1887 -0
  117. package/dist/chunk-ISI2TIUG.js.map +0 -1
  118. package/dist/chunk-MWDVXQOL.js.map +0 -1
  119. package/dist/chunk-NBE6CHRI.js.map +0 -1
  120. package/dist/chunk-YHZXQ7HP.js.map +0 -1
  121. package/dist/integration-features.d.ts +0 -99
  122. /package/dist/{chunk-F5FT7BEZ.js.map → chunk-P3RE4D2B.js.map} +0 -0
@@ -0,0 +1,39 @@
1
+ -- deployment-mode: maintenance
2
+ -- Complete the saved-browser lifecycle with optimistic metadata updates and
3
+ -- replay-safe mutation receipts. Immutable revisions remain untouched.
4
+ SET LOCAL lock_timeout = '5s';
5
+ SET LOCAL statement_timeout = '30s';
6
+
7
+ ALTER TABLE "browser_identities"
8
+ ADD COLUMN "version" bigint NOT NULL DEFAULT 1;
9
+
10
+ ALTER TABLE "browser_identities"
11
+ DROP CONSTRAINT "browser_identities_values_check";
12
+
13
+ ALTER TABLE "browser_identities"
14
+ ADD CONSTRAINT "browser_identities_values_check" CHECK (
15
+ octet_length("name") BETWEEN 1 AND 200
16
+ AND "name" = btrim("name")
17
+ AND octet_length("created_by_subject_id") BETWEEN 1 AND 1024
18
+ AND "version" > 0
19
+ AND "head_generation" >= 0
20
+ AND "revision_count" >= 0
21
+ AND (
22
+ ("head_generation" = 0 AND "default_revision_id" IS NULL)
23
+ OR ("head_generation" > 0 AND "default_revision_id" IS NOT NULL)
24
+ )
25
+ );
26
+
27
+ ALTER TABLE "interaction_resource_operations"
28
+ DROP CONSTRAINT "interaction_resource_operations_resource_kind_check";
29
+
30
+ ALTER TABLE "interaction_resource_operations"
31
+ ADD CONSTRAINT "interaction_resource_operations_resource_kind_check"
32
+ CHECK ("resource_kind" IN (
33
+ 'browser_identity',
34
+ 'network_route',
35
+ 'site_auth_connection',
36
+ 'auth_run',
37
+ 'intervention',
38
+ 'browser_download'
39
+ ));
@@ -0,0 +1,72 @@
1
+ -- deployment-mode: rolling
2
+ -- Forward-repair direct session references introduced after migration 0225.
3
+
4
+ SET LOCAL lock_timeout = '5s';
5
+ SET LOCAL statement_timeout = '10min';
6
+
7
+ DO $session_visibility_slack_task_repair$
8
+ DECLARE
9
+ data_schema text := current_schema();
10
+ target_table text;
11
+ policy_expression text;
12
+ BEGIN
13
+ IF pg_catalog.to_regprocedure(
14
+ pg_catalog.format('%I.session_private_actor_visible(uuid,uuid,uuid,text)', data_schema)
15
+ ) IS NULL OR pg_catalog.to_regprocedure(
16
+ pg_catalog.format('%I.session_reference_visible(uuid,uuid,uuid)', data_schema)
17
+ ) IS NULL THEN
18
+ RAISE EXCEPTION 'session visibility helper chain is missing'
19
+ USING ERRCODE = '42883';
20
+ END IF;
21
+
22
+ EXECUTE pg_catalog.format(
23
+ 'REVOKE ALL ON FUNCTION %I.session_private_actor_visible(uuid,uuid,uuid,text) FROM PUBLIC',
24
+ data_schema
25
+ );
26
+ EXECUTE pg_catalog.format(
27
+ 'REVOKE ALL ON FUNCTION %I.session_reference_visible(uuid,uuid,uuid) FROM PUBLIC',
28
+ data_schema
29
+ );
30
+ IF EXISTS (SELECT 1 FROM pg_catalog.pg_roles WHERE rolname = 'opengeni_app') THEN
31
+ EXECUTE pg_catalog.format(
32
+ 'GRANT EXECUTE ON FUNCTION %I.session_private_actor_visible(uuid,uuid,uuid,text) TO opengeni_app',
33
+ data_schema
34
+ );
35
+ EXECUTE pg_catalog.format(
36
+ 'GRANT EXECUTE ON FUNCTION %I.session_reference_visible(uuid,uuid,uuid) TO opengeni_app',
37
+ data_schema
38
+ );
39
+ END IF;
40
+
41
+ FOREACH target_table IN ARRAY ARRAY[
42
+ 'slack_interaction_action_handles',
43
+ 'slack_shared_task_origins',
44
+ 'xai_capacity_waiters',
45
+ 'xai_session_account_pins'
46
+ ]
47
+ LOOP
48
+ IF pg_catalog.to_regclass(pg_catalog.format('%I.%I', data_schema, target_table)) IS NULL THEN
49
+ RAISE EXCEPTION 'session visibility repair table is missing: %', target_table
50
+ USING ERRCODE = '42P01';
51
+ END IF;
52
+
53
+ policy_expression := pg_catalog.format(
54
+ '%I.session_reference_visible(account_id, workspace_id, session_id)',
55
+ data_schema
56
+ );
57
+ EXECUTE pg_catalog.format(
58
+ 'DROP POLICY IF EXISTS session_visibility_isolation ON %I.%I',
59
+ data_schema,
60
+ target_table
61
+ );
62
+ EXECUTE pg_catalog.format(
63
+ 'CREATE POLICY session_visibility_isolation ON %I.%I AS RESTRICTIVE '
64
+ || 'FOR ALL USING (%s) WITH CHECK (%s)',
65
+ data_schema,
66
+ target_table,
67
+ policy_expression,
68
+ policy_expression
69
+ );
70
+ END LOOP;
71
+ END
72
+ $session_visibility_slack_task_repair$;
@@ -0,0 +1,263 @@
1
+ -- deployment-mode: maintenance
2
+ -- Settle controller transitions whose API owner disappeared after dispatch.
3
+ -- Active Browser/Computer sessions are deliberately excluded: their durable
4
+ -- placement must survive a hidden UI, a closed laptop, and long human login.
5
+ SET LOCAL lock_timeout = '5s';
6
+ SET LOCAL statement_timeout = '30s';
7
+
8
+ DO $transition_reaper$
9
+ DECLARE data_schema text := current_schema();
10
+ BEGIN
11
+ EXECUTE format($create$
12
+ CREATE OR REPLACE FUNCTION opengeni_private.reap_stale_interaction_transitions(
13
+ p_interaction_holder_ttl_ms bigint
14
+ )
15
+ RETURNS integer
16
+ LANGUAGE plpgsql
17
+ SECURITY DEFINER
18
+ SET search_path = pg_catalog
19
+ AS $function$
20
+ DECLARE
21
+ stale_operation_ids uuid[] := ARRAY[]::uuid[];
22
+ stale_browser_ids uuid[] := ARRAY[]::uuid[];
23
+ stale_computer_ids uuid[] := ARRAY[]::uuid[];
24
+ changed_workspace_ids uuid[] := ARRAY[]::uuid[];
25
+ orphan_workspace_ids uuid[] := ARRAY[]::uuid[];
26
+ affected_lease_ids uuid[] := ARRAY[]::uuid[];
27
+ settled_count integer := 0;
28
+ BEGIN
29
+ IF p_interaction_holder_ttl_ms <= 0 THEN
30
+ RETURN 0;
31
+ END IF;
32
+
33
+ -- The exact lifecycle operation is the request-owner heartbeat. Long
34
+ -- controller calls pulse updated_at; a stale dispatched operation means
35
+ -- the caller vanished. Prepared operations cannot have a physical side
36
+ -- effect yet and remain replayable, so they are intentionally excluded.
37
+ SELECT coalesce(pg_catalog.array_agg(candidate.operation_id), ARRAY[]::uuid[])
38
+ INTO stale_operation_ids
39
+ FROM (
40
+ SELECT operation.operation_id
41
+ FROM %1$I.interaction_operations operation
42
+ WHERE operation.state = 'dispatched'
43
+ AND operation.updated_at
44
+ < pg_catalog.now()
45
+ - pg_catalog.make_interval(
46
+ secs => p_interaction_holder_ttl_ms / 1000.0
47
+ )
48
+ AND (
49
+ EXISTS (
50
+ SELECT 1
51
+ FROM %1$I.browser_sessions browser
52
+ WHERE operation.resource_kind = 'browser_session'
53
+ AND operation.account_id = browser.account_id
54
+ AND operation.workspace_id = browser.workspace_id
55
+ AND operation.resource_id = browser.id
56
+ AND browser.lifecycle IN (
57
+ 'starting', 'suspending', 'restoring', 'ending'
58
+ )
59
+ )
60
+ OR EXISTS (
61
+ SELECT 1
62
+ FROM %1$I.computer_sessions computer
63
+ WHERE operation.resource_kind = 'computer_session'
64
+ AND operation.account_id = computer.account_id
65
+ AND operation.workspace_id = computer.workspace_id
66
+ AND operation.resource_id = computer.id
67
+ AND computer.lifecycle IN ('starting', 'ending')
68
+ )
69
+ )
70
+ ORDER BY operation.updated_at, operation.operation_id
71
+ LIMIT 500
72
+ FOR UPDATE OF operation SKIP LOCKED
73
+ ) candidate;
74
+
75
+ SELECT coalesce(
76
+ pg_catalog.array_agg(operation.resource_id)
77
+ FILTER (WHERE operation.resource_kind = 'browser_session'),
78
+ ARRAY[]::uuid[]
79
+ ),
80
+ coalesce(
81
+ pg_catalog.array_agg(operation.resource_id)
82
+ FILTER (WHERE operation.resource_kind = 'computer_session'),
83
+ ARRAY[]::uuid[]
84
+ ),
85
+ coalesce(
86
+ pg_catalog.array_agg(DISTINCT operation.workspace_id),
87
+ ARRAY[]::uuid[]
88
+ )
89
+ INTO stale_browser_ids, stale_computer_ids, changed_workspace_ids
90
+ FROM %1$I.interaction_operations operation
91
+ WHERE operation.operation_id = ANY(stale_operation_ids);
92
+
93
+ -- Lock every affected lease before its holder, matching lease acquire,
94
+ -- release and the ordinary global reaper. Connected-machine transitions
95
+ -- have no lease and still settle through the same operation contract.
96
+ SELECT coalesce(pg_catalog.array_agg(DISTINCT holder.lease_id), ARRAY[]::uuid[])
97
+ INTO affected_lease_ids
98
+ FROM %1$I.sandbox_lease_holders holder
99
+ WHERE holder.kind = 'interaction'
100
+ AND (
101
+ holder.holder_id IN (
102
+ SELECT 'browser-session:' || id::text
103
+ FROM pg_catalog.unnest(stale_browser_ids) ids(id)
104
+ )
105
+ OR holder.holder_id IN (
106
+ SELECT 'computer-session:' || id::text
107
+ FROM pg_catalog.unnest(stale_computer_ids) ids(id)
108
+ )
109
+ );
110
+
111
+ PERFORM lease.id
112
+ FROM %1$I.sandbox_leases lease
113
+ WHERE lease.id = ANY(affected_lease_ids)
114
+ ORDER BY lease.id
115
+ FOR UPDATE OF lease;
116
+
117
+ PERFORM holder.id
118
+ FROM %1$I.sandbox_lease_holders holder
119
+ WHERE holder.lease_id = ANY(affected_lease_ids)
120
+ AND holder.kind = 'interaction'
121
+ AND (
122
+ holder.holder_id IN (
123
+ SELECT 'browser-session:' || id::text
124
+ FROM pg_catalog.unnest(stale_browser_ids) ids(id)
125
+ )
126
+ OR holder.holder_id IN (
127
+ SELECT 'computer-session:' || id::text
128
+ FROM pg_catalog.unnest(stale_computer_ids) ids(id)
129
+ )
130
+ )
131
+ ORDER BY holder.id
132
+ FOR UPDATE OF holder;
133
+
134
+ UPDATE %1$I.interaction_operations operation
135
+ SET state = 'outcome_unknown',
136
+ error_code = 'controller_transition_expired',
137
+ error_message = 'Interaction controller transition heartbeat expired',
138
+ error_retryable = false,
139
+ error_details = pg_catalog.jsonb_build_object(
140
+ 'reason', 'transition_heartbeat_expired'
141
+ ),
142
+ settled_at = pg_catalog.now(),
143
+ updated_at = pg_catalog.now()
144
+ WHERE operation.operation_id = ANY(stale_operation_ids)
145
+ AND operation.state = 'dispatched';
146
+ GET DIAGNOSTICS settled_count = ROW_COUNT;
147
+
148
+ -- Outcome is unknown: retain the exact controller binding so a subsequent
149
+ -- end/cleanup can target the same generation. The lease holder is released
150
+ -- below; provider drain remains the final physical cleanup fence.
151
+ UPDATE %1$I.browser_sessions browser
152
+ SET lifecycle = 'lost',
153
+ failure_code = 'controller_transition_expired',
154
+ updated_at = pg_catalog.now()
155
+ WHERE browser.id = ANY(stale_browser_ids)
156
+ AND browser.lifecycle IN (
157
+ 'starting', 'suspending', 'restoring', 'ending'
158
+ );
159
+
160
+ UPDATE %1$I.computer_sessions computer
161
+ SET lifecycle = 'lost',
162
+ failure_code = 'controller_transition_expired',
163
+ updated_at = pg_catalog.now()
164
+ WHERE computer.id = ANY(stale_computer_ids)
165
+ AND computer.lifecycle IN ('starting', 'ending');
166
+
167
+ -- Terminal/mismatched interaction holders are lifecycle orphans. Include
168
+ -- the transitions settled above plus missed best-effort releases after a
169
+ -- successful suspend/end/failure. Active controllers remain immortal.
170
+ SELECT coalesce(pg_catalog.array_agg(DISTINCT holder.lease_id), ARRAY[]::uuid[]),
171
+ coalesce(pg_catalog.array_agg(DISTINCT holder.workspace_id), ARRAY[]::uuid[])
172
+ INTO affected_lease_ids, orphan_workspace_ids
173
+ FROM %1$I.sandbox_lease_holders holder
174
+ JOIN %1$I.sandbox_leases lease ON lease.id = holder.lease_id
175
+ WHERE holder.kind = 'interaction'
176
+ AND NOT (
177
+ EXISTS (
178
+ SELECT 1
179
+ FROM %1$I.browser_sessions browser
180
+ WHERE holder.holder_id = ('browser-session:' || browser.id::text)
181
+ AND holder.account_id = browser.account_id
182
+ AND holder.workspace_id = browser.workspace_id
183
+ AND browser.controller_host_sandbox_group_id = lease.sandbox_group_id
184
+ AND browser.lifecycle IN (
185
+ 'starting', 'active', 'suspending', 'restoring', 'ending'
186
+ )
187
+ )
188
+ OR EXISTS (
189
+ SELECT 1
190
+ FROM %1$I.computer_sessions computer
191
+ WHERE holder.holder_id = ('computer-session:' || computer.id::text)
192
+ AND holder.account_id = computer.account_id
193
+ AND holder.workspace_id = computer.workspace_id
194
+ AND computer.sandbox_group_id = lease.sandbox_group_id
195
+ AND computer.lifecycle IN (
196
+ 'starting', 'active', 'suspending', 'restoring', 'ending'
197
+ )
198
+ )
199
+ );
200
+
201
+ PERFORM lease.id
202
+ FROM %1$I.sandbox_leases lease
203
+ WHERE lease.id = ANY(affected_lease_ids)
204
+ ORDER BY lease.id
205
+ FOR UPDATE OF lease;
206
+
207
+ DELETE FROM %1$I.sandbox_lease_holders holder
208
+ USING %1$I.sandbox_leases lease
209
+ WHERE holder.lease_id = lease.id
210
+ AND holder.lease_id = ANY(affected_lease_ids)
211
+ AND holder.kind = 'interaction'
212
+ AND NOT (
213
+ EXISTS (
214
+ SELECT 1
215
+ FROM %1$I.browser_sessions browser
216
+ WHERE holder.holder_id = ('browser-session:' || browser.id::text)
217
+ AND holder.account_id = browser.account_id
218
+ AND holder.workspace_id = browser.workspace_id
219
+ AND browser.controller_host_sandbox_group_id = lease.sandbox_group_id
220
+ AND browser.lifecycle IN (
221
+ 'starting', 'active', 'suspending', 'restoring', 'ending'
222
+ )
223
+ )
224
+ OR EXISTS (
225
+ SELECT 1
226
+ FROM %1$I.computer_sessions computer
227
+ WHERE holder.holder_id = ('computer-session:' || computer.id::text)
228
+ AND holder.account_id = computer.account_id
229
+ AND holder.workspace_id = computer.workspace_id
230
+ AND computer.sandbox_group_id = lease.sandbox_group_id
231
+ AND computer.lifecycle IN (
232
+ 'starting', 'active', 'suspending', 'restoring', 'ending'
233
+ )
234
+ )
235
+ );
236
+
237
+ UPDATE %1$I.workspace_interaction_revisions revision
238
+ SET revision = revision.revision + 1,
239
+ updated_at = pg_catalog.now()
240
+ WHERE revision.workspace_id = ANY(changed_workspace_ids || orphan_workspace_ids);
241
+
242
+ RETURN settled_count;
243
+ END;
244
+ $function$;
245
+ $create$, data_schema);
246
+ END
247
+ $transition_reaper$;
248
+
249
+ REVOKE ALL ON FUNCTION opengeni_private.reap_stale_interaction_transitions(bigint)
250
+ FROM PUBLIC;
251
+
252
+ DO $reaper_grant$
253
+ BEGIN
254
+ IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'opengeni_app') THEN
255
+ GRANT EXECUTE ON FUNCTION
256
+ opengeni_private.reap_stale_interaction_transitions(bigint)
257
+ TO opengeni_app;
258
+ END IF;
259
+ END
260
+ $reaper_grant$;
261
+
262
+ RESET statement_timeout;
263
+ RESET lock_timeout;