@opengeni/db 3.6.0 → 3.7.4-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 (92) hide show
  1. package/dist/automations.d.ts +4 -0
  2. package/dist/canonical-human-identities.js +3 -3
  3. package/dist/{chunk-UGDVSQ6U.js → chunk-3ZMN4EXC.js} +2 -2
  4. package/dist/{chunk-744DFC65.js → chunk-6FIVOJ3V.js} +96 -6
  5. package/dist/chunk-6FIVOJ3V.js.map +1 -0
  6. package/dist/{chunk-UJ2EW3QI.js → chunk-DXJ2WY6W.js} +427 -85
  7. package/dist/chunk-DXJ2WY6W.js.map +1 -0
  8. package/dist/{chunk-CDMMSUWJ.js → chunk-JP6IYGYI.js} +3 -3
  9. package/dist/{chunk-Q5YUGQVK.js → chunk-JS3AWDKZ.js} +3 -3
  10. package/dist/{chunk-G3732M3T.js → chunk-LHKB62GC.js} +2 -2
  11. package/dist/{chunk-2NT476HD.js → chunk-QL4AHBYD.js} +2 -2
  12. package/dist/{chunk-IW6O6G7R.js → chunk-VDXHLVDE.js} +2 -2
  13. package/dist/{chunk-WW7AJ5IC.js → chunk-ZTSJPFDH.js} +5 -7
  14. package/dist/chunk-ZTSJPFDH.js.map +1 -0
  15. package/dist/codex-token-resolver.d.ts +12 -1
  16. package/dist/company-profile-agent-admin.d.ts +4 -2
  17. package/dist/company-profile-agent-policy.d.ts +20 -0
  18. package/dist/company-profile-schema.d.ts +573 -0
  19. package/dist/editable-artifact-durable-export.js +2 -2
  20. package/dist/editable-artifacts.js +3 -3
  21. package/dist/index.d.ts +487 -20
  22. package/dist/index.js +9489 -6041
  23. package/dist/index.js.map +1 -1
  24. package/dist/managed-auth-session-sets.js +3 -3
  25. package/dist/managed-human-provisioning.d.ts +3 -3
  26. package/dist/memory-domain.d.ts +5 -3
  27. package/dist/model-catalog.d.ts +153 -0
  28. package/dist/pr-review.d.ts +9 -0
  29. package/dist/provision-roles.js +1 -1
  30. package/dist/runtime-posture.d.ts +7 -7
  31. package/dist/schema.d.ts +1069 -6
  32. package/dist/schema.js +17 -1
  33. package/dist/session-background-commands.js +3 -3
  34. package/dist/session-control.d.ts +75 -5
  35. package/dist/session-queue-commands.d.ts +19 -0
  36. package/dist/session-tenancy.js +3 -3
  37. package/dist/user-resource-authority.d.ts +8 -0
  38. package/dist/video-generation.js +3 -3
  39. package/dist/xai-subscription.d.ts +8 -0
  40. package/drizzle/0369_local_human_personal_authority.sql +350 -0
  41. package/drizzle/0370_workspace_member_management_scope.sql +98 -0
  42. package/drizzle/0371_workspace_member_candidate_inventory.sql +128 -0
  43. package/drizzle/0372_ordered_variable_set_runtime_authority.sql +287 -0
  44. package/drizzle/0373_sandbox_shared_preparation.sql +59 -0
  45. package/drizzle/0374_session_event_cursors.sql +315 -0
  46. package/drizzle/0375_session_recovery_observability.sql +73 -0
  47. package/drizzle/0376_organization_workspace_inventory.sql +88 -0
  48. package/drizzle/0377_scoped_rig_health_projection.sql +80 -0
  49. package/drizzle/0378_scoped_rig_health_audit_timestamp.sql +77 -0
  50. package/drizzle/0379_session_event_raw_lane_activation.sql +518 -0
  51. package/drizzle/0380_autonomous_company_profile_agent_policy.sql +829 -0
  52. package/drizzle/0381_organization_codex_subscription_inheritance.sql +720 -0
  53. package/drizzle/0382_organization_api_key_provenance.sql +91 -0
  54. package/drizzle/0383_codex_cooldown_reconciliation.sql +51 -0
  55. package/drizzle/0384_codex_cooldown_revision_guard_privileges.sql +6 -0
  56. package/drizzle/0385_connected_machine_legacy_tilde_workdirs.sql +25 -0
  57. package/drizzle/0386_local_organization_administration.sql +157 -0
  58. package/drizzle/0387_bound_host_export_session_payloads.sql +165 -0
  59. package/drizzle/0388_sandbox_provider_deadline_interactions.sql +491 -0
  60. package/drizzle/0389_model_catalog_and_gateway_custom_models.sql +241 -0
  61. package/package.json +6 -6
  62. package/src/automations.ts +9 -1
  63. package/src/codex-token-resolver.ts +26 -1
  64. package/src/company-brain-governed-writes.ts +30 -1
  65. package/src/company-profile-agent-admin.ts +68 -1
  66. package/src/company-profile-agent-policy.ts +126 -0
  67. package/src/company-profile-schema.ts +115 -1
  68. package/src/database.ts +3 -5
  69. package/src/index.ts +4473 -570
  70. package/src/insights.ts +21 -7
  71. package/src/managed-human-provisioning.ts +3 -3
  72. package/src/memory-domain.ts +9 -4
  73. package/src/model-catalog.ts +682 -0
  74. package/src/organization-membership-lifecycle.ts +0 -1
  75. package/src/pr-review.ts +19 -0
  76. package/src/provision-roles.ts +83 -4
  77. package/src/runtime-posture.ts +26 -0
  78. package/src/schema.ts +259 -10
  79. package/src/session-control.ts +347 -59
  80. package/src/session-queue-commands.ts +303 -122
  81. package/src/session-tool-call-settlement.ts +34 -7
  82. package/src/user-resource-authority.ts +56 -0
  83. package/src/xai-subscription.ts +66 -14
  84. package/dist/chunk-744DFC65.js.map +0 -1
  85. package/dist/chunk-UJ2EW3QI.js.map +0 -1
  86. package/dist/chunk-WW7AJ5IC.js.map +0 -1
  87. /package/dist/{chunk-UGDVSQ6U.js.map → chunk-3ZMN4EXC.js.map} +0 -0
  88. /package/dist/{chunk-CDMMSUWJ.js.map → chunk-JP6IYGYI.js.map} +0 -0
  89. /package/dist/{chunk-Q5YUGQVK.js.map → chunk-JS3AWDKZ.js.map} +0 -0
  90. /package/dist/{chunk-G3732M3T.js.map → chunk-LHKB62GC.js.map} +0 -0
  91. /package/dist/{chunk-2NT476HD.js.map → chunk-QL4AHBYD.js.map} +0 -0
  92. /package/dist/{chunk-IW6O6G7R.js.map → chunk-VDXHLVDE.js.map} +0 -0
@@ -0,0 +1,350 @@
1
+ -- deployment-mode: rolling
2
+ -- Give the explicit single-user local identity the same private authority
3
+ -- anchor as a managed human. This does not add runtime access to the hidden
4
+ -- personal workspace and does not authorize configured keys or host services.
5
+
6
+ SET LOCAL lock_timeout = '5s';
7
+ SET LOCAL statement_timeout = '10min';
8
+
9
+ DO $local_human_personal_authority$
10
+ DECLARE
11
+ data_schema text := current_schema();
12
+ BEGIN
13
+ EXECUTE format($ddl$
14
+ CREATE OR REPLACE FUNCTION %1$I.ensure_managed_human_personal_workspace(
15
+ p_account_id uuid,
16
+ p_subject_id text,
17
+ p_personal_workspace_id uuid
18
+ )
19
+ RETURNS TABLE (
20
+ organization_membership_id uuid,
21
+ personal_workspace_id uuid
22
+ )
23
+ LANGUAGE plpgsql
24
+ SECURITY DEFINER
25
+ SET search_path = %1$I, pg_catalog
26
+ AS $body$
27
+ DECLARE
28
+ expected_external_id text;
29
+ managed_identity boolean := false;
30
+ local_identity boolean := false;
31
+ membership_row organization_memberships%%ROWTYPE;
32
+ workspace_row workspaces%%ROWTYPE;
33
+ previous_workspace_id text := pg_catalog.current_setting(
34
+ 'opengeni.workspace_id', true
35
+ );
36
+ previous_lifecycle_marker text := pg_catalog.current_setting(
37
+ 'opengeni.organization_tenancy_lifecycle', true
38
+ );
39
+ BEGIN
40
+ IF p_account_id IS NULL
41
+ OR p_subject_id IS NULL
42
+ OR p_personal_workspace_id IS NULL
43
+ OR p_subject_id <> pg_catalog.btrim(p_subject_id)
44
+ OR pg_catalog.length(p_subject_id) NOT BETWEEN 1 AND 1024
45
+ THEN
46
+ RAISE EXCEPTION 'human provisioning requires a valid complete identity'
47
+ USING ERRCODE = '42501';
48
+ END IF;
49
+
50
+ IF p_account_id IS DISTINCT FROM opengeni_private.current_account_id() THEN
51
+ RAISE EXCEPTION 'human provisioning account authority is invalid'
52
+ USING ERRCODE = '42501';
53
+ END IF;
54
+
55
+ IF p_subject_id LIKE 'user:%%' THEN
56
+ expected_external_id := pg_catalog.substr(p_subject_id, 6);
57
+ SELECT EXISTS (
58
+ SELECT 1
59
+ FROM managed_accounts account_row
60
+ WHERE account_row.id = p_account_id
61
+ AND account_row.external_source = 'better-auth:user'
62
+ AND account_row.external_id = expected_external_id
63
+ ) INTO managed_identity;
64
+ END IF;
65
+ SELECT EXISTS (
66
+ SELECT 1
67
+ FROM managed_accounts account_row
68
+ WHERE account_row.id = p_account_id
69
+ AND account_row.external_source = 'opengeni:local'
70
+ AND account_row.external_id = 'default'
71
+ AND p_subject_id = 'dev'
72
+ AND opengeni_private.current_subject_id() = p_subject_id
73
+ ) INTO local_identity;
74
+ IF NOT managed_identity AND NOT local_identity THEN
75
+ RAISE EXCEPTION 'human provisioning account identity is invalid'
76
+ USING ERRCODE = '42501';
77
+ END IF;
78
+
79
+ IF NOT EXISTS (
80
+ SELECT 1
81
+ FROM workspace_memberships owner_membership
82
+ INNER JOIN workspaces owner_workspace
83
+ ON owner_workspace.id = owner_membership.workspace_id
84
+ AND owner_workspace.account_id = owner_membership.account_id
85
+ WHERE owner_membership.account_id = p_account_id
86
+ AND owner_membership.subject_id = p_subject_id
87
+ AND owner_membership.role = 'owner'
88
+ AND (
89
+ NOT local_identity
90
+ OR (
91
+ owner_workspace.external_source = 'opengeni:local'
92
+ AND owner_workspace.external_id = 'default'
93
+ )
94
+ )
95
+ ) THEN
96
+ RAISE EXCEPTION 'human provisioning owner membership is invalid'
97
+ USING ERRCODE = '42501';
98
+ END IF;
99
+
100
+ SELECT * INTO workspace_row
101
+ FROM workspaces candidate_workspace
102
+ WHERE candidate_workspace.id = p_personal_workspace_id
103
+ FOR UPDATE;
104
+ IF NOT FOUND
105
+ OR workspace_row.account_id IS DISTINCT FROM p_account_id
106
+ OR workspace_row.external_source IS DISTINCT FROM 'opengeni:organization-membership'
107
+ OR workspace_row.external_id IS DISTINCT FROM (
108
+ p_account_id::text || ':' || p_subject_id
109
+ )
110
+ THEN
111
+ RAISE EXCEPTION 'human provisioning personal workspace identity is invalid'
112
+ USING ERRCODE = '42501';
113
+ END IF;
114
+
115
+ IF EXISTS (
116
+ SELECT 1 FROM workspaces conflicting_workspace
117
+ WHERE conflicting_workspace.external_source = 'opengeni:organization-membership'
118
+ AND conflicting_workspace.external_id = p_account_id::text || ':' || p_subject_id
119
+ AND conflicting_workspace.id <> p_personal_workspace_id
120
+ ) THEN
121
+ RAISE EXCEPTION 'human provisioning personal workspace identity conflicts'
122
+ USING ERRCODE = '23505';
123
+ END IF;
124
+
125
+ IF EXISTS (
126
+ SELECT 1 FROM workspace_memberships personal_access
127
+ WHERE personal_access.workspace_id = p_personal_workspace_id
128
+ ) THEN
129
+ RAISE EXCEPTION 'human personal workspace already has runtime access'
130
+ USING ERRCODE = '42501';
131
+ END IF;
132
+
133
+ PERFORM pg_catalog.set_config(
134
+ 'opengeni.workspace_id', p_personal_workspace_id::text, true
135
+ );
136
+ IF NOT EXISTS (
137
+ SELECT 1 FROM workspace_inference_controls control_row
138
+ WHERE control_row.workspace_id = p_personal_workspace_id
139
+ AND control_row.account_id = p_account_id
140
+ ) THEN
141
+ RAISE EXCEPTION 'human personal workspace control is missing'
142
+ USING ERRCODE = '42501';
143
+ END IF;
144
+
145
+ PERFORM pg_catalog.set_config(
146
+ 'opengeni.organization_tenancy_lifecycle',
147
+ 'managed_human_provisioning',
148
+ true
149
+ );
150
+ INSERT INTO organization_memberships (
151
+ account_id, subject_id, status, personal_workspace_id
152
+ ) VALUES (
153
+ p_account_id, p_subject_id, 'active', p_personal_workspace_id
154
+ ) ON CONFLICT (account_id, subject_id) DO NOTHING;
155
+
156
+ SELECT * INTO membership_row
157
+ FROM organization_memberships candidate_membership
158
+ WHERE candidate_membership.account_id = p_account_id
159
+ AND candidate_membership.subject_id = p_subject_id
160
+ FOR UPDATE;
161
+ IF NOT FOUND THEN
162
+ RAISE EXCEPTION 'human organization membership was not created'
163
+ USING ERRCODE = 'P0002';
164
+ END IF;
165
+ IF membership_row.status IN ('suspended', 'revoked') THEN
166
+ RAISE EXCEPTION 'human organization membership is not active'
167
+ USING ERRCODE = '42501';
168
+ END IF;
169
+ IF membership_row.personal_workspace_id IS NOT NULL
170
+ AND membership_row.personal_workspace_id IS DISTINCT FROM p_personal_workspace_id
171
+ THEN
172
+ RAISE EXCEPTION 'human organization membership personal workspace conflicts'
173
+ USING ERRCODE = '23505';
174
+ END IF;
175
+ IF membership_row.status = 'provisioning' THEN
176
+ UPDATE organization_memberships
177
+ SET status = 'active',
178
+ personal_workspace_id = p_personal_workspace_id,
179
+ updated_at = pg_catalog.clock_timestamp()
180
+ WHERE id = membership_row.id;
181
+ membership_row.status := 'active';
182
+ membership_row.personal_workspace_id := p_personal_workspace_id;
183
+ END IF;
184
+ IF membership_row.status <> 'active'
185
+ OR membership_row.personal_workspace_id IS DISTINCT FROM p_personal_workspace_id
186
+ THEN
187
+ RAISE EXCEPTION 'human organization membership did not converge'
188
+ USING ERRCODE = '42501';
189
+ END IF;
190
+
191
+ PERFORM pg_catalog.set_config(
192
+ 'opengeni.workspace_id', coalesce(previous_workspace_id, ''), true
193
+ );
194
+ PERFORM pg_catalog.set_config(
195
+ 'opengeni.organization_tenancy_lifecycle',
196
+ coalesce(previous_lifecycle_marker, ''),
197
+ true
198
+ );
199
+ organization_membership_id := membership_row.id;
200
+ personal_workspace_id := membership_row.personal_workspace_id;
201
+ RETURN NEXT;
202
+ EXCEPTION WHEN OTHERS THEN
203
+ PERFORM pg_catalog.set_config(
204
+ 'opengeni.workspace_id', coalesce(previous_workspace_id, ''), true
205
+ );
206
+ PERFORM pg_catalog.set_config(
207
+ 'opengeni.organization_tenancy_lifecycle',
208
+ coalesce(previous_lifecycle_marker, ''),
209
+ true
210
+ );
211
+ RAISE;
212
+ END;
213
+ $body$;
214
+ $ddl$, data_schema);
215
+
216
+ EXECUTE format(
217
+ 'REVOKE ALL ON FUNCTION %I.ensure_managed_human_personal_workspace(uuid,text,uuid) FROM PUBLIC',
218
+ data_schema
219
+ );
220
+ IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'opengeni_app') THEN
221
+ EXECUTE format(
222
+ 'GRANT EXECUTE ON FUNCTION %I.ensure_managed_human_personal_workspace(uuid,text,uuid) TO opengeni_app',
223
+ data_schema
224
+ );
225
+ END IF;
226
+ END
227
+ $local_human_personal_authority$;
228
+
229
+ COMMENT ON FUNCTION ensure_managed_human_personal_workspace(uuid, text, uuid) IS
230
+ 'Lifecycle-only managed or explicit local-human organization membership and personal-workspace provisioning; no workspace access grant.';
231
+
232
+ CREATE FUNCTION issue_self_local_connection_use_grant(
233
+ p_account_id uuid,
234
+ p_authority_id uuid,
235
+ p_workspace_id uuid,
236
+ p_context text,
237
+ p_workspace_shared_acknowledged boolean DEFAULT false
238
+ ) RETURNS TABLE (
239
+ grant_id uuid, organization_id uuid, authority_generation bigint,
240
+ target_workspace_id uuid, target_session_id uuid, action text,
241
+ grant_mode text, grant_context text, authority_epoch integer,
242
+ grant_generation bigint, grant_status text, expires_at timestamptz
243
+ )
244
+ LANGUAGE plpgsql
245
+ SECURITY DEFINER
246
+ SET search_path FROM CURRENT
247
+ AS $body$
248
+ #variable_conflict use_column
249
+ DECLARE
250
+ caller_subject text := nullif(current_setting('opengeni.subject_id', true), '');
251
+ owner_membership_id uuid;
252
+ BEGIN
253
+ PERFORM set_config(
254
+ 'opengeni.organization_tenancy_lifecycle', 'personal_resource_grant_management', true
255
+ );
256
+ IF p_account_id IS DISTINCT FROM opengeni_private.current_account_id()
257
+ OR p_workspace_id IS DISTINCT FROM opengeni_private.current_workspace_id()
258
+ OR caller_subject IS DISTINCT FROM 'dev'
259
+ OR p_context NOT IN ('user_private', 'workspace_shared')
260
+ OR (p_context = 'workspace_shared' AND p_workspace_shared_acknowledged IS NOT TRUE)
261
+ OR NOT EXISTS (
262
+ SELECT 1 FROM managed_accounts account_row
263
+ WHERE account_row.id = p_account_id
264
+ AND account_row.external_source = 'opengeni:local'
265
+ AND account_row.external_id = 'default'
266
+ )
267
+ THEN
268
+ RAISE EXCEPTION 'local connection grant authority is invalid'
269
+ USING ERRCODE = '42501';
270
+ END IF;
271
+
272
+ SELECT membership.id INTO owner_membership_id
273
+ FROM organization_memberships membership
274
+ WHERE membership.account_id = p_account_id
275
+ AND membership.subject_id = caller_subject
276
+ AND membership.status = 'active'
277
+ AND membership.revoked_at IS NULL
278
+ FOR SHARE;
279
+ IF NOT FOUND OR NOT EXISTS (
280
+ SELECT 1 FROM workspace_memberships workspace_membership
281
+ WHERE workspace_membership.account_id = p_account_id
282
+ AND workspace_membership.workspace_id = p_workspace_id
283
+ AND workspace_membership.subject_id = caller_subject
284
+ AND workspace_membership.role = 'owner'
285
+ ) THEN
286
+ RAISE EXCEPTION 'local connection grant owner is invalid'
287
+ USING ERRCODE = '42501';
288
+ END IF;
289
+
290
+ SELECT authority.generation INTO authority_generation
291
+ FROM organization_user_resource_authorities authority
292
+ WHERE authority.id = p_authority_id
293
+ AND authority.account_id = p_account_id
294
+ AND authority.organization_membership_id = owner_membership_id
295
+ AND authority.resource_kind = 'connection'
296
+ AND authority.status = 'active'
297
+ AND authority.revoked_at IS NULL
298
+ FOR UPDATE;
299
+ IF NOT FOUND THEN
300
+ RAISE EXCEPTION 'local connection authority is unavailable'
301
+ USING ERRCODE = '42501';
302
+ END IF;
303
+
304
+ INSERT INTO organization_user_resource_grants (
305
+ account_id, authority_id, owner_organization_membership_id, workspace_id,
306
+ session_id, action, mode, context, authority_epoch, generation, status
307
+ ) VALUES (
308
+ p_account_id, p_authority_id, owner_membership_id, p_workspace_id,
309
+ NULL, 'connection.use', 'always', p_context, NULL, 1, 'active'
310
+ )
311
+ ON CONFLICT (account_id, authority_id, workspace_id, action, mode, context,
312
+ (coalesce(session_id, '00000000-0000-0000-0000-000000000000'::uuid)),
313
+ (coalesce(authority_epoch, 0))) WHERE status = 'active'
314
+ DO UPDATE SET updated_at = organization_user_resource_grants.updated_at
315
+ RETURNING id, workspace_id, session_id, organization_user_resource_grants.action,
316
+ mode, context, organization_user_resource_grants.authority_epoch, generation,
317
+ status, organization_user_resource_grants.expires_at
318
+ INTO grant_id, target_workspace_id, target_session_id, action, grant_mode,
319
+ grant_context, authority_epoch, grant_generation, grant_status, expires_at;
320
+ organization_id := p_account_id;
321
+ RETURN NEXT;
322
+ END
323
+ $body$;
324
+
325
+ DO $local_connection_grant_search_path$
326
+ DECLARE
327
+ data_schema text := current_schema();
328
+ BEGIN
329
+ EXECUTE format(
330
+ 'ALTER FUNCTION %I.issue_self_local_connection_use_grant(uuid,uuid,uuid,text,boolean) SET search_path = pg_catalog, %I, pg_temp',
331
+ data_schema, data_schema
332
+ );
333
+ END
334
+ $local_connection_grant_search_path$;
335
+ REVOKE ALL ON FUNCTION issue_self_local_connection_use_grant(
336
+ uuid, uuid, uuid, text, boolean
337
+ ) FROM PUBLIC;
338
+ DO $local_connection_grant_role$
339
+ BEGIN
340
+ IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'opengeni_app') THEN
341
+ GRANT EXECUTE ON FUNCTION issue_self_local_connection_use_grant(
342
+ uuid, uuid, uuid, text, boolean
343
+ ) TO opengeni_app;
344
+ END IF;
345
+ END
346
+ $local_connection_grant_role$;
347
+
348
+ COMMENT ON FUNCTION issue_self_local_connection_use_grant(
349
+ uuid, uuid, uuid, text, boolean
350
+ ) IS 'Idempotently issues standing connection.use only for the explicit local dev human and exact local owner workspace.';
@@ -0,0 +1,98 @@
1
+ -- deployment-mode: rolling
2
+ -- Workspace administrators may manage access to their exact shared workspace,
3
+ -- but they may only add active human members of the owning organization.
4
+
5
+ SET LOCAL lock_timeout = '5s';
6
+ SET LOCAL statement_timeout = '10min';
7
+
8
+ CREATE FUNCTION assert_workspace_member_management_candidate(
9
+ p_account_id uuid,
10
+ p_workspace_id uuid,
11
+ p_actor_subject_id text,
12
+ p_target_subject_id text
13
+ ) RETURNS void
14
+ LANGUAGE plpgsql SECURITY DEFINER
15
+ SET search_path FROM CURRENT
16
+ AS $body$
17
+ DECLARE
18
+ previous_lifecycle text := current_setting('opengeni.organization_tenancy_lifecycle', true);
19
+ BEGIN
20
+ IF p_account_id IS NULL OR p_workspace_id IS NULL
21
+ OR nullif(pg_catalog.btrim(p_actor_subject_id), '') IS NULL
22
+ OR nullif(pg_catalog.btrim(p_target_subject_id), '') IS NULL
23
+ OR p_account_id IS DISTINCT FROM opengeni_private.current_account_id()
24
+ OR p_workspace_id IS DISTINCT FROM opengeni_private.current_workspace_id()
25
+ OR p_actor_subject_id IS DISTINCT FROM opengeni_private.current_subject_id()
26
+ THEN
27
+ RAISE EXCEPTION 'workspace member management authority required' USING ERRCODE = '42501';
28
+ END IF;
29
+
30
+ PERFORM pg_catalog.set_config(
31
+ 'opengeni.organization_tenancy_lifecycle',
32
+ 'organization_membership_lifecycle', true
33
+ );
34
+
35
+ IF NOT EXISTS (
36
+ SELECT 1 FROM workspaces workspace
37
+ WHERE workspace.id = p_workspace_id AND workspace.account_id = p_account_id
38
+ ) THEN
39
+ RAISE EXCEPTION 'workspace not found' USING ERRCODE = 'P0002';
40
+ END IF;
41
+
42
+ IF EXISTS (
43
+ SELECT 1 FROM organization_memberships membership
44
+ WHERE membership.account_id = p_account_id
45
+ AND membership.personal_workspace_id = p_workspace_id
46
+ ) THEN
47
+ RAISE EXCEPTION 'Personal workspace membership is owner-only' USING ERRCODE = '42501';
48
+ END IF;
49
+
50
+ IF NOT EXISTS (
51
+ SELECT 1
52
+ FROM organization_memberships organization_membership
53
+ JOIN workspace_memberships workspace_membership
54
+ ON workspace_membership.account_id = organization_membership.account_id
55
+ AND workspace_membership.subject_id = organization_membership.subject_id
56
+ AND workspace_membership.workspace_id = p_workspace_id
57
+ WHERE organization_membership.account_id = p_account_id
58
+ AND organization_membership.subject_id = p_actor_subject_id
59
+ AND organization_membership.status = 'active'
60
+ AND (
61
+ workspace_membership.permissions ? 'members:manage'
62
+ OR workspace_membership.permissions ? 'workspace:admin'
63
+ )
64
+ ) THEN
65
+ RAISE EXCEPTION 'workspace member management authority required' USING ERRCODE = '42501';
66
+ END IF;
67
+
68
+ IF NOT EXISTS (
69
+ SELECT 1 FROM organization_memberships target
70
+ WHERE target.account_id = p_account_id
71
+ AND target.subject_id = p_target_subject_id
72
+ AND target.status = 'active'
73
+ ) THEN
74
+ RAISE EXCEPTION 'active organization member not found' USING ERRCODE = 'P0002';
75
+ END IF;
76
+
77
+ PERFORM pg_catalog.set_config(
78
+ 'opengeni.organization_tenancy_lifecycle', COALESCE(previous_lifecycle, ''), true
79
+ );
80
+ EXCEPTION WHEN OTHERS THEN
81
+ PERFORM pg_catalog.set_config(
82
+ 'opengeni.organization_tenancy_lifecycle', COALESCE(previous_lifecycle, ''), true
83
+ );
84
+ RAISE;
85
+ END
86
+ $body$;
87
+
88
+ REVOKE ALL ON FUNCTION assert_workspace_member_management_candidate(uuid, uuid, text, text)
89
+ FROM PUBLIC;
90
+ DO $workspace_member_management_role$
91
+ BEGIN
92
+ IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'opengeni_app') THEN
93
+ GRANT EXECUTE ON FUNCTION assert_workspace_member_management_candidate(
94
+ uuid, uuid, text, text
95
+ ) TO opengeni_app;
96
+ END IF;
97
+ END
98
+ $workspace_member_management_role$;
@@ -0,0 +1,128 @@
1
+ -- deployment-mode: rolling
2
+ -- Workspace member managers may enumerate only active same-organization humans
3
+ -- who do not already have access to their exact shared workspace.
4
+
5
+ SET LOCAL lock_timeout = '5s';
6
+ SET LOCAL statement_timeout = '10min';
7
+
8
+ CREATE FUNCTION list_workspace_member_management_candidates(
9
+ p_account_id uuid,
10
+ p_workspace_id uuid,
11
+ p_actor_subject_id text
12
+ ) RETURNS jsonb
13
+ LANGUAGE plpgsql SECURITY DEFINER
14
+ SET search_path FROM CURRENT
15
+ AS $body$
16
+ DECLARE
17
+ previous_lifecycle text := current_setting('opengeni.organization_tenancy_lifecycle', true);
18
+ result jsonb;
19
+ BEGIN
20
+ IF p_account_id IS NULL OR p_workspace_id IS NULL
21
+ OR nullif(pg_catalog.btrim(p_actor_subject_id), '') IS NULL
22
+ OR p_account_id IS DISTINCT FROM opengeni_private.current_account_id()
23
+ OR p_workspace_id IS DISTINCT FROM opengeni_private.current_workspace_id()
24
+ OR p_actor_subject_id IS DISTINCT FROM opengeni_private.current_subject_id()
25
+ THEN
26
+ RAISE EXCEPTION 'workspace member management authority required' USING ERRCODE = '42501';
27
+ END IF;
28
+
29
+ PERFORM pg_catalog.set_config(
30
+ 'opengeni.organization_tenancy_lifecycle',
31
+ 'organization_membership_lifecycle', true
32
+ );
33
+
34
+ IF NOT EXISTS (
35
+ SELECT 1 FROM workspaces workspace
36
+ WHERE workspace.id = p_workspace_id AND workspace.account_id = p_account_id
37
+ ) THEN
38
+ RAISE EXCEPTION 'workspace not found' USING ERRCODE = 'P0002';
39
+ END IF;
40
+
41
+ IF EXISTS (
42
+ SELECT 1 FROM organization_memberships membership
43
+ WHERE membership.account_id = p_account_id
44
+ AND membership.personal_workspace_id = p_workspace_id
45
+ ) THEN
46
+ RAISE EXCEPTION 'Personal workspace membership is owner-only' USING ERRCODE = '42501';
47
+ END IF;
48
+
49
+ IF NOT EXISTS (
50
+ SELECT 1
51
+ FROM organization_memberships organization_membership
52
+ JOIN workspace_memberships workspace_membership
53
+ ON workspace_membership.account_id = organization_membership.account_id
54
+ AND workspace_membership.subject_id = organization_membership.subject_id
55
+ AND workspace_membership.workspace_id = p_workspace_id
56
+ WHERE organization_membership.account_id = p_account_id
57
+ AND organization_membership.subject_id = p_actor_subject_id
58
+ AND organization_membership.status = 'active'
59
+ AND (
60
+ workspace_membership.permissions ? 'members:manage'
61
+ OR workspace_membership.permissions ? 'workspace:admin'
62
+ )
63
+ ) THEN
64
+ RAISE EXCEPTION 'workspace member management authority required' USING ERRCODE = '42501';
65
+ END IF;
66
+
67
+ IF (
68
+ SELECT count(*)
69
+ FROM organization_memberships membership
70
+ WHERE membership.account_id = p_account_id
71
+ AND membership.status = 'active'
72
+ AND membership.subject_id LIKE 'user:%'
73
+ AND NOT EXISTS (
74
+ SELECT 1 FROM workspace_memberships access
75
+ WHERE access.account_id = p_account_id
76
+ AND access.workspace_id = p_workspace_id
77
+ AND access.subject_id = membership.subject_id
78
+ )
79
+ ) > 1000 THEN
80
+ RAISE EXCEPTION 'workspace member candidate inventory exceeds the bounded projection'
81
+ USING ERRCODE = '54000';
82
+ END IF;
83
+
84
+ SELECT coalesce(pg_catalog.jsonb_agg(
85
+ pg_catalog.jsonb_build_object(
86
+ 'organizationMembershipId', membership.id,
87
+ 'subjectId', membership.subject_id,
88
+ 'name', auth_user.name,
89
+ 'email', auth_user.email,
90
+ 'organizationRole', membership.role
91
+ ) ORDER BY lower(coalesce(auth_user.name, auth_user.email, membership.subject_id)), membership.id
92
+ ), '[]'::jsonb) INTO result
93
+ FROM organization_memberships membership
94
+ LEFT JOIN auth_users auth_user
95
+ ON membership.subject_id = 'user:' || auth_user.id
96
+ WHERE membership.account_id = p_account_id
97
+ AND membership.status = 'active'
98
+ AND membership.subject_id LIKE 'user:%'
99
+ AND NOT EXISTS (
100
+ SELECT 1 FROM workspace_memberships access
101
+ WHERE access.account_id = p_account_id
102
+ AND access.workspace_id = p_workspace_id
103
+ AND access.subject_id = membership.subject_id
104
+ );
105
+
106
+ PERFORM pg_catalog.set_config(
107
+ 'opengeni.organization_tenancy_lifecycle', COALESCE(previous_lifecycle, ''), true
108
+ );
109
+ RETURN result;
110
+ EXCEPTION WHEN OTHERS THEN
111
+ PERFORM pg_catalog.set_config(
112
+ 'opengeni.organization_tenancy_lifecycle', COALESCE(previous_lifecycle, ''), true
113
+ );
114
+ RAISE;
115
+ END
116
+ $body$;
117
+
118
+ REVOKE ALL ON FUNCTION list_workspace_member_management_candidates(uuid, uuid, text)
119
+ FROM PUBLIC;
120
+ DO $workspace_member_candidate_inventory_role$
121
+ BEGIN
122
+ IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'opengeni_app') THEN
123
+ GRANT EXECUTE ON FUNCTION list_workspace_member_management_candidates(
124
+ uuid, uuid, text
125
+ ) TO opengeni_app;
126
+ END IF;
127
+ END
128
+ $workspace_member_candidate_inventory_role$;