@opengeni/db 1.0.1 → 3.1.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 (265) 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-LTG3S6ZY.js → chunk-EULAN2NP.js} +2 -2
  7. package/dist/{chunk-CUPM3FGB.js → chunk-NJVZPWXY.js} +3 -3
  8. package/dist/{chunk-4SR4HKKA.js → chunk-NMUBV7Z5.js} +19 -11
  9. package/dist/chunk-NMUBV7Z5.js.map +1 -0
  10. package/dist/chunk-OF5OBB76.js +4457 -0
  11. package/dist/chunk-OF5OBB76.js.map +1 -0
  12. package/dist/{chunk-6ZYKCRFO.js → chunk-PR2WMLOQ.js} +7580 -4417
  13. package/dist/chunk-PR2WMLOQ.js.map +1 -0
  14. package/dist/{chunk-ZWREYEWA.js → chunk-SCPUJS53.js} +41 -4
  15. package/dist/chunk-SCPUJS53.js.map +1 -0
  16. package/dist/{chunk-SK7YYHBI.js → chunk-SIBYBA2D.js} +46 -1
  17. package/dist/chunk-SIBYBA2D.js.map +1 -0
  18. package/dist/chunk-TIKF3KTI.js +383 -0
  19. package/dist/chunk-TIKF3KTI.js.map +1 -0
  20. package/dist/chunk-ZZ5LJEFX.js +516 -0
  21. package/dist/chunk-ZZ5LJEFX.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 +41 -0
  33. package/dist/connection-token-resolver.d.ts +30 -1
  34. package/dist/database.d.ts +19 -0
  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 +1595 -81
  43. package/dist/index.js +21571 -8126
  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 +22 -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 +41 -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 +153 -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 +1 -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/package.json +10 -6
  189. package/src/attached-browser-devices.ts +233 -5
  190. package/src/automations.ts +911 -0
  191. package/src/browser-sessions.ts +10 -0
  192. package/src/capability-integrations.ts +175 -1
  193. package/src/child-lifecycle-notices.ts +241 -0
  194. package/src/codemode-operations.ts +1 -35
  195. package/src/company-brain-context-selection-schema.ts +100 -0
  196. package/src/company-brain-context-selection.ts +359 -0
  197. package/src/company-brain-governed-writes.ts +1170 -0
  198. package/src/company-brain.ts +309 -0
  199. package/src/company-profile-agent-admin.ts +225 -0
  200. package/src/company-profile-schema.ts +121 -1
  201. package/src/company-profile.ts +21 -0
  202. package/src/computer-sessions.ts +10 -1
  203. package/src/connection-authority.ts +290 -0
  204. package/src/connection-scopes.ts +20 -0
  205. package/src/connection-tenancy-backfill.ts +81 -0
  206. package/src/connection-token-resolver.ts +263 -31
  207. package/src/database.ts +75 -2
  208. package/src/editable-artifacts-schema.ts +10 -5
  209. package/src/editable-artifacts.ts +21 -11
  210. package/src/governed-learning-activation-schema.ts +121 -0
  211. package/src/governed-learning-activation.ts +588 -0
  212. package/src/governed-learning-evaluator-schema.ts +72 -0
  213. package/src/governed-learning-evaluator.ts +217 -0
  214. package/src/index.ts +11651 -1548
  215. package/src/insights.ts +107 -0
  216. package/src/integration-bindings.ts +88 -6
  217. package/src/integration-facets.ts +287 -84
  218. package/src/interaction-placement-loss.ts +234 -0
  219. package/src/managed-human-provisioning.ts +116 -0
  220. package/src/memory-domain.ts +27 -32
  221. package/src/migrate.ts +77 -1
  222. package/src/new-session-drafts.ts +229 -35
  223. package/src/organization-membership-backfill.ts +735 -0
  224. package/src/organization-membership-lifecycle.ts +985 -0
  225. package/src/pr-review.ts +890 -0
  226. package/src/preference-registry.ts +31 -1
  227. package/src/provision-roles.ts +877 -6
  228. package/src/runtime-posture-cli.ts +2 -0
  229. package/src/runtime-posture.ts +1291 -76
  230. package/src/schema.ts +3303 -428
  231. package/src/scoped-knowledge-schema.ts +16 -8
  232. package/src/scoped-knowledge.ts +1 -1
  233. package/src/session-background-commands.ts +759 -0
  234. package/src/session-control.ts +640 -74
  235. package/src/session-goal-pacing.ts +126 -0
  236. package/src/session-queue-commands.ts +437 -84
  237. package/src/session-realtime-context.ts +3 -3
  238. package/src/session-realtime-ledger.ts +22 -11
  239. package/src/session-realtime-mirror.ts +1 -1
  240. package/src/session-tenancy.ts +403 -49
  241. package/src/session-tool-call-settlement.ts +38 -29
  242. package/src/slack-routing-personal-workspace.ts +67 -0
  243. package/src/slack-routing.ts +469 -0
  244. package/src/slack-task-policy-schema.ts +5 -0
  245. package/src/slack-task-policy.ts +18 -0
  246. package/src/slack-user-link-access.ts +17 -1
  247. package/src/task-notes-schema.ts +74 -0
  248. package/src/task-notes.ts +124 -2
  249. package/src/turn-initiator.ts +8 -0
  250. package/src/user-resource-authority.ts +377 -0
  251. package/src/workspace-authority.ts +160 -0
  252. package/src/workspace-instruction-policies-schema.ts +53 -1
  253. package/src/workspace-instruction-policies.ts +528 -77
  254. package/src/workspace-learning-policy.ts +21 -5
  255. package/src/workspace-membership-permissions.ts +9 -0
  256. package/dist/chunk-4SR4HKKA.js.map +0 -1
  257. package/dist/chunk-6ZYKCRFO.js.map +0 -1
  258. package/dist/chunk-NXAFLCQX.js +0 -2468
  259. package/dist/chunk-NXAFLCQX.js.map +0 -1
  260. package/dist/chunk-SK7YYHBI.js.map +0 -1
  261. package/dist/chunk-WD5ROSLL.js +0 -117
  262. package/dist/chunk-WD5ROSLL.js.map +0 -1
  263. package/dist/chunk-ZWREYEWA.js.map +0 -1
  264. /package/dist/{chunk-LTG3S6ZY.js.map → chunk-EULAN2NP.js.map} +0 -0
  265. /package/dist/{chunk-CUPM3FGB.js.map → chunk-NJVZPWXY.js.map} +0 -0
@@ -0,0 +1,662 @@
1
+ -- deployment-mode: rolling
2
+ -- Correct personal-resource delegation authority without rewriting migration 0241.
3
+ -- Personal-workspace owners use their exact active organization membership;
4
+ -- every non-personal target still requires ordinary workspace membership, and
5
+ -- only a running turn may own admission or resolution for an active attempt.
6
+
7
+ SET LOCAL lock_timeout = '5s';
8
+ SET LOCAL statement_timeout = '10min';
9
+
10
+ DO $personal_resource_delegation_authority_correction$
11
+ DECLARE
12
+ data_schema text := current_schema();
13
+ BEGIN
14
+ EXECUTE format($ddl$
15
+ CREATE OR REPLACE FUNCTION %1$I.admit_session_attempt_personal_resources()
16
+ RETURNS trigger
17
+ LANGUAGE plpgsql
18
+ SECURITY DEFINER
19
+ SET search_path = %1$I, pg_catalog
20
+ AS $body$
21
+ DECLARE
22
+ session_row sessions%%ROWTYPE;
23
+ turn_row session_turns%%ROWTYPE;
24
+ member_row organization_memberships%%ROWTYPE;
25
+ resource_row record;
26
+ grant_row organization_user_resource_grants%%ROWTYPE;
27
+ resource_total integer := 0;
28
+ snapshot_total integer := 0;
29
+ initiating_subject text;
30
+ affected integer;
31
+ BEGIN
32
+ INSERT INTO opengeni_private.personal_resource_delegation_capabilities (
33
+ backend_pid, transaction_id, capability_kind
34
+ ) VALUES (pg_catalog.pg_backend_pid(), pg_catalog.pg_current_xact_id(), 'admit')
35
+ ON CONFLICT DO NOTHING;
36
+
37
+ SELECT session_value.* INTO STRICT session_row
38
+ FROM sessions session_value
39
+ WHERE session_value.id = NEW.session_id
40
+ AND session_value.account_id = NEW.account_id
41
+ AND session_value.workspace_id = NEW.workspace_id
42
+ FOR SHARE;
43
+
44
+ SELECT turn_value.* INTO STRICT turn_row
45
+ FROM session_turns turn_value
46
+ WHERE turn_value.id = NEW.turn_id
47
+ AND turn_value.account_id = NEW.account_id
48
+ AND turn_value.workspace_id = NEW.workspace_id
49
+ AND turn_value.session_id = NEW.session_id
50
+ FOR SHARE;
51
+
52
+ SELECT count(*)::integer INTO resource_total
53
+ FROM (
54
+ SELECT DISTINCT selected.resource_kind, selected.resource_id
55
+ FROM (
56
+ SELECT 'variable_set'::text AS resource_kind, variable_set.id AS resource_id
57
+ FROM workspace_variable_sets variable_set
58
+ WHERE variable_set.id = session_row.variable_set_id
59
+ AND variable_set.account_id = NEW.account_id
60
+ AND variable_set.authority_scope = 'user'
61
+ UNION ALL
62
+ SELECT 'rig'::text, rig.id
63
+ FROM rigs rig
64
+ WHERE rig.id = session_row.rig_id
65
+ AND rig.account_id = NEW.account_id
66
+ AND rig.authority_scope = 'user'
67
+ UNION ALL
68
+ SELECT 'variable_set'::text, default_variable_set.id
69
+ FROM rig_versions rig_version
70
+ CROSS JOIN LATERAL jsonb_array_elements_text(
71
+ rig_version.default_variable_set_ids
72
+ ) default_id(value)
73
+ JOIN workspace_variable_sets default_variable_set
74
+ ON default_variable_set.id = default_id.value::uuid
75
+ AND default_variable_set.account_id = NEW.account_id
76
+ AND default_variable_set.authority_scope = 'user'
77
+ WHERE rig_version.id = session_row.rig_version_id
78
+ AND rig_version.rig_id = session_row.rig_id
79
+ AND rig_version.account_id = NEW.account_id
80
+ ) selected
81
+ ) selected_personal_resources;
82
+
83
+ IF resource_total = 0 THEN
84
+ DELETE FROM opengeni_private.personal_resource_delegation_capabilities
85
+ WHERE backend_pid = pg_catalog.pg_backend_pid()
86
+ AND transaction_id = pg_catalog.pg_current_xact_id_if_assigned()
87
+ AND capability_kind = 'admit';
88
+ RETURN NEW;
89
+ END IF;
90
+
91
+ IF NEW.execution_generation <= 0
92
+ OR NEW.state NOT IN ('claimed', 'running')
93
+ OR NEW.closed_at IS NOT NULL
94
+ OR NEW.quiesced_at IS NOT NULL
95
+ OR session_row.active_turn_id IS DISTINCT FROM NEW.turn_id
96
+ OR turn_row.active_attempt_id IS DISTINCT FROM NEW.id
97
+ OR turn_row.execution_generation IS DISTINCT FROM NEW.execution_generation
98
+ OR turn_row.status <> 'running'
99
+ OR EXISTS (
100
+ SELECT 1
101
+ FROM session_attempt_interruptions interruption
102
+ WHERE interruption.account_id = NEW.account_id
103
+ AND interruption.workspace_id = NEW.workspace_id
104
+ AND interruption.session_id = NEW.session_id
105
+ AND interruption.attempt_id = NEW.id
106
+ AND interruption.state IN ('pending', 'delivered', 'acknowledged')
107
+ )
108
+ THEN
109
+ RAISE EXCEPTION 'personal-resource admission requires the exact current uninterrupted attempt'
110
+ USING ERRCODE = '42501';
111
+ END IF;
112
+
113
+ IF NEW.authority_visibility IS DISTINCT FROM session_row.visibility
114
+ OR NEW.authority_epoch IS DISTINCT FROM session_row.authority_epoch
115
+ OR NEW.authority_owner_organization_membership_id
116
+ IS DISTINCT FROM session_row.owner_organization_membership_id
117
+ THEN
118
+ RAISE EXCEPTION 'personal-resource admission requires the exact session authority'
119
+ USING ERRCODE = '42501';
120
+ END IF;
121
+
122
+ initiating_subject := coalesce(
123
+ nullif(btrim(turn_row.initiating_human_subject_id), ''),
124
+ CASE WHEN turn_row.initiator_kind = 'subject'
125
+ THEN nullif(btrim(turn_row.initiator_subject_id), '') END
126
+ );
127
+ IF initiating_subject IS NULL THEN
128
+ RAISE EXCEPTION 'personal-resource admission requires an initiating human subject'
129
+ USING ERRCODE = '42501';
130
+ END IF;
131
+
132
+ SELECT membership.* INTO STRICT member_row
133
+ FROM organization_memberships membership
134
+ WHERE membership.account_id = NEW.account_id
135
+ AND membership.subject_id = initiating_subject
136
+ AND membership.status = 'active'
137
+ AND membership.revoked_at IS NULL
138
+ AND membership.personal_workspace_id IS NOT NULL
139
+ FOR SHARE;
140
+
141
+ IF member_row.personal_workspace_id IS DISTINCT FROM NEW.workspace_id THEN
142
+ PERFORM 1
143
+ FROM workspace_memberships workspace_membership
144
+ WHERE workspace_membership.account_id = NEW.account_id
145
+ AND workspace_membership.workspace_id = NEW.workspace_id
146
+ AND workspace_membership.subject_id = initiating_subject
147
+ FOR KEY SHARE;
148
+ IF NOT FOUND THEN
149
+ RAISE EXCEPTION 'initiating human lacks target-workspace membership'
150
+ USING ERRCODE = '42501';
151
+ END IF;
152
+ END IF;
153
+
154
+ INSERT INTO session_attempt_personal_resource_admissions (
155
+ attempt_id, account_id, workspace_id, session_id, turn_id,
156
+ execution_generation, initiating_human_subject_id,
157
+ owner_organization_membership_id, membership_authorization_revision,
158
+ session_visibility, session_authority_epoch, resource_count
159
+ ) VALUES (
160
+ NEW.id, NEW.account_id, NEW.workspace_id, NEW.session_id, NEW.turn_id,
161
+ NEW.execution_generation, initiating_subject, member_row.id,
162
+ member_row.authorization_revision, session_row.visibility,
163
+ session_row.authority_epoch, resource_total
164
+ );
165
+
166
+ FOR resource_row IN
167
+ WITH selected AS (
168
+ SELECT
169
+ 'variable_set'::text AS resource_kind,
170
+ variable_set.id AS resource_id,
171
+ NULL::uuid AS resource_version_id,
172
+ 'variable_set.use'::text AS action,
173
+ 'session_variable_set'::text AS selection_source,
174
+ variable_set.workspace_id AS resource_workspace_id,
175
+ variable_set.authority_id,
176
+ variable_set.owner_organization_membership_id,
177
+ variable_set.origin_workspace_id
178
+ FROM workspace_variable_sets variable_set
179
+ WHERE variable_set.id = session_row.variable_set_id
180
+ AND variable_set.account_id = NEW.account_id
181
+ AND variable_set.authority_scope = 'user'
182
+ UNION ALL
183
+ SELECT
184
+ 'rig'::text, rig.id, session_row.rig_version_id, 'rig.use'::text,
185
+ 'session_rig'::text, rig.workspace_id, rig.authority_id,
186
+ rig.owner_organization_membership_id, rig.origin_workspace_id
187
+ FROM rigs rig
188
+ WHERE rig.id = session_row.rig_id
189
+ AND rig.account_id = NEW.account_id
190
+ AND rig.authority_scope = 'user'
191
+ UNION ALL
192
+ SELECT
193
+ 'variable_set'::text, default_variable_set.id, NULL::uuid,
194
+ 'variable_set.use'::text,
195
+ ('rig_default_variable_set:' || default_id.ordinality::text)::text,
196
+ default_variable_set.workspace_id, default_variable_set.authority_id,
197
+ default_variable_set.owner_organization_membership_id,
198
+ default_variable_set.origin_workspace_id
199
+ FROM rig_versions rig_version
200
+ CROSS JOIN LATERAL jsonb_array_elements_text(
201
+ rig_version.default_variable_set_ids
202
+ ) WITH ORDINALITY default_id(value, ordinality)
203
+ JOIN workspace_variable_sets default_variable_set
204
+ ON default_variable_set.id = default_id.value::uuid
205
+ AND default_variable_set.account_id = NEW.account_id
206
+ AND default_variable_set.authority_scope = 'user'
207
+ WHERE rig_version.id = session_row.rig_version_id
208
+ AND rig_version.rig_id = session_row.rig_id
209
+ AND rig_version.account_id = NEW.account_id
210
+ )
211
+ SELECT resource_kind, resource_id,
212
+ min(resource_version_id::text)::uuid AS resource_version_id,
213
+ action, array_agg(selection_source ORDER BY selection_source) AS selection_sources,
214
+ min(resource_workspace_id::text)::uuid AS resource_workspace_id,
215
+ min(authority_id::text)::uuid AS authority_id,
216
+ min(owner_organization_membership_id::text)::uuid
217
+ AS owner_organization_membership_id,
218
+ min(origin_workspace_id::text)::uuid AS origin_workspace_id
219
+ FROM selected
220
+ GROUP BY resource_kind, resource_id, action
221
+ ORDER BY resource_kind, resource_id
222
+ LOOP
223
+ IF resource_row.owner_organization_membership_id IS DISTINCT FROM member_row.id
224
+ OR resource_row.resource_workspace_id IS DISTINCT FROM member_row.personal_workspace_id
225
+ OR resource_row.origin_workspace_id IS DISTINCT FROM member_row.personal_workspace_id
226
+ THEN
227
+ RAISE EXCEPTION 'personal resource owner/origin does not match initiating membership'
228
+ USING ERRCODE = '42501';
229
+ END IF;
230
+
231
+ IF resource_row.resource_kind = 'variable_set' THEN
232
+ PERFORM 1 FROM workspace_variable_sets variable_set
233
+ WHERE variable_set.id = resource_row.resource_id
234
+ AND variable_set.account_id = NEW.account_id
235
+ AND variable_set.workspace_id = member_row.personal_workspace_id
236
+ AND variable_set.authority_scope = 'user'
237
+ AND variable_set.authority_id = resource_row.authority_id
238
+ AND variable_set.owner_organization_membership_id = member_row.id
239
+ AND variable_set.origin_workspace_id = member_row.personal_workspace_id
240
+ FOR SHARE;
241
+ ELSE
242
+ PERFORM 1 FROM rigs rig
243
+ WHERE rig.id = resource_row.resource_id
244
+ AND rig.account_id = NEW.account_id
245
+ AND rig.workspace_id = member_row.personal_workspace_id
246
+ AND rig.authority_scope = 'user'
247
+ AND rig.authority_id = resource_row.authority_id
248
+ AND rig.owner_organization_membership_id = member_row.id
249
+ AND rig.origin_workspace_id = member_row.personal_workspace_id
250
+ FOR SHARE;
251
+ IF FOUND THEN
252
+ PERFORM 1 FROM rig_versions rig_version
253
+ WHERE rig_version.id = resource_row.resource_version_id
254
+ AND rig_version.account_id = NEW.account_id
255
+ AND rig_version.rig_id = resource_row.resource_id
256
+ AND rig_version.workspace_id = member_row.personal_workspace_id
257
+ FOR SHARE;
258
+ END IF;
259
+ END IF;
260
+ IF NOT FOUND THEN
261
+ RAISE EXCEPTION 'personal resource identity changed during admission'
262
+ USING ERRCODE = '42501';
263
+ END IF;
264
+
265
+ PERFORM 1
266
+ FROM organization_user_resource_authorities authority
267
+ WHERE authority.id = resource_row.authority_id
268
+ AND authority.account_id = NEW.account_id
269
+ AND authority.organization_membership_id = member_row.id
270
+ AND authority.resource_kind = resource_row.resource_kind
271
+ AND authority.resource_id = resource_row.resource_id
272
+ AND authority.origin_workspace_id = member_row.personal_workspace_id
273
+ AND authority.status = 'active'
274
+ AND authority.revoked_at IS NULL
275
+ FOR SHARE;
276
+ IF NOT FOUND THEN
277
+ RAISE EXCEPTION 'personal resource authority is not live'
278
+ USING ERRCODE = '42501';
279
+ END IF;
280
+
281
+ SELECT grant_value.* INTO grant_row
282
+ FROM organization_user_resource_grants grant_value
283
+ WHERE grant_value.account_id = NEW.account_id
284
+ AND grant_value.authority_id = resource_row.authority_id
285
+ AND grant_value.owner_organization_membership_id = member_row.id
286
+ AND grant_value.workspace_id = NEW.workspace_id
287
+ AND grant_value.action = resource_row.action
288
+ AND grant_value.context = session_row.visibility
289
+ AND grant_value.status = 'active'
290
+ AND (grant_value.expires_at IS NULL OR grant_value.expires_at > clock_timestamp())
291
+ AND (
292
+ (
293
+ grant_value.mode IN ('once', 'session')
294
+ AND grant_value.session_id = NEW.session_id
295
+ AND grant_value.authority_epoch = session_row.authority_epoch
296
+ ) OR (
297
+ grant_value.mode = 'always'
298
+ AND grant_value.session_id IS NULL
299
+ AND grant_value.authority_epoch IS NULL
300
+ )
301
+ )
302
+ ORDER BY
303
+ CASE grant_value.mode WHEN 'once' THEN 1 WHEN 'session' THEN 2 ELSE 3 END,
304
+ grant_value.generation DESC,
305
+ grant_value.id
306
+ LIMIT 1
307
+ FOR UPDATE;
308
+ IF NOT FOUND THEN
309
+ RAISE EXCEPTION 'matching personal-resource grant required'
310
+ USING ERRCODE = '42501';
311
+ END IF;
312
+
313
+ INSERT INTO session_attempt_personal_resource_snapshots (
314
+ attempt_id, account_id, workspace_id, session_id, turn_id,
315
+ execution_generation, resource_kind, resource_id, resource_version_id,
316
+ selection_sources, action, origin_workspace_id,
317
+ owner_organization_membership_id, membership_authorization_revision,
318
+ authority_id, authority_generation, target_workspace_id,
319
+ session_visibility, session_authority_epoch, grant_id, grant_generation,
320
+ grant_mode, grant_context, grant_session_id, grant_authority_epoch
321
+ )
322
+ SELECT
323
+ NEW.id, NEW.account_id, NEW.workspace_id, NEW.session_id, NEW.turn_id,
324
+ NEW.execution_generation, resource_row.resource_kind, resource_row.resource_id,
325
+ resource_row.resource_version_id, resource_row.selection_sources,
326
+ resource_row.action, member_row.personal_workspace_id, member_row.id,
327
+ member_row.authorization_revision, authority.id, authority.generation,
328
+ NEW.workspace_id, session_row.visibility, session_row.authority_epoch,
329
+ grant_row.id, grant_row.generation, grant_row.mode, grant_row.context,
330
+ grant_row.session_id, grant_row.authority_epoch
331
+ FROM organization_user_resource_authorities authority
332
+ WHERE authority.id = resource_row.authority_id
333
+ AND authority.account_id = NEW.account_id;
334
+
335
+ IF grant_row.mode = 'once' THEN
336
+ UPDATE organization_user_resource_grants
337
+ SET status = 'consumed', updated_at = clock_timestamp()
338
+ WHERE id = grant_row.id
339
+ AND account_id = NEW.account_id
340
+ AND generation = grant_row.generation
341
+ AND status = 'active';
342
+ GET DIAGNOSTICS affected = ROW_COUNT;
343
+ IF affected <> 1 THEN
344
+ RAISE EXCEPTION 'once grant lost its first-use race'
345
+ USING ERRCODE = '40001';
346
+ END IF;
347
+ INSERT INTO personal_resource_once_consumption_receipts (
348
+ grant_id, account_id, attempt_id, workspace_id, session_id, turn_id,
349
+ execution_generation, authority_id, authority_generation, grant_generation
350
+ ) SELECT
351
+ grant_row.id, NEW.account_id, NEW.id, NEW.workspace_id, NEW.session_id,
352
+ NEW.turn_id, NEW.execution_generation, authority.id, authority.generation,
353
+ grant_row.generation
354
+ FROM organization_user_resource_authorities authority
355
+ WHERE authority.id = resource_row.authority_id
356
+ AND authority.account_id = NEW.account_id;
357
+ END IF;
358
+ snapshot_total := snapshot_total + 1;
359
+ END LOOP;
360
+
361
+ IF snapshot_total <> resource_total THEN
362
+ RAISE EXCEPTION 'personal-resource snapshot collection is not exact'
363
+ USING ERRCODE = '23514';
364
+ END IF;
365
+
366
+ DELETE FROM opengeni_private.personal_resource_delegation_capabilities
367
+ WHERE backend_pid = pg_catalog.pg_backend_pid()
368
+ AND transaction_id = pg_catalog.pg_current_xact_id_if_assigned()
369
+ AND capability_kind = 'admit';
370
+ RETURN NEW;
371
+ EXCEPTION WHEN OTHERS THEN
372
+ DELETE FROM opengeni_private.personal_resource_delegation_capabilities
373
+ WHERE backend_pid = pg_catalog.pg_backend_pid()
374
+ AND transaction_id = pg_catalog.pg_current_xact_id_if_assigned()
375
+ AND capability_kind = 'admit';
376
+ RAISE;
377
+ END;
378
+ $body$;
379
+ $ddl$, data_schema);
380
+
381
+ EXECUTE format($ddl$
382
+ CREATE OR REPLACE FUNCTION %1$I.resolve_session_attempt_personal_resources(
383
+ p_account_id uuid,
384
+ p_workspace_id uuid,
385
+ p_attempt_id uuid
386
+ ) RETURNS TABLE (
387
+ resource_kind text,
388
+ resource_id uuid,
389
+ resource_version_id uuid,
390
+ selection_sources text[],
391
+ action text,
392
+ authority_id uuid,
393
+ authority_generation bigint,
394
+ grant_id uuid,
395
+ grant_generation bigint,
396
+ grant_mode text
397
+ )
398
+ LANGUAGE plpgsql
399
+ SECURITY DEFINER
400
+ SET search_path = %1$I, pg_catalog
401
+ AS $body$
402
+ DECLARE
403
+ admission_row session_attempt_personal_resource_admissions%%ROWTYPE;
404
+ invalid_count integer;
405
+ caller_subject text := coalesce(
406
+ nullif(pg_catalog.current_setting('opengeni.initiating_human_subject_id', true), ''),
407
+ nullif(pg_catalog.current_setting('opengeni.subject_id', true), '')
408
+ );
409
+ BEGIN
410
+ IF p_account_id IS DISTINCT FROM nullif(
411
+ pg_catalog.current_setting('opengeni.account_id', true), ''
412
+ )::uuid
413
+ OR p_workspace_id IS DISTINCT FROM nullif(
414
+ pg_catalog.current_setting('opengeni.workspace_id', true), ''
415
+ )::uuid
416
+ THEN
417
+ RAISE EXCEPTION 'personal-resource resolve scope mismatch'
418
+ USING ERRCODE = '42501';
419
+ END IF;
420
+
421
+ INSERT INTO opengeni_private.personal_resource_delegation_capabilities (
422
+ backend_pid, transaction_id, capability_kind
423
+ ) VALUES (pg_catalog.pg_backend_pid(), pg_catalog.pg_current_xact_id(), 'resolve')
424
+ ON CONFLICT DO NOTHING;
425
+
426
+ SELECT admission.* INTO STRICT admission_row
427
+ FROM session_attempt_personal_resource_admissions admission
428
+ WHERE admission.attempt_id = p_attempt_id
429
+ AND admission.account_id = p_account_id
430
+ AND admission.workspace_id = p_workspace_id;
431
+
432
+ IF caller_subject IS DISTINCT FROM admission_row.initiating_human_subject_id THEN
433
+ RAISE EXCEPTION 'personal-resource resolve initiating human mismatch'
434
+ USING ERRCODE = '42501';
435
+ END IF;
436
+
437
+ PERFORM 1
438
+ FROM sessions session_value
439
+ JOIN session_turns turn_value
440
+ ON turn_value.account_id = session_value.account_id
441
+ AND turn_value.workspace_id = session_value.workspace_id
442
+ AND turn_value.session_id = session_value.id
443
+ JOIN session_turn_attempts attempt
444
+ ON attempt.account_id = turn_value.account_id
445
+ AND attempt.workspace_id = turn_value.workspace_id
446
+ AND attempt.session_id = turn_value.session_id
447
+ AND attempt.turn_id = turn_value.id
448
+ WHERE session_value.id = admission_row.session_id
449
+ AND session_value.account_id = admission_row.account_id
450
+ AND session_value.workspace_id = admission_row.workspace_id
451
+ AND session_value.active_turn_id = admission_row.turn_id
452
+ AND turn_value.id = admission_row.turn_id
453
+ AND turn_value.active_attempt_id = admission_row.attempt_id
454
+ AND turn_value.execution_generation = admission_row.execution_generation
455
+ AND turn_value.status = 'running'
456
+ AND attempt.id = admission_row.attempt_id
457
+ AND attempt.execution_generation = admission_row.execution_generation
458
+ AND attempt.state IN ('claimed', 'running')
459
+ AND attempt.closed_at IS NULL
460
+ AND attempt.quiesced_at IS NULL
461
+ FOR SHARE OF session_value, turn_value
462
+ FOR UPDATE OF attempt;
463
+ IF NOT FOUND THEN
464
+ RAISE EXCEPTION 'personal-resource resolve requires the exact current uninterrupted attempt'
465
+ USING ERRCODE = '42501';
466
+ END IF;
467
+
468
+ IF EXISTS (
469
+ SELECT 1
470
+ FROM session_attempt_interruptions interruption
471
+ WHERE interruption.account_id = admission_row.account_id
472
+ AND interruption.workspace_id = admission_row.workspace_id
473
+ AND interruption.session_id = admission_row.session_id
474
+ AND interruption.attempt_id = admission_row.attempt_id
475
+ AND interruption.state IN ('pending', 'delivered', 'acknowledged')
476
+ )
477
+ THEN
478
+ RAISE EXCEPTION 'personal-resource resolve requires the exact current uninterrupted attempt'
479
+ USING ERRCODE = '42501';
480
+ END IF;
481
+
482
+ SELECT count(*)::integer INTO invalid_count
483
+ FROM session_attempt_personal_resource_snapshots snapshot
484
+ WHERE snapshot.attempt_id = admission_row.attempt_id
485
+ AND NOT (
486
+ EXISTS (
487
+ SELECT 1
488
+ FROM session_turn_attempts attempt
489
+ JOIN sessions session_value
490
+ ON session_value.id = attempt.session_id
491
+ AND session_value.account_id = attempt.account_id
492
+ AND session_value.workspace_id = attempt.workspace_id
493
+ JOIN session_turns turn_value
494
+ ON turn_value.id = attempt.turn_id
495
+ AND turn_value.account_id = attempt.account_id
496
+ AND turn_value.workspace_id = attempt.workspace_id
497
+ AND turn_value.session_id = attempt.session_id
498
+ WHERE attempt.id = snapshot.attempt_id
499
+ AND attempt.account_id = snapshot.account_id
500
+ AND attempt.workspace_id = snapshot.workspace_id
501
+ AND attempt.session_id = snapshot.session_id
502
+ AND attempt.turn_id = snapshot.turn_id
503
+ AND attempt.execution_generation = snapshot.execution_generation
504
+ AND attempt.state IN ('claimed', 'running')
505
+ AND attempt.quiesced_at IS NULL
506
+ AND attempt.authority_visibility = snapshot.session_visibility
507
+ AND attempt.authority_epoch = snapshot.session_authority_epoch
508
+ AND session_value.visibility = snapshot.session_visibility
509
+ AND session_value.authority_epoch = snapshot.session_authority_epoch
510
+ AND coalesce(
511
+ nullif(btrim(turn_value.initiating_human_subject_id), ''),
512
+ CASE WHEN turn_value.initiator_kind = 'subject'
513
+ THEN nullif(btrim(turn_value.initiator_subject_id), '') END
514
+ ) = admission_row.initiating_human_subject_id
515
+ )
516
+ AND EXISTS (
517
+ SELECT 1
518
+ FROM organization_memberships membership
519
+ WHERE membership.id = snapshot.owner_organization_membership_id
520
+ AND membership.account_id = snapshot.account_id
521
+ AND membership.subject_id = admission_row.initiating_human_subject_id
522
+ AND membership.status = 'active'
523
+ AND membership.revoked_at IS NULL
524
+ AND membership.personal_workspace_id = snapshot.origin_workspace_id
525
+ AND membership.authorization_revision
526
+ = snapshot.membership_authorization_revision
527
+ AND (
528
+ membership.personal_workspace_id = snapshot.workspace_id
529
+ OR EXISTS (
530
+ SELECT 1
531
+ FROM workspace_memberships workspace_membership
532
+ WHERE workspace_membership.account_id = membership.account_id
533
+ AND workspace_membership.workspace_id = snapshot.workspace_id
534
+ AND workspace_membership.subject_id = membership.subject_id
535
+ )
536
+ )
537
+ )
538
+ AND EXISTS (
539
+ SELECT 1
540
+ FROM organization_user_resource_authorities authority
541
+ WHERE authority.id = snapshot.authority_id
542
+ AND authority.account_id = snapshot.account_id
543
+ AND authority.organization_membership_id
544
+ = snapshot.owner_organization_membership_id
545
+ AND authority.resource_kind = snapshot.resource_kind
546
+ AND authority.resource_id = snapshot.resource_id
547
+ AND authority.origin_workspace_id = snapshot.origin_workspace_id
548
+ AND authority.generation = snapshot.authority_generation
549
+ AND authority.status = 'active'
550
+ AND authority.revoked_at IS NULL
551
+ )
552
+ AND (
553
+ (
554
+ snapshot.resource_kind = 'variable_set'
555
+ AND EXISTS (
556
+ SELECT 1 FROM workspace_variable_sets variable_set
557
+ WHERE variable_set.id = snapshot.resource_id
558
+ AND variable_set.account_id = snapshot.account_id
559
+ AND variable_set.workspace_id = snapshot.origin_workspace_id
560
+ AND variable_set.authority_scope = 'user'
561
+ AND variable_set.authority_id = snapshot.authority_id
562
+ AND variable_set.owner_organization_membership_id
563
+ = snapshot.owner_organization_membership_id
564
+ AND variable_set.origin_workspace_id = snapshot.origin_workspace_id
565
+ )
566
+ ) OR (
567
+ snapshot.resource_kind = 'rig'
568
+ AND EXISTS (
569
+ SELECT 1 FROM rigs rig
570
+ JOIN rig_versions rig_version
571
+ ON rig_version.id = snapshot.resource_version_id
572
+ AND rig_version.rig_id = rig.id
573
+ AND rig_version.account_id = rig.account_id
574
+ AND rig_version.workspace_id = snapshot.origin_workspace_id
575
+ WHERE rig.id = snapshot.resource_id
576
+ AND rig.account_id = snapshot.account_id
577
+ AND rig.workspace_id = snapshot.origin_workspace_id
578
+ AND rig.authority_scope = 'user'
579
+ AND rig.authority_id = snapshot.authority_id
580
+ AND rig.owner_organization_membership_id
581
+ = snapshot.owner_organization_membership_id
582
+ AND rig.origin_workspace_id = snapshot.origin_workspace_id
583
+ )
584
+ )
585
+ )
586
+ AND EXISTS (
587
+ SELECT 1
588
+ FROM organization_user_resource_grants grant_value
589
+ WHERE grant_value.id = snapshot.grant_id
590
+ AND grant_value.account_id = snapshot.account_id
591
+ AND grant_value.authority_id = snapshot.authority_id
592
+ AND grant_value.owner_organization_membership_id
593
+ = snapshot.owner_organization_membership_id
594
+ AND grant_value.workspace_id = snapshot.target_workspace_id
595
+ AND grant_value.action = snapshot.action
596
+ AND grant_value.mode = snapshot.grant_mode
597
+ AND grant_value.context = snapshot.grant_context
598
+ AND grant_value.generation = snapshot.grant_generation
599
+ AND grant_value.session_id IS NOT DISTINCT FROM snapshot.grant_session_id
600
+ AND grant_value.authority_epoch
601
+ IS NOT DISTINCT FROM snapshot.grant_authority_epoch
602
+ AND (grant_value.expires_at IS NULL OR grant_value.expires_at > clock_timestamp())
603
+ AND (
604
+ (
605
+ snapshot.grant_mode = 'once'
606
+ AND grant_value.status = 'consumed'
607
+ AND EXISTS (
608
+ SELECT 1 FROM personal_resource_once_consumption_receipts receipt
609
+ WHERE receipt.grant_id = snapshot.grant_id
610
+ AND receipt.account_id = snapshot.account_id
611
+ AND receipt.attempt_id = snapshot.attempt_id
612
+ AND receipt.authority_id = snapshot.authority_id
613
+ AND receipt.authority_generation = snapshot.authority_generation
614
+ AND receipt.grant_generation = snapshot.grant_generation
615
+ )
616
+ ) OR (
617
+ snapshot.grant_mode IN ('session', 'always')
618
+ AND grant_value.status = 'active'
619
+ )
620
+ )
621
+ )
622
+ );
623
+
624
+ IF invalid_count <> 0 THEN
625
+ RAISE EXCEPTION 'personal-resource authority snapshot is no longer live'
626
+ USING ERRCODE = '42501';
627
+ END IF;
628
+
629
+ SELECT count(*)::integer INTO invalid_count
630
+ FROM session_attempt_personal_resource_snapshots snapshot
631
+ WHERE snapshot.attempt_id = admission_row.attempt_id;
632
+ IF invalid_count <> admission_row.resource_count THEN
633
+ RAISE EXCEPTION 'personal-resource snapshot collection is incomplete'
634
+ USING ERRCODE = '42501';
635
+ END IF;
636
+
637
+ RETURN QUERY
638
+ SELECT snapshot.resource_kind, snapshot.resource_id,
639
+ snapshot.resource_version_id, snapshot.selection_sources, snapshot.action,
640
+ snapshot.authority_id, snapshot.authority_generation, snapshot.grant_id,
641
+ snapshot.grant_generation, snapshot.grant_mode
642
+ FROM session_attempt_personal_resource_snapshots snapshot
643
+ WHERE snapshot.attempt_id = admission_row.attempt_id
644
+ ORDER BY snapshot.resource_kind, snapshot.resource_id;
645
+
646
+ DELETE FROM opengeni_private.personal_resource_delegation_capabilities
647
+ WHERE backend_pid = pg_catalog.pg_backend_pid()
648
+ AND transaction_id = pg_catalog.pg_current_xact_id_if_assigned()
649
+ AND capability_kind = 'resolve';
650
+ RETURN;
651
+ EXCEPTION WHEN OTHERS THEN
652
+ DELETE FROM opengeni_private.personal_resource_delegation_capabilities
653
+ WHERE backend_pid = pg_catalog.pg_backend_pid()
654
+ AND transaction_id = pg_catalog.pg_current_xact_id_if_assigned()
655
+ AND capability_kind = 'resolve';
656
+ RAISE;
657
+ END;
658
+ $body$;
659
+ $ddl$, data_schema);
660
+
661
+ END
662
+ $personal_resource_delegation_authority_correction$;