@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,391 @@
1
+ -- deployment-mode: rolling
2
+ SET lock_timeout = '5s';
3
+ SET statement_timeout = '10min';
4
+
5
+ -- Widen the task-note expiry ceiling from 30 to 90 days. Task notes are pure
6
+ -- agent-to-agent coordination within one root session tree; a resumed root
7
+ -- session/task tree after a long pause otherwise silently loses all
8
+ -- coordination notes with no warning, since expiry is a read-time filter, not
9
+ -- a deletion. No documented rationale exists for the original 30-day figure.
10
+ -- This is fully backward compatible: every existing row and every caller
11
+ -- still supplying 1-30 days keeps working unchanged.
12
+
13
+ ALTER TABLE "task_notes"
14
+ DROP CONSTRAINT "task_notes_expiry_check";
15
+ ALTER TABLE "task_notes"
16
+ ADD CONSTRAINT "task_notes_expiry_check"
17
+ CHECK ("expires_at" > "created_at" AND "expires_at" <= "created_at" + interval '90 days')
18
+ NOT VALID;
19
+ ALTER TABLE "task_notes"
20
+ VALIDATE CONSTRAINT "task_notes_expiry_check";
21
+
22
+ -- Function bodies below are byte-identical to their prior definitions
23
+ -- (0239_task_tree_notes.sql / 0260_task_note_knowledge_promotion.sql) except
24
+ -- the one numeric bound each enforces in its input-validation check.
25
+
26
+ CREATE OR REPLACE FUNCTION create_task_note_for_attempt(
27
+ p_account_id uuid,
28
+ p_workspace_id uuid,
29
+ p_session_id uuid,
30
+ p_turn_id uuid,
31
+ p_attempt_id uuid,
32
+ p_execution_generation integer,
33
+ p_operation_id uuid,
34
+ p_kind text,
35
+ p_text text,
36
+ p_expires_in_days integer
37
+ ) RETURNS TABLE (
38
+ note_id uuid, root_session_id uuid, kind text, note_text text, status text,
39
+ version integer, expires_at timestamptz, created_at timestamptz,
40
+ updated_at timestamptz, archived_at timestamptz, actor_kind text,
41
+ source_session_id uuid, source_turn_id uuid, replayed boolean
42
+ )
43
+ LANGUAGE plpgsql
44
+ SECURITY DEFINER
45
+ SET search_path FROM CURRENT
46
+ AS $$
47
+ DECLARE
48
+ authority record;
49
+ existing_event task_note_events%ROWTYPE;
50
+ note_row task_notes%ROWTYPE;
51
+ calculated_text_hash text;
52
+ calculated_input_hash text;
53
+ calculated_expires_at timestamptz;
54
+ write_capability_id uuid := gen_random_uuid();
55
+ previous_capability text := current_setting('opengeni.task_note_write_capability', true);
56
+ BEGIN
57
+ SELECT * INTO STRICT authority FROM resolve_task_note_attempt_authority(
58
+ p_account_id, p_workspace_id, p_session_id, p_turn_id,
59
+ p_attempt_id, p_execution_generation
60
+ );
61
+ IF p_operation_id IS NULL
62
+ OR p_kind NOT IN ('finding','decision','blocker','ownership','artifact','handoff')
63
+ OR p_text IS NULL OR octet_length(p_text) NOT BETWEEN 1 AND 4096
64
+ OR p_text <> btrim(p_text)
65
+ OR p_expires_in_days IS NULL OR p_expires_in_days NOT BETWEEN 1 AND 90
66
+ THEN
67
+ RAISE EXCEPTION 'task note input is invalid' USING ERRCODE = '22023';
68
+ END IF;
69
+ calculated_expires_at := transaction_timestamp()
70
+ + pg_catalog.make_interval(days => p_expires_in_days);
71
+ calculated_text_hash := encode(sha256(convert_to(p_text, 'UTF8')), 'hex');
72
+ calculated_input_hash := encode(sha256(convert_to(jsonb_build_object(
73
+ 'accountId', p_account_id, 'workspaceId', p_workspace_id,
74
+ 'rootSessionId', authority.root_session_id, 'sessionId', p_session_id,
75
+ 'turnId', p_turn_id, 'attemptId', p_attempt_id,
76
+ 'executionGeneration', p_execution_generation, 'kind', p_kind,
77
+ 'textHash', calculated_text_hash, 'expiresInDays', p_expires_in_days
78
+ )::text, 'UTF8')), 'hex');
79
+
80
+ INSERT INTO task_note_write_capabilities (backend_pid, transaction_id, capability_id)
81
+ VALUES (pg_backend_pid(), pg_current_xact_id(), write_capability_id);
82
+ PERFORM set_config('opengeni.task_note_write_capability', write_capability_id::text, true);
83
+
84
+ SELECT * INTO existing_event FROM task_note_events event
85
+ WHERE event.workspace_id = p_workspace_id AND event.operation_id = p_operation_id
86
+ FOR SHARE;
87
+ IF FOUND THEN
88
+ IF existing_event.event_type <> 'created'
89
+ OR existing_event.input_hash <> calculated_input_hash
90
+ OR existing_event.root_session_id <> authority.root_session_id
91
+ OR existing_event.actor_session_id <> p_session_id
92
+ OR existing_event.actor_turn_id <> p_turn_id
93
+ OR existing_event.actor_attempt_id <> p_attempt_id
94
+ OR existing_event.actor_execution_generation <> p_execution_generation
95
+ THEN
96
+ RAISE EXCEPTION 'task note operation conflicts with another input or attempt'
97
+ USING ERRCODE = '23505';
98
+ END IF;
99
+ SELECT * INTO STRICT note_row FROM task_notes note
100
+ WHERE note.workspace_id = p_workspace_id AND note.id = existing_event.note_id;
101
+ replayed := true;
102
+ ELSE
103
+ IF (SELECT count(*) FROM task_notes note
104
+ WHERE note.workspace_id = p_workspace_id
105
+ AND note.root_session_id = authority.root_session_id
106
+ AND note.status = 'active' AND note.expires_at > transaction_timestamp()) >= 500
107
+ THEN
108
+ RAISE EXCEPTION 'task note active-record limit reached' USING ERRCODE = '54000';
109
+ END IF;
110
+ INSERT INTO task_notes (
111
+ account_id, workspace_id, root_session_id, kind, text, text_hash,
112
+ expires_at, create_operation_id, create_input_hash,
113
+ created_by_actor_kind, created_by_actor_subject_id,
114
+ created_by_initiating_human_subject_id, created_by_session_id,
115
+ created_by_turn_id, created_by_attempt_id, created_by_execution_generation
116
+ ) VALUES (
117
+ p_account_id, p_workspace_id, authority.root_session_id, p_kind, p_text,
118
+ calculated_text_hash, calculated_expires_at, p_operation_id, calculated_input_hash,
119
+ authority.actor_kind, authority.actor_subject_id,
120
+ authority.initiating_human_subject_id, p_session_id, p_turn_id,
121
+ p_attempt_id, p_execution_generation
122
+ ) RETURNING * INTO note_row;
123
+ INSERT INTO task_note_events (
124
+ account_id, workspace_id, root_session_id, note_id, event_type,
125
+ note_version, operation_id, input_hash, text_hash, actor_kind,
126
+ actor_subject_id, initiating_human_subject_id, actor_session_id,
127
+ actor_turn_id, actor_attempt_id, actor_execution_generation
128
+ ) VALUES (
129
+ p_account_id, p_workspace_id, authority.root_session_id, note_row.id,
130
+ 'created', 1, p_operation_id, calculated_input_hash,
131
+ calculated_text_hash, authority.actor_kind, authority.actor_subject_id,
132
+ authority.initiating_human_subject_id, p_session_id, p_turn_id,
133
+ p_attempt_id, p_execution_generation
134
+ );
135
+ replayed := false;
136
+ END IF;
137
+
138
+ note_id := note_row.id; root_session_id := note_row.root_session_id;
139
+ kind := note_row.kind; note_text := note_row.text; status := note_row.status;
140
+ version := note_row.version; expires_at := note_row.expires_at;
141
+ created_at := note_row.created_at; updated_at := note_row.updated_at;
142
+ archived_at := note_row.archived_at; actor_kind := note_row.created_by_actor_kind;
143
+ source_session_id := note_row.created_by_session_id;
144
+ source_turn_id := note_row.created_by_turn_id;
145
+ DELETE FROM task_note_write_capabilities capability
146
+ WHERE capability.backend_pid = pg_backend_pid()
147
+ AND capability.transaction_id = pg_current_xact_id()
148
+ AND capability.capability_id = write_capability_id;
149
+ PERFORM set_config('opengeni.task_note_write_capability', coalesce(previous_capability, ''), true);
150
+ RETURN NEXT;
151
+ EXCEPTION WHEN OTHERS THEN
152
+ PERFORM set_config('opengeni.task_note_write_capability', coalesce(previous_capability, ''), true);
153
+ RAISE;
154
+ END;
155
+ $$;
156
+
157
+ CREATE OR REPLACE FUNCTION replace_task_note_for_attempt(
158
+ p_account_id uuid,
159
+ p_workspace_id uuid,
160
+ p_session_id uuid,
161
+ p_turn_id uuid,
162
+ p_attempt_id uuid,
163
+ p_execution_generation integer,
164
+ p_operation_id uuid,
165
+ p_archive_operation_id uuid,
166
+ p_create_operation_id uuid,
167
+ p_replaced_note_id uuid,
168
+ p_expected_replaced_version integer,
169
+ p_replacement_kind text,
170
+ p_replacement_text text,
171
+ p_replacement_expires_in_days integer,
172
+ p_reason text
173
+ ) RETURNS TABLE (
174
+ operation_id uuid,
175
+ input_hash text,
176
+ replaced_note_id uuid,
177
+ replaced_note_version integer,
178
+ replacement_note_id uuid,
179
+ root_session_id uuid,
180
+ replacement_kind text,
181
+ replacement_text text,
182
+ replacement_status text,
183
+ replacement_version integer,
184
+ replacement_expires_at timestamptz,
185
+ replacement_created_at timestamptz,
186
+ replacement_updated_at timestamptz,
187
+ replacement_archived_at timestamptz,
188
+ replacement_actor_kind text,
189
+ replacement_source_session_id uuid,
190
+ replacement_source_turn_id uuid,
191
+ replayed boolean
192
+ )
193
+ LANGUAGE plpgsql
194
+ SECURITY DEFINER
195
+ SET search_path FROM CURRENT
196
+ AS $$
197
+ DECLARE
198
+ authority record;
199
+ receipt_row task_note_replacement_receipts%ROWTYPE;
200
+ replaced_row task_notes%ROWTYPE;
201
+ replacement_row task_notes%ROWTYPE;
202
+ archived_result record;
203
+ created_result record;
204
+ calculated_replacement_text_hash text;
205
+ calculated_input_hash text;
206
+ BEGIN
207
+ SELECT * INTO STRICT authority FROM resolve_task_note_attempt_authority(
208
+ p_account_id, p_workspace_id, p_session_id, p_turn_id,
209
+ p_attempt_id, p_execution_generation
210
+ );
211
+ IF p_operation_id IS NULL
212
+ OR p_archive_operation_id IS NULL
213
+ OR p_create_operation_id IS NULL
214
+ OR p_operation_id = p_archive_operation_id
215
+ OR p_operation_id = p_create_operation_id
216
+ OR p_archive_operation_id = p_create_operation_id
217
+ OR p_replaced_note_id IS NULL
218
+ OR p_expected_replaced_version IS DISTINCT FROM 1
219
+ OR p_replacement_kind NOT IN ('finding','decision','blocker','ownership','artifact','handoff')
220
+ OR p_replacement_text IS NULL
221
+ OR octet_length(p_replacement_text) NOT BETWEEN 1 AND 4096
222
+ OR p_replacement_text <> btrim(p_replacement_text)
223
+ OR p_replacement_expires_in_days IS NULL
224
+ OR p_replacement_expires_in_days NOT BETWEEN 1 AND 90
225
+ OR p_reason IS NULL
226
+ OR octet_length(p_reason) NOT BETWEEN 1 AND 2048
227
+ OR p_reason <> btrim(p_reason)
228
+ THEN
229
+ RAISE EXCEPTION 'Task-note replacement input is invalid' USING ERRCODE = '22023';
230
+ END IF;
231
+
232
+ calculated_replacement_text_hash := encode(
233
+ sha256(convert_to(p_replacement_text, 'UTF8')), 'hex'
234
+ );
235
+ calculated_input_hash := encode(sha256(convert_to(jsonb_build_object(
236
+ 'accountId', p_account_id,
237
+ 'workspaceId', p_workspace_id,
238
+ 'rootSessionId', authority.root_session_id,
239
+ 'sessionId', p_session_id,
240
+ 'turnId', p_turn_id,
241
+ 'attemptId', p_attempt_id,
242
+ 'executionGeneration', p_execution_generation,
243
+ 'operationId', p_operation_id,
244
+ 'archiveOperationId', p_archive_operation_id,
245
+ 'createOperationId', p_create_operation_id,
246
+ 'replacedNoteId', p_replaced_note_id,
247
+ 'expectedReplacedVersion', p_expected_replaced_version,
248
+ 'replacementKind', p_replacement_kind,
249
+ 'replacementTextHash', calculated_replacement_text_hash,
250
+ 'replacementExpiresInDays', p_replacement_expires_in_days,
251
+ 'reason', p_reason
252
+ )::text, 'UTF8')), 'hex');
253
+
254
+ SELECT receipt.* INTO receipt_row
255
+ FROM task_note_replacement_receipts receipt
256
+ WHERE receipt.workspace_id = p_workspace_id
257
+ AND receipt.operation_id = p_operation_id
258
+ FOR SHARE;
259
+ IF FOUND THEN
260
+ IF receipt_row.account_id IS DISTINCT FROM p_account_id
261
+ OR receipt_row.root_session_id IS DISTINCT FROM authority.root_session_id
262
+ OR receipt_row.input_hash IS DISTINCT FROM calculated_input_hash
263
+ OR receipt_row.replaced_note_id IS DISTINCT FROM p_replaced_note_id
264
+ OR receipt_row.archive_operation_id IS DISTINCT FROM p_archive_operation_id
265
+ OR receipt_row.create_operation_id IS DISTINCT FROM p_create_operation_id
266
+ OR receipt_row.actor_session_id IS DISTINCT FROM p_session_id
267
+ OR receipt_row.actor_turn_id IS DISTINCT FROM p_turn_id
268
+ OR receipt_row.actor_attempt_id IS DISTINCT FROM p_attempt_id
269
+ OR receipt_row.actor_execution_generation IS DISTINCT FROM p_execution_generation
270
+ OR receipt_row.actor_kind IS DISTINCT FROM authority.actor_kind
271
+ OR receipt_row.actor_subject_id IS DISTINCT FROM authority.actor_subject_id
272
+ OR receipt_row.initiating_human_subject_id
273
+ IS DISTINCT FROM authority.initiating_human_subject_id
274
+ THEN
275
+ RAISE EXCEPTION 'Task-note replacement operation conflicts with another input or attempt'
276
+ USING ERRCODE = '23505';
277
+ END IF;
278
+ SELECT note.* INTO STRICT replacement_row
279
+ FROM task_notes note
280
+ WHERE note.workspace_id = p_workspace_id
281
+ AND note.root_session_id = authority.root_session_id
282
+ AND note.id = receipt_row.replacement_note_id;
283
+ replayed := true;
284
+ ELSE
285
+ SELECT note.* INTO replaced_row
286
+ FROM task_notes note
287
+ WHERE note.workspace_id = p_workspace_id
288
+ AND note.root_session_id = authority.root_session_id
289
+ AND note.id = p_replaced_note_id
290
+ FOR UPDATE;
291
+ IF NOT FOUND THEN
292
+ RAISE EXCEPTION 'Task note is unavailable for replacement' USING ERRCODE = 'P0002';
293
+ END IF;
294
+ IF replaced_row.status <> 'active'
295
+ OR replaced_row.version <> p_expected_replaced_version
296
+ OR replaced_row.expires_at <= transaction_timestamp()
297
+ THEN
298
+ RAISE EXCEPTION 'Task-note replacement version or lifecycle conflict'
299
+ USING ERRCODE = '40001';
300
+ END IF;
301
+
302
+ SELECT * INTO STRICT archived_result FROM archive_task_note_for_attempt(
303
+ p_account_id, p_workspace_id, p_session_id, p_turn_id,
304
+ p_attempt_id, p_execution_generation, p_archive_operation_id,
305
+ p_replaced_note_id, p_expected_replaced_version, p_reason
306
+ );
307
+ SELECT * INTO STRICT created_result FROM create_task_note_for_attempt(
308
+ p_account_id, p_workspace_id, p_session_id, p_turn_id,
309
+ p_attempt_id, p_execution_generation, p_create_operation_id,
310
+ p_replacement_kind, p_replacement_text, p_replacement_expires_in_days
311
+ );
312
+ IF archived_result.note_id IS DISTINCT FROM p_replaced_note_id
313
+ OR archived_result.status IS DISTINCT FROM 'archived'
314
+ OR archived_result.version IS DISTINCT FROM 2
315
+ OR created_result.status IS DISTINCT FROM 'active'
316
+ OR created_result.version IS DISTINCT FROM 1
317
+ OR created_result.root_session_id IS DISTINCT FROM authority.root_session_id
318
+ THEN
319
+ RAISE EXCEPTION 'Task-note replacement lifecycle returned an invalid projection'
320
+ USING ERRCODE = '23514';
321
+ END IF;
322
+ SELECT note.* INTO STRICT replacement_row
323
+ FROM task_notes note
324
+ WHERE note.workspace_id = p_workspace_id
325
+ AND note.root_session_id = authority.root_session_id
326
+ AND note.id = created_result.note_id;
327
+
328
+ INSERT INTO task_note_replacement_receipts (
329
+ account_id, workspace_id, root_session_id, operation_id, input_hash,
330
+ replaced_note_id, replaced_note_version, replacement_note_id,
331
+ replacement_note_version, archive_operation_id, create_operation_id,
332
+ actor_kind, actor_subject_id, initiating_human_subject_id,
333
+ actor_session_id, actor_turn_id, actor_attempt_id, actor_execution_generation
334
+ ) VALUES (
335
+ p_account_id, p_workspace_id, authority.root_session_id,
336
+ p_operation_id, calculated_input_hash, p_replaced_note_id, 2,
337
+ replacement_row.id, 1, p_archive_operation_id, p_create_operation_id,
338
+ authority.actor_kind, authority.actor_subject_id,
339
+ authority.initiating_human_subject_id, p_session_id, p_turn_id,
340
+ p_attempt_id, p_execution_generation
341
+ ) RETURNING * INTO STRICT receipt_row;
342
+ replayed := false;
343
+ END IF;
344
+
345
+ operation_id := receipt_row.operation_id;
346
+ input_hash := receipt_row.input_hash;
347
+ replaced_note_id := receipt_row.replaced_note_id;
348
+ replaced_note_version := receipt_row.replaced_note_version;
349
+ replacement_note_id := replacement_row.id;
350
+ root_session_id := replacement_row.root_session_id;
351
+ replacement_kind := replacement_row.kind;
352
+ replacement_text := replacement_row.text;
353
+ replacement_status := replacement_row.status;
354
+ replacement_version := replacement_row.version;
355
+ replacement_expires_at := replacement_row.expires_at;
356
+ replacement_created_at := replacement_row.created_at;
357
+ replacement_updated_at := replacement_row.updated_at;
358
+ replacement_archived_at := replacement_row.archived_at;
359
+ replacement_actor_kind := replacement_row.created_by_actor_kind;
360
+ replacement_source_session_id := replacement_row.created_by_session_id;
361
+ replacement_source_turn_id := replacement_row.created_by_turn_id;
362
+ RETURN NEXT;
363
+ END;
364
+ $$;
365
+
366
+ RESET statement_timeout;
367
+ RESET lock_timeout;
368
+
369
+ DO $task_note_expiry_widen_hardening$
370
+ DECLARE
371
+ target_schema text := current_schema();
372
+ BEGIN
373
+ -- CREATE OR REPLACE FUNCTION drops the previously pinned search_path
374
+ -- (the FROM CURRENT clause re-resolves to the migration runner's
375
+ -- session search_path at DDL time, not the hardened value). Both functions
376
+ -- were originally re-pinned via ALTER FUNCTION in 0239/0260; re-apply the
377
+ -- same pin here.
378
+ EXECUTE format(
379
+ 'ALTER FUNCTION %I.create_task_note_for_attempt('
380
+ || 'uuid,uuid,uuid,uuid,uuid,integer,uuid,text,text,integer) '
381
+ || 'SET search_path = pg_catalog, %I, pg_temp',
382
+ target_schema, target_schema
383
+ );
384
+ EXECUTE format(
385
+ 'ALTER FUNCTION %I.replace_task_note_for_attempt('
386
+ || 'uuid,uuid,uuid,uuid,uuid,integer,uuid,uuid,uuid,uuid,integer,text,text,integer,text) '
387
+ || 'SET search_path = pg_catalog, %I, pg_temp',
388
+ target_schema, target_schema
389
+ );
390
+ END
391
+ $task_note_expiry_widen_hardening$;
@@ -0,0 +1,18 @@
1
+ -- deployment-mode: rolling
2
+ -- Persist the requires_action open suffix on pending tool-call receipts so
3
+ -- resume can pair history without materializing an SDK generatedItems heap.
4
+ ALTER TABLE "session_pending_tool_calls"
5
+ ADD COLUMN "interruption_kind" text,
6
+ ADD COLUMN "tied_reasoning_items" jsonb NOT NULL DEFAULT '[]'::jsonb,
7
+ ADD COLUMN "tied_reasoning_items_codec_version" integer;
8
+
9
+ ALTER TABLE "session_pending_tool_calls"
10
+ ADD CONSTRAINT "session_pending_tool_calls_interruption_kind_chk" CHECK (
11
+ "interruption_kind" IS NULL
12
+ OR "interruption_kind" IN ('human_input', 'approval', 'interaction_intervention')
13
+ );
14
+
15
+ ALTER TABLE "session_pending_tool_calls"
16
+ ADD CONSTRAINT "session_pending_tool_calls_tied_reasoning_items_chk" CHECK (
17
+ jsonb_typeof("tied_reasoning_items") = 'array'
18
+ );
@@ -0,0 +1,64 @@
1
+ -- deployment-mode: rolling
2
+ -- A Chrome profile keeps one stable device id across OpenGeni Agent reinstalls.
3
+ -- Re-enrollment creates a new enrollment row, so let the live enrollment reclaim
4
+ -- that endpoint only after its previous enrollment has been revoked. Active-to-
5
+ -- active reassignment remains forbidden.
6
+
7
+ SET LOCAL lock_timeout = '5s';
8
+ SET LOCAL statement_timeout = '30s';
9
+
10
+ CREATE OR REPLACE FUNCTION opengeni_private.attached_browser_devices_update_guard()
11
+ RETURNS trigger
12
+ LANGUAGE plpgsql
13
+ SET search_path FROM CURRENT
14
+ AS $guard$
15
+ DECLARE
16
+ enrollment_transfer_allowed boolean;
17
+ BEGIN
18
+ IF ROW(
19
+ NEW.id, NEW.account_id, NEW.workspace_id, NEW.created_at
20
+ ) IS DISTINCT FROM ROW(
21
+ OLD.id, OLD.account_id, OLD.workspace_id, OLD.created_at
22
+ ) THEN
23
+ RAISE EXCEPTION 'Attached browser endpoint identity cannot change'
24
+ USING ERRCODE = '23514';
25
+ END IF;
26
+
27
+ IF NEW.enrollment_id IS DISTINCT FROM OLD.enrollment_id THEN
28
+ SELECT
29
+ EXISTS (
30
+ SELECT 1
31
+ FROM enrollments previous_enrollment
32
+ WHERE previous_enrollment.id = OLD.enrollment_id
33
+ AND previous_enrollment.account_id = OLD.account_id
34
+ AND previous_enrollment.workspace_id = OLD.workspace_id
35
+ AND previous_enrollment.status = 'revoked'
36
+ )
37
+ AND EXISTS (
38
+ SELECT 1
39
+ FROM enrollments next_enrollment
40
+ WHERE next_enrollment.id = NEW.enrollment_id
41
+ AND next_enrollment.account_id = NEW.account_id
42
+ AND next_enrollment.workspace_id = NEW.workspace_id
43
+ AND next_enrollment.status = 'active'
44
+ )
45
+ INTO enrollment_transfer_allowed;
46
+
47
+ IF NOT coalesce(enrollment_transfer_allowed, false) THEN
48
+ RAISE EXCEPTION 'Attached browser endpoint enrollment can move only from revoked to active'
49
+ USING ERRCODE = '23514';
50
+ END IF;
51
+ END IF;
52
+
53
+ IF NEW.last_seen_at < OLD.last_seen_at OR NEW.updated_at < OLD.updated_at THEN
54
+ RAISE EXCEPTION 'Attached browser endpoint time cannot move backwards'
55
+ USING ERRCODE = '23514';
56
+ END IF;
57
+ IF NEW.connection_generation = OLD.connection_generation
58
+ AND NEW.inventory_revision < OLD.inventory_revision THEN
59
+ RAISE EXCEPTION 'Attached browser inventory revision cannot move backwards'
60
+ USING ERRCODE = '23514';
61
+ END IF;
62
+ RETURN NEW;
63
+ END
64
+ $guard$;