@opengeni/db 0.36.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 (274) 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-GYO7ED2Q.js → chunk-EULAN2NP.js} +2 -2
  7. package/dist/{chunk-VTPRIXKG.js → chunk-NJVZPWXY.js} +3 -3
  8. package/dist/{chunk-HSOWSYOX.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-5KTIEDX7.js → chunk-PR2WMLOQ.js} +7714 -4443
  13. package/dist/chunk-PR2WMLOQ.js.map +1 -0
  14. package/dist/{chunk-Z7VYMNPZ.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.d.ts +10 -0
  36. package/dist/editable-artifact-durable-export.js +18 -3
  37. package/dist/editable-artifact-durable-export.js.map +1 -1
  38. package/dist/editable-artifacts.d.ts +2 -2
  39. package/dist/editable-artifacts.js +3 -3
  40. package/dist/governed-learning-activation-schema.d.ts +984 -0
  41. package/dist/governed-learning-activation.d.ts +98 -0
  42. package/dist/governed-learning-evaluator-schema.d.ts +633 -0
  43. package/dist/governed-learning-evaluator.d.ts +28 -0
  44. package/dist/index.d.ts +1633 -87
  45. package/dist/index.js +22004 -8109
  46. package/dist/index.js.map +1 -1
  47. package/dist/insights.d.ts +18 -0
  48. package/dist/integration-bindings.d.ts +1 -0
  49. package/dist/integration-facets.d.ts +30 -0
  50. package/dist/interaction-placement-loss.d.ts +22 -0
  51. package/dist/knowledge-source-sync-schema.d.ts +730 -0
  52. package/dist/knowledge-source-sync.d.ts +60 -0
  53. package/dist/managed-human-provisioning.d.ts +25 -0
  54. package/dist/memory-domain.d.ts +3 -3
  55. package/dist/migrate.d.ts +11 -1
  56. package/dist/migrate.js +1 -1
  57. package/dist/new-session-drafts.d.ts +43 -5
  58. package/dist/organization-membership-backfill.d.ts +174 -0
  59. package/dist/organization-membership-lifecycle.d.ts +162 -0
  60. package/dist/pr-review.d.ts +107 -0
  61. package/dist/preference-registry-schema.d.ts +2 -0
  62. package/dist/preference-registry.d.ts +2 -0
  63. package/dist/provision-roles.js +1 -1
  64. package/dist/runtime-posture.d.ts +23 -9
  65. package/dist/schema.d.ts +24925 -13697
  66. package/dist/schema.js +103 -1
  67. package/dist/scoped-knowledge-schema.d.ts +52 -1
  68. package/dist/session-background-commands.d.ts +125 -0
  69. package/dist/session-background-commands.js +34 -0
  70. package/dist/session-background-commands.js.map +1 -0
  71. package/dist/session-control.d.ts +156 -3
  72. package/dist/session-goal-pacing.d.ts +68 -0
  73. package/dist/session-queue-commands.d.ts +42 -5
  74. package/dist/session-realtime-ledger.d.ts +3 -0
  75. package/dist/session-tenancy.d.ts +71 -1
  76. package/dist/session-tenancy.js +25 -3
  77. package/dist/session-tool-call-settlement.d.ts +9 -4
  78. package/dist/slack-routing-personal-workspace.d.ts +23 -0
  79. package/dist/slack-routing.d.ts +153 -0
  80. package/dist/slack-task-policy-schema.d.ts +34 -0
  81. package/dist/slack-task-policy.d.ts +8 -0
  82. package/dist/slack-user-link-access.d.ts +1 -0
  83. package/dist/task-notes-schema.d.ts +594 -0
  84. package/dist/task-notes.d.ts +39 -0
  85. package/dist/turn-initiator.d.ts +2 -0
  86. package/dist/user-resource-authority.d.ts +109 -0
  87. package/dist/video-generation.js +3 -3
  88. package/dist/workspace-authority.d.ts +81 -0
  89. package/dist/workspace-instruction-policies-schema.d.ts +279 -0
  90. package/dist/workspace-instruction-policies.d.ts +62 -0
  91. package/dist/workspace-learning-policy.d.ts +1 -0
  92. package/dist/workspace-membership-permissions.d.ts +2 -0
  93. package/drizzle/0240_enrollment_connection_authority.sql +39 -0
  94. package/drizzle/0240_model_context_user_messages.sql +204 -0
  95. package/drizzle/0241_atomic_personal_resource_delegation.sql +1000 -0
  96. package/drizzle/0241_enrollment_agent_runtime.sql +70 -0
  97. package/drizzle/0243_google_drive_object_acl_authority.sql +554 -0
  98. package/drizzle/0244_slack_app_home_refresh_queue.sql +120 -0
  99. package/drizzle/0245_model_context_contribution_facts.sql +88 -0
  100. package/drizzle/0246_integration_personal_instance_authority.sql +70 -0
  101. package/drizzle/0247_terraform_stacks_provenance_repair.sql +428 -0
  102. package/drizzle/0248_terraform_stacks_component_resolution_fence.sql +83 -0
  103. package/drizzle/0249_personal_resource_delegation_authority_correction.sql +662 -0
  104. package/drizzle/0250_direct_retained_process_owner_liveness.sql +199 -0
  105. package/drizzle/0251_connected_machine_operation_policy.sql +45 -0
  106. package/drizzle/0252_scheduled_personal_resource_delegation.sql +1867 -0
  107. package/drizzle/0253_common_user_resource_authority_lifecycle.sql +1555 -0
  108. package/drizzle/0254_scoped_variable_set_authority.sql +1255 -0
  109. package/drizzle/0255_company_brain_governed_write_proposals.sql +524 -0
  110. package/drizzle/0256_connection_authority_delegation.sql +703 -0
  111. package/drizzle/0257_goal_revision_decisions_and_root_constraints.sql +436 -0
  112. package/drizzle/0258_three_scope_document_knowledge_authority.sql +1273 -0
  113. package/drizzle/0259_company_brain_context_selection_receipts.sql +869 -0
  114. package/drizzle/0260_task_note_knowledge_promotion.sql +820 -0
  115. package/drizzle/0261_preference_knowledge_proposal_actor_binding.sql +471 -0
  116. package/drizzle/0262_scoped_connected_machines_and_rigs.sql +1700 -0
  117. package/drizzle/0263_organization_membership_lifecycle.sql +3284 -0
  118. package/drizzle/0264_connection_authority_runtime_activation.sql +1084 -0
  119. package/drizzle/0266_company_brain_context_receipt_inspection.sql +156 -0
  120. package/drizzle/0268_governed_learning_decision_receipts.sql +825 -0
  121. package/drizzle/0269_governed_learning_activation_controller.sql +1874 -0
  122. package/drizzle/0270_governed_learning_history_inspection.sql +170 -0
  123. package/drizzle/0271_company_brain_retrieval_only_default.sql +524 -0
  124. package/drizzle/0272_human_confirmed_learning_activation.sql +591 -0
  125. package/drizzle/0273_scheduled_variable_set_materialization.sql +268 -0
  126. package/drizzle/0274_human_confirmed_knowledge_review.sql +310 -0
  127. package/drizzle/0275_scheduled_connection_authority.sql +5527 -0
  128. package/drizzle/0276_onboarding_proposal_initiating_human_guc.sql +198 -0
  129. package/drizzle/0277_workspace_writer_authority_attribution.sql +393 -0
  130. package/drizzle/0278_workspace_membership_removal_fencing.sql +1174 -0
  131. package/drizzle/0279_workspace_connection_use_lane.sql +343 -0
  132. package/drizzle/0280_connection_and_variable_set_audit_attribution.sql +773 -0
  133. package/drizzle/0281_viewer_holder_authority_claims.sql +52 -0
  134. package/drizzle/0282_variable_set_session_attach_attribution.sql +178 -0
  135. package/drizzle/0283_editable_spreadsheet_authored_state.sql +82 -0
  136. package/drizzle/0284_truthful_human_confirmed_review_reason.sql +930 -0
  137. package/drizzle/0285_organization_tenancy_inventory.sql +329 -0
  138. package/drizzle/0286_widen_task_note_expiry_ceiling.sql +391 -0
  139. package/drizzle/0287_open_suffix_pending_tool_calls.sql +18 -0
  140. package/drizzle/0288_attached_browser_reenrollment.sql +64 -0
  141. package/drizzle/0289_session_composer_policy_authority.sql +597 -0
  142. package/drizzle/0290_organization_membership_backfill.sql +268 -0
  143. package/drizzle/0291_resource_authority_classification_assertion.sql +371 -0
  144. package/drizzle/0292_truthful_tenancy_inventory_counters.sql +291 -0
  145. package/drizzle/0293_confirm_time_rule_rebaseline.sql +615 -0
  146. package/drizzle/0294_preference_activation_authority.sql +237 -0
  147. package/drizzle/0295_retire_legacy_standing_memory_mode.sql +476 -0
  148. package/drizzle/0296_force_rls_backfill_noop_repair.sql +215 -0
  149. package/drizzle/0297_session_ownership_classification_and_backfill.sql +752 -0
  150. package/drizzle/0298_organization_tenancy_parity.sql +609 -0
  151. package/drizzle/0299_organization_membership_lock_order.sql +291 -0
  152. package/drizzle/0300_tenancy_backfill_ledger.sql +459 -0
  153. package/drizzle/0301_session_snapshot_and_pin_visibility.sql +181 -0
  154. package/drizzle/0302_personal_workspace_session_ownership.sql +303 -0
  155. package/drizzle/0303_session_tenancy_product_activation.sql +919 -0
  156. package/drizzle/0304_personal_workspace_private_session_reads.sql +97 -0
  157. package/drizzle/0305_personal_resource_grant_management.sql +584 -0
  158. package/drizzle/0306_atomic_personal_resource_attachments.sql +1374 -0
  159. package/drizzle/0307_session_attention_state.sql +51 -0
  160. package/drizzle/0308_session_archives.sql +35 -0
  161. package/drizzle/0309_channel_project_pins.sql +6 -0
  162. package/drizzle/0310_channel_project_order.sql +27 -0
  163. package/drizzle/0311_company_scope_and_private_session_create.sql +656 -0
  164. package/drizzle/0312_quiescent_session_tree_deletion.sql +39 -0
  165. package/drizzle/0313_private_child_session_authority.sql +365 -0
  166. package/drizzle/0314_unregistered_organization_invitations.sql +606 -0
  167. package/drizzle/0315_personal_github_repository_selection.sql +624 -0
  168. package/drizzle/0316_human_confirmed_activation_resumed_generation.sql +869 -0
  169. package/drizzle/0317_session_goal_continuation_hold.sql +64 -0
  170. package/drizzle/0318_session_turn_startup_milestones.sql +115 -0
  171. package/drizzle/0319_event_triggered_automations.sql +254 -0
  172. package/drizzle/0320_pr_review_pack.sql +113 -0
  173. package/drizzle/0321_slack_bot_environment_display_name.sql +15 -0
  174. package/drizzle/0322_session_turns_unclaimed_prompt_trigger_index.sql +5 -0
  175. package/drizzle/0323_organization_private_session_enablement.sql +489 -0
  176. package/drizzle/0324_human_confirmed_company_profile_agent_admin.sql +856 -0
  177. package/drizzle/0325_child_lifecycle_notices.sql +44 -0
  178. package/drizzle/0326_interaction_operation_error_codes.sql +62 -0
  179. package/drizzle/0327_slack_first_task_hint.sql +29 -0
  180. package/drizzle/0328_session_background_commands.sql +590 -0
  181. package/drizzle/0329_slack_orchestration_delivery_events.sql +91 -0
  182. package/drizzle/0330_api_key_descriptions.sql +20 -0
  183. package/drizzle/0331_managed_organization_creation.sql +163 -0
  184. package/drizzle/0332_organization_shared_workspace_control_plane.sql +539 -0
  185. package/drizzle/0333_session_turn_prompt_routing.sql +45 -0
  186. package/drizzle/0334_connected_machine_workspace_root.sql +99 -0
  187. package/drizzle/0335_slack_workspace_routing.sql +460 -0
  188. package/drizzle/0336_atomic_session_fork_visibility.sql +667 -0
  189. package/drizzle/0337_slack_routed_action_handles.sql +189 -0
  190. package/drizzle/0338_atomic_connected_machine_attachments.sql +410 -0
  191. package/drizzle/0339_document_authority_reclassification.sql +1153 -0
  192. package/drizzle/0340_tenancy_backfill_activation_evidence.sql +1347 -0
  193. package/drizzle/0341_slack_routing_probe_organization_fence.sql +109 -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 +81 -0
  212. package/src/connection-token-resolver.ts +263 -31
  213. package/src/database.ts +75 -2
  214. package/src/editable-artifact-durable-export.ts +27 -0
  215. package/src/editable-artifacts-schema.ts +10 -5
  216. package/src/editable-artifacts.ts +21 -11
  217. package/src/governed-learning-activation-schema.ts +121 -0
  218. package/src/governed-learning-activation.ts +588 -0
  219. package/src/governed-learning-evaluator-schema.ts +72 -0
  220. package/src/governed-learning-evaluator.ts +217 -0
  221. package/src/index.ts +12001 -1699
  222. package/src/insights.ts +107 -0
  223. package/src/integration-bindings.ts +88 -6
  224. package/src/integration-facets.ts +287 -84
  225. package/src/interaction-placement-loss.ts +234 -0
  226. package/src/knowledge-source-sync-schema.ts +83 -0
  227. package/src/knowledge-source-sync.ts +530 -0
  228. package/src/managed-human-provisioning.ts +116 -0
  229. package/src/memory-domain.ts +27 -32
  230. package/src/migrate.ts +77 -1
  231. package/src/new-session-drafts.ts +229 -35
  232. package/src/organization-membership-backfill.ts +735 -0
  233. package/src/organization-membership-lifecycle.ts +985 -0
  234. package/src/pr-review.ts +890 -0
  235. package/src/preference-registry.ts +31 -1
  236. package/src/provision-roles.ts +931 -24
  237. package/src/runtime-posture-cli.ts +2 -0
  238. package/src/runtime-posture.ts +1315 -52
  239. package/src/schema.ts +3336 -438
  240. package/src/scoped-knowledge-schema.ts +16 -8
  241. package/src/scoped-knowledge.ts +1 -1
  242. package/src/session-background-commands.ts +759 -0
  243. package/src/session-control.ts +640 -74
  244. package/src/session-goal-pacing.ts +126 -0
  245. package/src/session-queue-commands.ts +450 -98
  246. package/src/session-realtime-context.ts +19 -3
  247. package/src/session-realtime-ledger.ts +75 -12
  248. package/src/session-realtime-mirror.ts +1 -1
  249. package/src/session-tenancy.ts +403 -49
  250. package/src/session-tool-call-settlement.ts +38 -29
  251. package/src/slack-routing-personal-workspace.ts +67 -0
  252. package/src/slack-routing.ts +469 -0
  253. package/src/slack-task-policy-schema.ts +5 -0
  254. package/src/slack-task-policy.ts +18 -0
  255. package/src/slack-user-link-access.ts +17 -1
  256. package/src/task-notes-schema.ts +74 -0
  257. package/src/task-notes.ts +124 -2
  258. package/src/turn-initiator.ts +8 -0
  259. package/src/user-resource-authority.ts +377 -0
  260. package/src/workspace-authority.ts +160 -0
  261. package/src/workspace-instruction-policies-schema.ts +53 -1
  262. package/src/workspace-instruction-policies.ts +528 -77
  263. package/src/workspace-learning-policy.ts +21 -5
  264. package/src/workspace-membership-permissions.ts +9 -0
  265. package/dist/chunk-5KTIEDX7.js.map +0 -1
  266. package/dist/chunk-FPVAD4CO.js +0 -117
  267. package/dist/chunk-FPVAD4CO.js.map +0 -1
  268. package/dist/chunk-HSOWSYOX.js.map +0 -1
  269. package/dist/chunk-SK7YYHBI.js.map +0 -1
  270. package/dist/chunk-VKLB2ZGI.js +0 -2389
  271. package/dist/chunk-VKLB2ZGI.js.map +0 -1
  272. package/dist/chunk-Z7VYMNPZ.js.map +0 -1
  273. /package/dist/{chunk-GYO7ED2Q.js.map → chunk-EULAN2NP.js.map} +0 -0
  274. /package/dist/{chunk-VTPRIXKG.js.map → chunk-NJVZPWXY.js.map} +0 -0
@@ -0,0 +1,268 @@
1
+ -- deployment-mode: rolling
2
+ -- Migration 0273: let exact pure-service attempts materialize organization-
3
+ -- and workspace-scoped Variable Sets. Migration 0254 required every runtime
4
+ -- materialization to resolve to an initiating human, which incorrectly failed
5
+ -- scheduled runs even though those scopes are not personal resources. Exact
6
+ -- secret reads remain human-only through assert_scoped_variable_set_attempt;
7
+ -- user-scoped runtime materialization still requires a causal human plus the
8
+ -- immutable personal-resource grant admitted for this exact attempt.
9
+
10
+ SET LOCAL lock_timeout = '5s';
11
+ SET LOCAL statement_timeout = '10min';
12
+
13
+ CREATE OR REPLACE FUNCTION assert_scoped_variable_set_materialization_attempt(
14
+ p_account_id uuid,
15
+ p_workspace_id uuid,
16
+ p_session_id uuid,
17
+ p_turn_id uuid,
18
+ p_attempt_id uuid,
19
+ p_execution_generation integer
20
+ ) RETURNS TABLE (
21
+ actor_subject text,
22
+ causal_human_subject text,
23
+ actor_kind text
24
+ )
25
+ LANGUAGE plpgsql
26
+ SECURITY DEFINER
27
+ SET search_path FROM CURRENT
28
+ AS $$
29
+ DECLARE
30
+ stored_human_subject text;
31
+ exact_initiator_kind text;
32
+ exact_initiator_subject text;
33
+ caller_subject text := nullif(
34
+ pg_catalog.current_setting('opengeni.subject_id', true), ''
35
+ );
36
+ caller_human_subject text := nullif(
37
+ pg_catalog.current_setting('opengeni.initiating_human_subject_id', true), ''
38
+ );
39
+ BEGIN
40
+ IF p_account_id IS DISTINCT FROM nullif(
41
+ pg_catalog.current_setting('opengeni.account_id', true), ''
42
+ )::uuid
43
+ OR p_workspace_id IS DISTINCT FROM nullif(
44
+ pg_catalog.current_setting('opengeni.workspace_id', true), ''
45
+ )::uuid
46
+ OR p_execution_generation <= 0
47
+ THEN
48
+ RAISE EXCEPTION 'variable-set materialization attempt scope mismatch'
49
+ USING ERRCODE = '42501';
50
+ END IF;
51
+
52
+ SELECT
53
+ nullif(pg_catalog.btrim(turn_value.initiating_human_subject_id), ''),
54
+ turn_value.initiator_kind,
55
+ nullif(pg_catalog.btrim(turn_value.initiator_subject_id), '')
56
+ INTO STRICT stored_human_subject, exact_initiator_kind, exact_initiator_subject
57
+ FROM sessions session_value
58
+ JOIN session_turns turn_value
59
+ ON turn_value.id = p_turn_id
60
+ AND turn_value.account_id = session_value.account_id
61
+ AND turn_value.workspace_id = session_value.workspace_id
62
+ AND turn_value.session_id = session_value.id
63
+ JOIN session_turn_attempts attempt
64
+ ON attempt.id = p_attempt_id
65
+ AND attempt.account_id = turn_value.account_id
66
+ AND attempt.workspace_id = turn_value.workspace_id
67
+ AND attempt.session_id = turn_value.session_id
68
+ AND attempt.turn_id = turn_value.id
69
+ WHERE session_value.id = p_session_id
70
+ AND session_value.account_id = p_account_id
71
+ AND session_value.workspace_id = p_workspace_id
72
+ AND session_value.active_turn_id = p_turn_id
73
+ AND turn_value.active_attempt_id = p_attempt_id
74
+ AND turn_value.execution_generation = p_execution_generation
75
+ AND turn_value.status = 'running'
76
+ AND attempt.execution_generation = p_execution_generation
77
+ AND attempt.state IN ('claimed', 'running')
78
+ AND attempt.closed_at IS NULL
79
+ AND attempt.quiesced_at IS NULL
80
+ AND attempt.authority_epoch = session_value.authority_epoch
81
+ AND attempt.authority_visibility = session_value.visibility
82
+ AND attempt.authority_owner_organization_membership_id
83
+ IS NOT DISTINCT FROM session_value.owner_organization_membership_id
84
+ AND NOT EXISTS (
85
+ SELECT 1 FROM session_attempt_interruptions interruption
86
+ WHERE interruption.account_id = p_account_id
87
+ AND interruption.workspace_id = p_workspace_id
88
+ AND interruption.session_id = p_session_id
89
+ AND interruption.attempt_id = p_attempt_id
90
+ AND interruption.state IN ('pending', 'delivered', 'acknowledged')
91
+ )
92
+ FOR SHARE OF session_value, turn_value
93
+ FOR UPDATE OF attempt;
94
+
95
+ causal_human_subject := coalesce(
96
+ stored_human_subject,
97
+ CASE WHEN exact_initiator_kind = 'subject' THEN exact_initiator_subject END
98
+ );
99
+ actor_subject := coalesce(causal_human_subject, exact_initiator_subject);
100
+ actor_kind := CASE WHEN causal_human_subject IS NULL THEN exact_initiator_kind ELSE 'subject' END;
101
+ IF actor_subject IS NULL
102
+ OR caller_subject IS DISTINCT FROM actor_subject
103
+ OR caller_human_subject IS DISTINCT FROM stored_human_subject
104
+ THEN
105
+ RAISE EXCEPTION 'variable-set materialization attempt actor mismatch'
106
+ USING ERRCODE = '42501';
107
+ END IF;
108
+ RETURN NEXT;
109
+ EXCEPTION WHEN NO_DATA_FOUND THEN
110
+ RAISE EXCEPTION 'variable-set materialization requires the exact current uninterrupted attempt'
111
+ USING ERRCODE = '42501';
112
+ END
113
+ $$;
114
+
115
+ CREATE OR REPLACE FUNCTION materialize_scoped_variable_set_for_attempt(
116
+ p_account_id uuid,
117
+ p_workspace_id uuid,
118
+ p_session_id uuid,
119
+ p_turn_id uuid,
120
+ p_attempt_id uuid,
121
+ p_execution_generation integer,
122
+ p_variable_set_id uuid
123
+ ) RETURNS TABLE (
124
+ variable_set_id uuid,
125
+ variable_set_name text,
126
+ variable_set_description text,
127
+ authority_scope text,
128
+ variable_set_generation bigint,
129
+ variable_name text,
130
+ value_encrypted text
131
+ )
132
+ LANGUAGE plpgsql
133
+ SECURITY DEFINER
134
+ SET search_path FROM CURRENT
135
+ AS $$
136
+ DECLARE
137
+ audit_subject text;
138
+ causal_human text;
139
+ audit_actor_kind text;
140
+ variable_set_row workspace_variable_sets%ROWTYPE;
141
+ resolved_count integer;
142
+ BEGIN
143
+ INSERT INTO opengeni_private.variable_set_authority_capabilities (
144
+ backend_pid, transaction_id, capability_kind
145
+ ) VALUES (pg_catalog.pg_backend_pid(), pg_catalog.pg_current_xact_id(), 'materialize')
146
+ ON CONFLICT DO NOTHING;
147
+
148
+ SELECT actor_subject, causal_human_subject, actor_kind
149
+ INTO STRICT audit_subject, causal_human, audit_actor_kind
150
+ FROM assert_scoped_variable_set_materialization_attempt(
151
+ p_account_id, p_workspace_id, p_session_id, p_turn_id, p_attempt_id,
152
+ p_execution_generation
153
+ );
154
+
155
+ SELECT variable_set.* INTO STRICT variable_set_row
156
+ FROM workspace_variable_sets variable_set
157
+ WHERE variable_set.id = p_variable_set_id
158
+ AND variable_set.account_id = p_account_id
159
+ AND variable_set.status = 'active'
160
+ FOR SHARE;
161
+
162
+ PERFORM 1 FROM sessions session_value
163
+ LEFT JOIN rig_versions rig_version
164
+ ON rig_version.id = session_value.rig_version_id
165
+ AND rig_version.rig_id = session_value.rig_id
166
+ AND rig_version.account_id = session_value.account_id
167
+ WHERE session_value.id = p_session_id
168
+ AND session_value.account_id = p_account_id
169
+ AND session_value.workspace_id = p_workspace_id
170
+ AND (
171
+ session_value.variable_set_id = variable_set_row.id
172
+ OR coalesce(rig_version.default_variable_set_ids, '[]'::jsonb)
173
+ ? variable_set_row.id::text
174
+ );
175
+ IF NOT FOUND THEN
176
+ RAISE EXCEPTION 'runtime variable set was not selected by the exact session'
177
+ USING ERRCODE = '42501';
178
+ END IF;
179
+
180
+ IF variable_set_row.authority_scope = 'workspace'
181
+ AND variable_set_row.workspace_id IS DISTINCT FROM p_workspace_id
182
+ THEN
183
+ RAISE EXCEPTION 'workspace variable set is outside the runtime workspace'
184
+ USING ERRCODE = '42501';
185
+ ELSIF variable_set_row.authority_scope = 'user' THEN
186
+ IF causal_human IS NULL THEN
187
+ RAISE EXCEPTION 'personal variable-set materialization requires an initiating human subject'
188
+ USING ERRCODE = '42501';
189
+ END IF;
190
+ SELECT count(*)::integer INTO resolved_count
191
+ FROM resolve_session_attempt_personal_resources(
192
+ p_account_id, p_workspace_id, p_attempt_id
193
+ ) resolved
194
+ WHERE resolved.resource_kind = 'variable_set'
195
+ AND resolved.resource_id = variable_set_row.id
196
+ AND resolved.authority_id = variable_set_row.authority_id
197
+ AND resolved.authority_generation = variable_set_row.generation;
198
+ IF resolved_count <> 1 THEN
199
+ RAISE EXCEPTION 'personal variable-set grant is not exact or current'
200
+ USING ERRCODE = '42501';
201
+ END IF;
202
+ END IF;
203
+
204
+ INSERT INTO audit_events (
205
+ account_id, workspace_id, subject_id, action, target_type, target_id,
206
+ metadata, metadata_codec_version
207
+ ) VALUES (
208
+ p_account_id, p_workspace_id, audit_subject,
209
+ 'variable_set.materialized', 'workspace_variable_set',
210
+ variable_set_row.id::text,
211
+ pg_catalog.jsonb_build_object(
212
+ 'variableSetId', variable_set_row.id,
213
+ 'scope', variable_set_row.authority_scope,
214
+ 'generation', variable_set_row.generation,
215
+ 'actorKind', audit_actor_kind,
216
+ 'sessionId', p_session_id,
217
+ 'turnId', p_turn_id,
218
+ 'attemptId', p_attempt_id,
219
+ 'executionGeneration', p_execution_generation
220
+ ),
221
+ 1
222
+ );
223
+
224
+ RETURN QUERY
225
+ SELECT selected.id, selected.name, selected.description,
226
+ selected.authority_scope, selected.generation,
227
+ variable.name, variable.value_encrypted
228
+ FROM workspace_variable_sets selected
229
+ LEFT JOIN workspace_variable_set_variables variable
230
+ ON variable.account_id = selected.account_id
231
+ AND variable.variable_set_id = selected.id
232
+ WHERE selected.id = variable_set_row.id
233
+ ORDER BY variable.name;
234
+
235
+ DELETE FROM opengeni_private.variable_set_authority_capabilities
236
+ WHERE backend_pid = pg_catalog.pg_backend_pid()
237
+ AND transaction_id = pg_catalog.pg_current_xact_id_if_assigned()
238
+ AND capability_kind = 'materialize';
239
+ RETURN;
240
+ EXCEPTION WHEN OTHERS THEN
241
+ DELETE FROM opengeni_private.variable_set_authority_capabilities
242
+ WHERE backend_pid = pg_catalog.pg_backend_pid()
243
+ AND transaction_id = pg_catalog.pg_current_xact_id_if_assigned()
244
+ AND capability_kind = 'materialize';
245
+ RAISE;
246
+ END
247
+ $$;
248
+
249
+ REVOKE ALL ON FUNCTION assert_scoped_variable_set_materialization_attempt(
250
+ uuid, uuid, uuid, uuid, uuid, integer
251
+ ) FROM PUBLIC;
252
+ REVOKE ALL ON FUNCTION materialize_scoped_variable_set_for_attempt(
253
+ uuid, uuid, uuid, uuid, uuid, integer, uuid
254
+ ) FROM PUBLIC;
255
+
256
+ DO $$
257
+ BEGIN
258
+ IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'opengeni_app') THEN
259
+ GRANT EXECUTE ON FUNCTION materialize_scoped_variable_set_for_attempt(
260
+ uuid, uuid, uuid, uuid, uuid, integer, uuid
261
+ ) TO opengeni_app;
262
+ END IF;
263
+ END
264
+ $$;
265
+
266
+ COMMENT ON FUNCTION materialize_scoped_variable_set_for_attempt(
267
+ uuid, uuid, uuid, uuid, uuid, integer, uuid
268
+ ) IS 'Only ciphertext egress for runtime injection; exact service attempts may materialize organization/workspace sets, while personal sets require an exact causal-human grant.';
@@ -0,0 +1,310 @@
1
+ -- deployment-mode: rolling
2
+ SET lock_timeout = '5s';
3
+ SET statement_timeout = '60s';
4
+
5
+ -- Human-confirmed Knowledge approval for explicit `remember` facts. A
6
+ -- user-directed Knowledge claim (Task-note evidence) is approved only after the
7
+ -- exact initiating human answered the bound structured human-input question
8
+ -- (`remember:<claimId>` = `save`, canonical prompt, exact note text as help
9
+ -- text) on the same live turn. The approval is written through the same
10
+ -- guarded service-review path the governed-learning controller uses and is
11
+ -- recorded on an immutable, content-free receipt ledger.
12
+
13
+ CREATE TABLE "remember_knowledge_confirmation_receipts" (
14
+ "id" uuid PRIMARY KEY DEFAULT pg_catalog.gen_random_uuid(),
15
+ "account_id" uuid NOT NULL REFERENCES "managed_accounts"("id") ON DELETE CASCADE,
16
+ "workspace_id" uuid NOT NULL REFERENCES "workspaces"("id") ON DELETE CASCADE,
17
+ "operation_id" uuid NOT NULL,
18
+ "input_hash" text NOT NULL,
19
+ "session_id" uuid NOT NULL,
20
+ "turn_id" uuid NOT NULL,
21
+ "execution_generation" integer NOT NULL,
22
+ "initiating_human_subject_id" text NOT NULL,
23
+ "service_actor_subject_id" text NOT NULL,
24
+ "claim_id" uuid NOT NULL,
25
+ "evidence_id" uuid NOT NULL,
26
+ "task_note_id" uuid NOT NULL,
27
+ "task_note_text_hash" text NOT NULL,
28
+ "human_input_request_id" uuid NOT NULL,
29
+ "previous_review_id" uuid NOT NULL,
30
+ "previous_review_revision" bigint NOT NULL,
31
+ "approval_review_id" uuid NOT NULL,
32
+ "approval_review_revision" bigint NOT NULL,
33
+ "created_at" timestamptz NOT NULL DEFAULT now(),
34
+ UNIQUE ("workspace_id", "operation_id"),
35
+ UNIQUE ("claim_id"),
36
+ CONSTRAINT "remember_knowledge_confirmation_receipts_actor_chk" CHECK (
37
+ length(btrim("initiating_human_subject_id")) BETWEEN 1 AND 1024
38
+ AND "service_actor_subject_id" LIKE 'service:governed-learning-activation:%'
39
+ AND "execution_generation" > 0
40
+ AND "input_hash" ~ '^[0-9a-f]{64}$'
41
+ AND "task_note_text_hash" ~ '^[0-9a-f]{64}$'
42
+ )
43
+ );
44
+ CREATE INDEX "remember_knowledge_confirmation_receipts_workspace_time_idx"
45
+ ON "remember_knowledge_confirmation_receipts" ("workspace_id", "created_at" DESC, "id" DESC);
46
+
47
+ ALTER TABLE "remember_knowledge_confirmation_receipts" ENABLE ROW LEVEL SECURITY;
48
+ ALTER TABLE "remember_knowledge_confirmation_receipts" FORCE ROW LEVEL SECURITY;
49
+ CREATE POLICY remember_knowledge_confirmation_receipts_tenant
50
+ ON "remember_knowledge_confirmation_receipts"
51
+ USING (opengeni_private.workspace_rls_visible("account_id", "workspace_id"))
52
+ WITH CHECK (opengeni_private.workspace_rls_visible("account_id", "workspace_id"));
53
+ CREATE POLICY session_visibility_isolation
54
+ ON "remember_knowledge_confirmation_receipts" AS RESTRICTIVE
55
+ USING (session_reference_visible("account_id", "workspace_id", "session_id"))
56
+ WITH CHECK (session_reference_visible("account_id", "workspace_id", "session_id"));
57
+
58
+ CREATE OR REPLACE FUNCTION reject_remember_knowledge_confirmation_receipt_mutation()
59
+ RETURNS trigger LANGUAGE plpgsql AS $$
60
+ BEGIN
61
+ IF TG_OP = 'DELETE' AND pg_catalog.pg_trigger_depth() > 1 AND (
62
+ NOT EXISTS (SELECT 1 FROM workspaces WHERE id = OLD.workspace_id)
63
+ OR NOT EXISTS (SELECT 1 FROM sessions WHERE workspace_id = OLD.workspace_id AND id = OLD.session_id)
64
+ OR NOT EXISTS (SELECT 1 FROM knowledge_claims WHERE id = OLD.claim_id)
65
+ ) THEN
66
+ RETURN OLD;
67
+ END IF;
68
+ RAISE EXCEPTION 'remember Knowledge confirmation receipts are immutable' USING ERRCODE = '55000';
69
+ END;
70
+ $$;
71
+ CREATE TRIGGER remember_knowledge_confirmation_receipts_immutable
72
+ BEFORE UPDATE OR DELETE ON "remember_knowledge_confirmation_receipts"
73
+ FOR EACH ROW EXECUTE FUNCTION reject_remember_knowledge_confirmation_receipt_mutation();
74
+
75
+ CREATE OR REPLACE FUNCTION confirm_remember_knowledge_claim(
76
+ p_account_id uuid,
77
+ p_workspace_id uuid,
78
+ p_session_id uuid,
79
+ p_turn_id uuid,
80
+ p_execution_generation integer,
81
+ p_operation_id uuid,
82
+ p_claim_id uuid,
83
+ p_human_input_request_id uuid
84
+ ) RETURNS SETOF remember_knowledge_confirmation_receipts
85
+ LANGUAGE plpgsql SECURITY DEFINER AS $$
86
+ DECLARE
87
+ caller_subject_id text := nullif(current_setting('opengeni.subject_id', true), '');
88
+ result_row remember_knowledge_confirmation_receipts%ROWTYPE;
89
+ claim_row knowledge_claims%ROWTYPE;
90
+ evidence_row knowledge_claim_evidence%ROWTYPE;
91
+ task_note_row task_notes%ROWTYPE;
92
+ review_row knowledge_claim_reviews%ROWTYPE;
93
+ approval_row knowledge_claim_reviews%ROWTYPE;
94
+ human_input_row session_human_input_requests%ROWTYPE;
95
+ input_hash_value text;
96
+ service_actor text;
97
+ human_question_id text;
98
+ human_question_prompt text := 'Save this as workspace knowledge for everyone in this workspace?';
99
+ human_question_help text;
100
+ human_question_options jsonb := jsonb_build_array(
101
+ jsonb_build_object('id', 'save', 'label', 'Save'),
102
+ jsonb_build_object('id', 'skip', 'label', 'Don''t save')
103
+ );
104
+ conflict_count integer;
105
+ BEGIN
106
+ IF p_account_id IS NULL OR p_workspace_id IS NULL OR p_session_id IS NULL OR p_turn_id IS NULL
107
+ OR p_execution_generation IS NULL OR p_execution_generation <= 0
108
+ OR p_operation_id IS NULL OR p_claim_id IS NULL OR p_human_input_request_id IS NULL
109
+ OR caller_subject_id IS NULL OR length(btrim(caller_subject_id)) NOT BETWEEN 1 AND 1024
110
+ OR p_account_id IS DISTINCT FROM opengeni_private.current_account_id()
111
+ OR p_workspace_id IS DISTINCT FROM opengeni_private.current_workspace_id()
112
+ THEN
113
+ RAISE EXCEPTION 'remember Knowledge confirmation requires exact tenant authority'
114
+ USING ERRCODE = '42501';
115
+ END IF;
116
+ input_hash_value := encode(sha256(convert_to(jsonb_build_array(
117
+ 'remember-knowledge-confirmation', 1, p_account_id, p_workspace_id, p_session_id,
118
+ p_turn_id, p_execution_generation, p_operation_id, p_claim_id, p_human_input_request_id
119
+ )::text, 'UTF8')), 'hex');
120
+ service_actor := 'service:governed-learning-activation:' || input_hash_value;
121
+
122
+ PERFORM 1 FROM workspaces workspace
123
+ WHERE workspace.account_id = p_account_id AND workspace.id = p_workspace_id FOR UPDATE;
124
+ IF NOT FOUND THEN
125
+ RAISE EXCEPTION 'remember Knowledge workspace is unavailable' USING ERRCODE = '42501';
126
+ END IF;
127
+ SELECT * INTO result_row FROM remember_knowledge_confirmation_receipts receipt
128
+ WHERE receipt.workspace_id = p_workspace_id AND receipt.operation_id = p_operation_id FOR SHARE;
129
+ IF FOUND THEN
130
+ IF result_row.account_id <> p_account_id OR result_row.input_hash <> input_hash_value
131
+ OR result_row.initiating_human_subject_id <> caller_subject_id
132
+ THEN
133
+ RAISE EXCEPTION 'remember Knowledge confirmation conflicts with immutable receipt'
134
+ USING ERRCODE = '23505';
135
+ END IF;
136
+ RETURN NEXT result_row;
137
+ RETURN;
138
+ END IF;
139
+ IF EXISTS (SELECT 1 FROM remember_knowledge_confirmation_receipts receipt WHERE receipt.claim_id = p_claim_id) THEN
140
+ RAISE EXCEPTION 'remember Knowledge claim was already confirmed by another operation'
141
+ USING ERRCODE = '23505';
142
+ END IF;
143
+
144
+ -- The live turn must belong to the caller (the initiating human) and hold a
145
+ -- running attempt of the given execution generation without a pending
146
+ -- interruption; the human-input pause resumes on a later attempt.
147
+ PERFORM 1 FROM sessions session
148
+ WHERE session.account_id = p_account_id AND session.workspace_id = p_workspace_id
149
+ AND session.id = p_session_id AND session.active_turn_id = p_turn_id
150
+ AND session_reference_visible(session.account_id, session.workspace_id, session.id)
151
+ FOR SHARE;
152
+ IF NOT FOUND THEN
153
+ RAISE EXCEPTION 'remember Knowledge session is unavailable' USING ERRCODE = '42501';
154
+ END IF;
155
+ PERFORM 1 FROM session_turns turn
156
+ JOIN session_turn_attempts attempt
157
+ ON attempt.account_id = turn.account_id AND attempt.workspace_id = turn.workspace_id
158
+ AND attempt.session_id = turn.session_id AND attempt.turn_id = turn.id
159
+ AND attempt.id = turn.active_attempt_id
160
+ WHERE turn.account_id = p_account_id AND turn.workspace_id = p_workspace_id
161
+ AND turn.session_id = p_session_id AND turn.id = p_turn_id
162
+ AND turn.execution_generation = p_execution_generation
163
+ AND turn.status IN ('running', 'requires_action', 'recovering', 'waiting_capacity')
164
+ AND coalesce(turn.initiating_human_subject_id,
165
+ CASE WHEN turn.initiator_kind = 'subject' THEN turn.initiator_subject_id END
166
+ ) = caller_subject_id
167
+ AND attempt.execution_generation = p_execution_generation
168
+ AND attempt.state IN ('claimed', 'running')
169
+ AND NOT EXISTS (
170
+ SELECT 1 FROM session_attempt_interruptions interruption
171
+ WHERE interruption.workspace_id = p_workspace_id
172
+ AND interruption.attempt_id = attempt.id
173
+ AND interruption.state IN ('pending', 'delivered', 'acknowledged')
174
+ )
175
+ FOR SHARE OF attempt;
176
+ IF NOT FOUND THEN
177
+ RAISE EXCEPTION 'remember Knowledge turn is unavailable' USING ERRCODE = '42501';
178
+ END IF;
179
+
180
+ SELECT * INTO claim_row FROM knowledge_claims claim
181
+ WHERE claim.id = p_claim_id AND claim.account_id = p_account_id
182
+ AND claim.scope_kind = 'workspace' AND claim.scope_workspace_id = p_workspace_id
183
+ AND claim.scope_subject_id IS NULL
184
+ AND claim.initiating_human_subject_id = caller_subject_id
185
+ AND claim.effective_at <= transaction_timestamp()
186
+ AND (claim.expires_at IS NULL OR claim.expires_at > transaction_timestamp())
187
+ FOR UPDATE;
188
+ IF NOT FOUND THEN
189
+ RAISE EXCEPTION 'remember Knowledge claim is unavailable' USING ERRCODE = '42501';
190
+ END IF;
191
+ SELECT * INTO evidence_row FROM knowledge_claim_evidence evidence
192
+ WHERE evidence.account_id = p_account_id AND evidence.scope_kind = 'workspace'
193
+ AND evidence.scope_workspace_id = p_workspace_id AND evidence.scope_subject_id IS NULL
194
+ AND evidence.claim_id = p_claim_id AND evidence.polarity = 'supports'
195
+ AND evidence.task_note_id IS NOT NULL
196
+ AND evidence.initiating_human_subject_id = caller_subject_id
197
+ ORDER BY evidence.created_at ASC LIMIT 1 FOR SHARE;
198
+ IF NOT FOUND THEN
199
+ RAISE EXCEPTION 'remember Knowledge confirmation requires exact Task-note evidence'
200
+ USING ERRCODE = '42501';
201
+ END IF;
202
+ SELECT count(*) INTO conflict_count FROM knowledge_claim_evidence contradiction
203
+ WHERE contradiction.account_id = p_account_id AND contradiction.scope_kind = 'workspace'
204
+ AND contradiction.scope_workspace_id = p_workspace_id AND contradiction.scope_subject_id IS NULL
205
+ AND contradiction.claim_id = p_claim_id AND contradiction.polarity = 'contradicts';
206
+ IF conflict_count <> 0 THEN
207
+ RAISE EXCEPTION 'remember Knowledge evidence now conflicts' USING ERRCODE = '23514';
208
+ END IF;
209
+ SELECT * INTO task_note_row FROM task_notes note
210
+ WHERE note.id = evidence_row.task_note_id AND note.account_id = p_account_id
211
+ AND note.workspace_id = p_workspace_id
212
+ AND note.root_session_id = evidence_row.task_note_root_session_id
213
+ AND note.version = evidence_row.task_note_version
214
+ AND note.text_hash = evidence_row.content_hash
215
+ AND note.status = 'active' AND note.expires_at > transaction_timestamp()
216
+ AND session_reference_visible(note.account_id, note.workspace_id, note.root_session_id)
217
+ FOR SHARE;
218
+ IF NOT FOUND THEN
219
+ RAISE EXCEPTION 'remember Knowledge Task-note authority was revoked' USING ERRCODE = '42501';
220
+ END IF;
221
+ SELECT * INTO review_row FROM knowledge_claim_reviews review
222
+ WHERE review.account_id = p_account_id AND review.claim_id = p_claim_id
223
+ ORDER BY review.review_revision DESC LIMIT 1 FOR SHARE;
224
+ IF NOT FOUND OR review_row.state <> 'proposed' THEN
225
+ RAISE EXCEPTION 'remember Knowledge claim is not awaiting confirmation' USING ERRCODE = '42501';
226
+ END IF;
227
+
228
+ -- The exact human must have answered the canonical bound question with
229
+ -- `save` on this session/turn generation. The question is reconstructed
230
+ -- here from the note text, so an agent cannot obtain confirmation through a
231
+ -- misleading prompt.
232
+ human_question_id := 'remember:' || p_claim_id::text;
233
+ human_question_help := left(task_note_row.text, 2000);
234
+ SELECT * INTO human_input_row FROM session_human_input_requests request
235
+ WHERE request.id = p_human_input_request_id
236
+ AND request.account_id = p_account_id AND request.workspace_id = p_workspace_id
237
+ AND request.session_id = p_session_id AND request.turn_id = p_turn_id
238
+ AND request.turn_generation = p_execution_generation
239
+ AND request.status = 'answered'
240
+ AND request.responded_by = caller_subject_id
241
+ AND request.response->>'outcome' = 'answered'
242
+ AND EXISTS (
243
+ SELECT 1 FROM jsonb_array_elements(request.questions) question(value)
244
+ WHERE question.value->>'id' = human_question_id
245
+ AND question.value->>'kind' = 'single_select'
246
+ AND question.value->>'prompt' = human_question_prompt
247
+ AND question.value->>'helpText' = human_question_help
248
+ AND question.value->'options' = human_question_options
249
+ AND coalesce((question.value->>'allowOther')::boolean, false) = false
250
+ )
251
+ AND EXISTS (
252
+ SELECT 1 FROM jsonb_array_elements(request.response->'answers') answer(value)
253
+ WHERE answer.value->>'questionId' = human_question_id
254
+ AND answer.value->'values' = to_jsonb(ARRAY['save'])
255
+ )
256
+ FOR SHARE;
257
+ IF NOT FOUND THEN
258
+ RAISE EXCEPTION 'human confirmation for this Knowledge claim is unavailable'
259
+ USING ERRCODE = '42501';
260
+ END IF;
261
+
262
+ SELECT * INTO approval_row FROM governed_learning_apply_knowledge_review(
263
+ p_account_id, p_workspace_id,
264
+ opengeni_private.governed_learning_derived_uuid(p_operation_id, 'remember-knowledge-approval'),
265
+ p_claim_id, review_row.id, review_row.review_revision, 'approved',
266
+ service_actor, caller_subject_id
267
+ );
268
+
269
+ INSERT INTO remember_knowledge_confirmation_receipts (
270
+ account_id, workspace_id, operation_id, input_hash, session_id, turn_id,
271
+ execution_generation, initiating_human_subject_id, service_actor_subject_id,
272
+ claim_id, evidence_id, task_note_id, task_note_text_hash, human_input_request_id,
273
+ previous_review_id, previous_review_revision, approval_review_id, approval_review_revision
274
+ ) VALUES (
275
+ p_account_id, p_workspace_id, p_operation_id, input_hash_value, p_session_id, p_turn_id,
276
+ p_execution_generation, caller_subject_id, service_actor,
277
+ p_claim_id, evidence_row.id, task_note_row.id, task_note_row.text_hash, p_human_input_request_id,
278
+ review_row.id, review_row.review_revision, approval_row.id, approval_row.review_revision
279
+ ) RETURNING * INTO result_row;
280
+ RETURN NEXT result_row;
281
+ END;
282
+ $$;
283
+ REVOKE ALL ON FUNCTION confirm_remember_knowledge_claim(uuid, uuid, uuid, uuid, integer, uuid, uuid, uuid) FROM PUBLIC;
284
+ REVOKE ALL ON TABLE "remember_knowledge_confirmation_receipts" FROM PUBLIC;
285
+
286
+ DO $remember_knowledge_confirmation_hardening$
287
+ DECLARE
288
+ target_schema text := current_schema();
289
+ runtime_role text := nullif(current_setting('opengeni.runtime_role', true), '');
290
+ BEGIN
291
+ IF runtime_role IS NULL AND EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'opengeni_app') THEN
292
+ runtime_role := 'opengeni_app';
293
+ END IF;
294
+ EXECUTE format(
295
+ 'ALTER FUNCTION %I.reject_remember_knowledge_confirmation_receipt_mutation() '
296
+ || 'SET search_path = pg_catalog, %I, pg_temp', target_schema, target_schema
297
+ );
298
+ EXECUTE format(
299
+ 'ALTER FUNCTION %I.confirm_remember_knowledge_claim(uuid,uuid,uuid,uuid,integer,uuid,uuid,uuid) '
300
+ || 'SET search_path = pg_catalog, %I, pg_temp', target_schema, target_schema
301
+ );
302
+ IF runtime_role IS NOT NULL THEN
303
+ EXECUTE format('REVOKE ALL ON TABLE %I.remember_knowledge_confirmation_receipts FROM %I', target_schema, runtime_role);
304
+ EXECUTE format(
305
+ 'GRANT EXECUTE ON FUNCTION %I.confirm_remember_knowledge_claim(uuid,uuid,uuid,uuid,integer,uuid,uuid,uuid) TO %I',
306
+ target_schema, runtime_role
307
+ );
308
+ END IF;
309
+ END
310
+ $remember_knowledge_confirmation_hardening$;