@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,303 @@
1
+ -- deployment-mode: rolling
2
+ -- Migration 0302: own sessions created in a managed human's OWN personal
3
+ -- workspace, and stop the write fence from silently minting a NULL owner when
4
+ -- an owner does exist.
5
+ --
6
+ -- THE DEFECT
7
+ -- ----------
8
+ -- 0225's `guard_session_authority_write` resolves a new session's owner from
9
+ -- the creator's active `organization_memberships` row, but gates that
10
+ -- resolution on an `EXISTS (workspace_memberships ...)` row in the session's
11
+ -- workspace. A managed human's personal workspace DELIBERATELY has no
12
+ -- `workspace_memberships` row: 0219's provisioning capability treats one as a
13
+ -- hard error ('managed-human personal workspace already has runtime access',
14
+ -- 42501), and docs/organization-tenancy.md states the owner-only access
15
+ -- projection is an `AccessContext` grant rather than a durable membership row.
16
+ --
17
+ -- The EXISTS can therefore never be satisfied in a personal workspace, the
18
+ -- `SELECT ... INTO` finds nothing, and the session is written with
19
+ -- `owner_organization_membership_id = NULL`. Consequence: a human in the one
20
+ -- workspace where they are by construction the ONLY possible member cannot own
21
+ -- their own sessions, so those sessions can never become `user_private` and can
22
+ -- never carry that human's personal connections or Documents. 0297 already
23
+ -- names this exact population ("A MANAGED HUMAN IN THEIR OWN PERSONAL
24
+ -- WORKSPACE") and repairs it historically; nothing stopped the mint.
25
+ --
26
+ -- THE FIX, AND WHY IT IS NOT AN INFERENCE
27
+ -- ---------------------------------------
28
+ -- Accept `membership.personal_workspace_id = NEW.workspace_id` as an
29
+ -- ALTERNATIVE to the `workspace_memberships` EXISTS. This is exactly the shape
30
+ -- 0258's `ensure_personal_document_authority` already uses for Documents
31
+ -- (`IF member_row.personal_workspace_id IS DISTINCT FROM p_workspace_id THEN`
32
+ -- require the workspace membership), and exactly the convergence 0297's
33
+ -- backfill uses.
34
+ --
35
+ -- Phase D forbids inferring user authority from `created_by`, connection
36
+ -- attribution, a default workspace, a resource name, or current access. This is
37
+ -- none of those: the membership row ITSELF names the workspace in its own
38
+ -- `personal_workspace_id` column, written by the 0219 lifecycle capability. It
39
+ -- is STATED authority read from the authority table, not derived evidence. The
40
+ -- pointer is 1:1 - 0218's unique
41
+ -- `organization_memberships_personal_workspace_idx` on
42
+ -- (account_id, personal_workspace_id) means at most one membership can name a
43
+ -- given workspace, and `organization_memberships_account_subject_idx` means at
44
+ -- most one membership exists per (account, subject). There is no second
45
+ -- candidate to disambiguate.
46
+ --
47
+ -- The ordinary shared-workspace path is UNCHANGED. A human with no
48
+ -- `workspace_memberships` row in an ordinary workspace still resolves to no
49
+ -- owner there, because the new disjunct only fires for the workspace their own
50
+ -- membership row points at.
51
+ --
52
+ -- MAKING THE SILENT MISS LOUD
53
+ -- ---------------------------
54
+ -- The original `SELECT ... INTO` has no `IF NOT FOUND` handling, so "this
55
+ -- session legitimately has no human owner" and "the resolver failed to project
56
+ -- an owner that exists" are byte-identical outcomes. That is precisely why the
57
+ -- defect above stayed invisible for seven migrations.
58
+ --
59
+ -- Genuinely-ownerless cases are preserved verbatim and must stay NULL:
60
+ -- * `created_by_kind <> 'subject'` (service initiators, the scheduler, the
61
+ -- pre-0096 `unattributed-legacy` default) never enters this branch at all;
62
+ -- * `api_key:*` / `configured:*` subjects, which 0219 and 0263 gate to
63
+ -- `user:%` and which can therefore never acquire an organization anchor;
64
+ -- * a `user:` subject with no ACTIVE organization membership;
65
+ -- * a `user:` subject with an active membership but no stated authority over
66
+ -- an ordinary shared workspace.
67
+ --
68
+ -- What is now loud instead: a `subject`-kind creator who HAS an active
69
+ -- organization membership, inserting into a workspace that is the
70
+ -- `personal_workspace_id` of an active membership, that still resolved to no
71
+ -- owner. A personal workspace has exactly one possible human owner by
72
+ -- construction (the 1:1 unique index above) and deliberately carries no
73
+ -- `workspace_memberships` row, so an unowned subject-created session there is a
74
+ -- resolver defect, not a legitimate `workspace_shared` session. It raises
75
+ -- SQLSTATE 55000 rather than writing NULL.
76
+ --
77
+ -- This cannot fire on the repaired path: when the creator IS the personal
78
+ -- workspace's member the new disjunct resolves them. It fires only when the two
79
+ -- durable facts disagree - a subject creating a session inside somebody else's
80
+ -- personal workspace, which 0219's access model makes unreachable - or if a
81
+ -- future change breaks the resolver again. A SUSPENDED or REVOKED member is
82
+ -- excluded from both the resolver and the classifier by the same
83
+ -- `status = 'active'` predicate, so their personal-workspace sessions stay
84
+ -- ownerless without raising, exactly as before.
85
+ --
86
+ -- ROLLING SAFETY
87
+ -- --------------
88
+ -- This migration replaces one function body and nothing else: no column, index,
89
+ -- constraint, policy, grant, or trigger definition changes. Old API and worker
90
+ -- images keep running against it unchanged - they never name the owner columns
91
+ -- on INSERT, which is what makes the derivation branch fire in the first place.
92
+ -- The new behaviour is strictly a widening plus an assertion over a population
93
+ -- that 0219 makes unreachable. There is no data rewrite here; historical rows
94
+ -- remain the shipped `bun run db:backfill-session-ownership` seam's job (0297).
95
+
96
+ SET LOCAL lock_timeout = '5s';
97
+ SET LOCAL statement_timeout = '5min';
98
+
99
+ DO $session_personal_workspace_ownership$
100
+ DECLARE
101
+ data_schema text := current_schema();
102
+ BEGIN
103
+ EXECUTE format($ddl$
104
+ CREATE OR REPLACE FUNCTION %1$I.guard_session_authority_write()
105
+ RETURNS trigger
106
+ LANGUAGE plpgsql
107
+ SECURITY DEFINER
108
+ SET search_path = %1$I, pg_catalog
109
+ AS $body$
110
+ DECLARE
111
+ resolved_owner_id uuid;
112
+ resolved_owner_subject_id text;
113
+ creator_has_active_membership boolean;
114
+ owner_provenance_supplied boolean :=
115
+ NEW.owner_organization_membership_id IS NOT NULL
116
+ OR NEW.owner_subject_id IS NOT NULL;
117
+ previous_lifecycle_marker text := pg_catalog.current_setting(
118
+ 'opengeni.organization_tenancy_lifecycle', true
119
+ );
120
+ BEGIN
121
+ IF TG_OP = 'INSERT'
122
+ AND NEW.owner_organization_membership_id IS NULL
123
+ AND NEW.owner_subject_id IS NULL
124
+ THEN
125
+ IF NEW.parent_session_id IS NOT NULL THEN
126
+ SELECT parent.owner_organization_membership_id, parent.owner_subject_id
127
+ INTO resolved_owner_id, resolved_owner_subject_id
128
+ FROM sessions parent
129
+ WHERE parent.account_id = NEW.account_id
130
+ AND parent.workspace_id = NEW.workspace_id
131
+ AND parent.id = NEW.parent_session_id;
132
+ ELSIF NEW.created_by_kind = 'subject'
133
+ AND NEW.created_by_subject_id IS NOT NULL
134
+ THEN
135
+ PERFORM pg_catalog.set_config(
136
+ 'opengeni.organization_tenancy_lifecycle',
137
+ 'session_visibility_activation',
138
+ true
139
+ );
140
+ SELECT membership.id, membership.subject_id
141
+ INTO resolved_owner_id, resolved_owner_subject_id
142
+ FROM organization_memberships membership
143
+ WHERE membership.account_id = NEW.account_id
144
+ AND membership.subject_id = NEW.created_by_subject_id
145
+ AND membership.status = 'active'
146
+ AND (
147
+ -- Stated authority, read from the authority row itself: a managed
148
+ -- human's personal workspace has no workspace_memberships row by
149
+ -- design (0219), so the membership's own personal-workspace
150
+ -- pointer is the authority for exactly that one workspace. Same
151
+ -- shape as 0258's personal Document authority.
152
+ --
153
+ -- Restricted to `user:%%` because 0219 and 0263 gate the ENTIRE
154
+ -- managed-human lifecycle - provisioning, invitation, acceptance
155
+ -- - to that prefix. A personal-workspace pointer on an
156
+ -- `api_key:`/`configured:` membership is not a shape any
157
+ -- lifecycle can produce, and 0297's classifier calls that lane
158
+ -- (`external_lane_owns_row`) permanently unrepairable. The write
159
+ -- path must not attribute what the classifier refuses.
160
+ (
161
+ NEW.created_by_subject_id LIKE 'user:%%'
162
+ AND membership.personal_workspace_id = NEW.workspace_id
163
+ )
164
+ OR EXISTS (
165
+ SELECT 1
166
+ FROM workspace_memberships workspace_membership
167
+ WHERE workspace_membership.account_id = NEW.account_id
168
+ AND workspace_membership.workspace_id = NEW.workspace_id
169
+ AND workspace_membership.subject_id = membership.subject_id
170
+ )
171
+ );
172
+ IF NOT FOUND THEN
173
+ -- Classify the miss instead of writing an indistinguishable NULL.
174
+ SELECT EXISTS (
175
+ SELECT 1
176
+ FROM organization_memberships creator_membership
177
+ WHERE creator_membership.account_id = NEW.account_id
178
+ AND creator_membership.subject_id = NEW.created_by_subject_id
179
+ AND creator_membership.status = 'active'
180
+ AND NEW.created_by_subject_id LIKE 'user:%%'
181
+ ) INTO creator_has_active_membership;
182
+ IF creator_has_active_membership
183
+ AND EXISTS (
184
+ SELECT 1
185
+ FROM organization_memberships personal_owner
186
+ WHERE personal_owner.account_id = NEW.account_id
187
+ AND personal_owner.personal_workspace_id = NEW.workspace_id
188
+ AND personal_owner.status = 'active'
189
+ AND personal_owner.subject_id LIKE 'user:%%'
190
+ )
191
+ THEN
192
+ RAISE EXCEPTION
193
+ 'session owner authority is unresolved in a personal workspace'
194
+ USING ERRCODE = '55000';
195
+ END IF;
196
+ -- Otherwise genuinely ownerless: no active organization membership,
197
+ -- or no stated authority over an ordinary shared workspace.
198
+ END IF;
199
+ END IF;
200
+ NEW.owner_organization_membership_id := resolved_owner_id;
201
+ NEW.owner_subject_id := resolved_owner_subject_id;
202
+ PERFORM pg_catalog.set_config(
203
+ 'opengeni.organization_tenancy_lifecycle',
204
+ CASE WHEN previous_lifecycle_marker IS NULL THEN '' ELSE previous_lifecycle_marker END,
205
+ true
206
+ );
207
+ END IF;
208
+
209
+ IF (NEW.owner_organization_membership_id IS NULL)
210
+ <> (NEW.owner_subject_id IS NULL)
211
+ OR (NEW.visibility = 'user_private'
212
+ AND NEW.owner_organization_membership_id IS NULL)
213
+ THEN
214
+ RAISE EXCEPTION 'session authority owner provenance is incomplete'
215
+ USING ERRCODE = '23514';
216
+ END IF;
217
+
218
+ IF TG_OP = 'UPDATE'
219
+ AND (
220
+ NEW.visibility IS DISTINCT FROM OLD.visibility
221
+ OR NEW.owner_organization_membership_id
222
+ IS DISTINCT FROM OLD.owner_organization_membership_id
223
+ OR NEW.owner_subject_id IS DISTINCT FROM OLD.owner_subject_id
224
+ OR NEW.authority_epoch IS DISTINCT FROM OLD.authority_epoch
225
+ OR NEW.forked_from_session_id IS DISTINCT FROM OLD.forked_from_session_id
226
+ OR NEW.forked_from_authority_epoch
227
+ IS DISTINCT FROM OLD.forked_from_authority_epoch
228
+ OR NEW.forked_from_visibility IS DISTINCT FROM OLD.forked_from_visibility
229
+ OR NEW.forked_at IS DISTINCT FROM OLD.forked_at
230
+ OR NEW.forked_by_organization_membership_id
231
+ IS DISTINCT FROM OLD.forked_by_organization_membership_id
232
+ )
233
+ AND NOT EXISTS (
234
+ SELECT 1
235
+ FROM session_visibility_write_capabilities capability
236
+ WHERE capability.backend_pid = pg_catalog.pg_backend_pid()
237
+ AND capability.transaction_id = pg_catalog.pg_current_xact_id()
238
+ AND capability.capability_id = nullif(
239
+ pg_catalog.current_setting(
240
+ 'opengeni.session_visibility_write_capability', true
241
+ ),
242
+ ''
243
+ )::uuid
244
+ )
245
+ THEN
246
+ RAISE EXCEPTION 'session authority changes require the lifecycle capability'
247
+ USING ERRCODE = '42501';
248
+ END IF;
249
+
250
+ IF TG_OP = 'INSERT'
251
+ AND (
252
+ NEW.visibility <> 'workspace_shared'
253
+ OR NEW.authority_epoch <> 1
254
+ OR NEW.forked_from_session_id IS NOT NULL
255
+ OR NEW.forked_from_authority_epoch IS NOT NULL
256
+ OR NEW.forked_from_visibility IS NOT NULL
257
+ OR NEW.forked_at IS NOT NULL
258
+ OR NEW.forked_by_organization_membership_id IS NOT NULL
259
+ OR owner_provenance_supplied
260
+ )
261
+ AND NOT EXISTS (
262
+ SELECT 1
263
+ FROM session_visibility_write_capabilities capability
264
+ WHERE capability.backend_pid = pg_catalog.pg_backend_pid()
265
+ AND capability.transaction_id = pg_catalog.pg_current_xact_id()
266
+ AND capability.capability_id = nullif(
267
+ pg_catalog.current_setting(
268
+ 'opengeni.session_visibility_write_capability', true
269
+ ),
270
+ ''
271
+ )::uuid
272
+ )
273
+ THEN
274
+ RAISE EXCEPTION 'non-default session authority requires the lifecycle capability'
275
+ USING ERRCODE = '42501';
276
+ END IF;
277
+ RETURN NEW;
278
+ EXCEPTION WHEN OTHERS THEN
279
+ PERFORM pg_catalog.set_config(
280
+ 'opengeni.organization_tenancy_lifecycle',
281
+ CASE WHEN previous_lifecycle_marker IS NULL THEN '' ELSE previous_lifecycle_marker END,
282
+ true
283
+ );
284
+ RAISE;
285
+ END;
286
+ $body$;
287
+ $ddl$, data_schema);
288
+
289
+ EXECUTE format(
290
+ 'COMMENT ON FUNCTION %I.guard_session_authority_write() IS %L',
291
+ data_schema,
292
+ 'Session authority write fence (0225, repaired by 0302). On INSERT it '
293
+ || 'derives the owner pair from the parent session, or from the '
294
+ || 'creator''s active organization membership when that membership '
295
+ || 'states authority over the session workspace - either an explicit '
296
+ || 'workspace_memberships row or the membership''s own '
297
+ || 'personal_workspace_id pointer, which is the only authority a managed '
298
+ || 'human''s membershipless personal workspace has. A subject-created '
299
+ || 'session that resolves to no owner inside an active membership''s '
300
+ || 'personal workspace raises 55000 instead of silently writing NULL.'
301
+ );
302
+ END
303
+ $session_personal_workspace_ownership$;