@opengeni/db 0.31.1 → 0.36.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.
- package/dist/browser-auth.d.ts +209 -1
- package/dist/browser-downloads.d.ts +51 -0
- package/dist/browser-identities.d.ts +11 -2
- package/dist/browser-sessions.d.ts +83 -1
- package/dist/browser-state-artifacts.d.ts +75 -1
- package/dist/canonical-human-identities.d.ts +48 -0
- package/dist/canonical-human-identities.js +28 -0
- package/dist/canonical-human-identities.js.map +1 -0
- package/dist/capability-integrations.d.ts +8 -6
- package/dist/{chunk-MWDVXQOL.js → chunk-5KTIEDX7.js} +5773 -4212
- package/dist/chunk-5KTIEDX7.js.map +1 -0
- package/dist/{chunk-NBE6CHRI.js → chunk-CQZ4QSP5.js} +49 -9
- package/dist/chunk-CQZ4QSP5.js.map +1 -0
- package/dist/chunk-F32YT7MP.js +117 -0
- package/dist/chunk-F32YT7MP.js.map +1 -0
- package/dist/{chunk-ISI2TIUG.js → chunk-JC5QPLUM.js} +30 -3
- package/dist/chunk-JC5QPLUM.js.map +1 -0
- package/dist/{chunk-F5FT7BEZ.js → chunk-P3RE4D2B.js} +2 -2
- package/dist/chunk-TAUTWOS5.js +259 -0
- package/dist/chunk-TAUTWOS5.js.map +1 -0
- package/dist/{chunk-YHZXQ7HP.js → chunk-VKLB2ZGI.js} +446 -19
- package/dist/chunk-VKLB2ZGI.js.map +1 -0
- package/dist/database.d.ts +5 -0
- package/dist/editable-artifact-durable-export.js +2 -2
- package/dist/editable-artifacts.js +3 -3
- package/dist/index.d.ts +438 -29
- package/dist/index.js +35640 -28969
- package/dist/index.js.map +1 -1
- package/dist/insights.d.ts +23 -7
- package/dist/integration-bindings.d.ts +24 -24
- package/dist/integration-facets.d.ts +99 -0
- package/dist/interaction-revisions.d.ts +11 -0
- package/dist/interaction-schema.d.ts +698 -34
- package/dist/provision-roles.js +1 -1
- package/dist/runtime-posture.d.ts +8 -7
- package/dist/schema.d.ts +9464 -5412
- package/dist/schema.js +51 -9
- package/dist/session-control.d.ts +29 -3
- package/dist/session-tenancy.d.ts +44 -0
- package/dist/session-tenancy.js +16 -0
- package/dist/session-tenancy.js.map +1 -0
- package/dist/slack-task-policy-schema.d.ts +847 -0
- package/dist/slack-task-policy.d.ts +65 -0
- package/dist/task-notes-schema.d.ts +924 -0
- package/dist/task-notes.d.ts +85 -0
- package/dist/video-generation.d.ts +9 -0
- package/dist/video-generation.js +5 -3
- package/dist/xai-subscription.d.ts +326 -0
- package/drizzle/0212_browser_state_transfer_hardening.sql +560 -0
- package/drizzle/0213_browser_interaction_authority.sql +67 -0
- package/drizzle/0214_browser_download_saves.sql +34 -0
- package/drizzle/0215_browser_controller_host.sql +385 -0
- package/drizzle/0216_browser_auth_health_evidence.sql +137 -0
- package/drizzle/0217_external_browser_auth_operations.sql +22 -0
- package/drizzle/0218_organization_tenancy_foundation.sql +299 -0
- package/drizzle/0219_organization_tenancy_managed_human_provisioning.sql +317 -0
- package/drizzle/0219_site_auth_maintenance_sessions.sql +234 -0
- package/drizzle/0220_memory_slack_append_only_cascade.sql +38 -0
- package/drizzle/0220_session_channels.sql +54 -0
- package/drizzle/0221_sessions_channel_index.sql +5 -0
- package/drizzle/0222_session_visibility_authority_epochs.sql +158 -0
- package/drizzle/0222_sessions_channel_fk.sql +89 -0
- package/drizzle/0223_pending_tool_event_output.sql +55 -0
- package/drizzle/0223_sessions_channel_fk_validate.sql +118 -0
- package/drizzle/0224_slack_post_outcome_reconciliation.sql +123 -0
- package/drizzle/0225_session_visibility_fork_activation.sql +1363 -0
- package/drizzle/0226_personal_codex_authority_foundation.sql +365 -0
- package/drizzle/0227_slack_native_actions.sql +145 -0
- package/drizzle/0228_interaction_controller_data_plane.sql +14 -0
- package/drizzle/0228_slack_task_policy.sql +400 -0
- package/drizzle/0229_slack_inbox_file_fact.sql +10 -0
- package/drizzle/0230_user_scoped_variable_sets_rigs.sql +84 -0
- package/drizzle/0231_integration_definition_identity_cutover.sql +271 -0
- package/drizzle/0232_integration_facet_authority_cutover.sql +610 -0
- package/drizzle/0233_skill_and_integration_authority_cutover.sql +1162 -0
- package/drizzle/0234_xai_subscription_authority.sql +1139 -0
- package/drizzle/0235_canonical_human_login_bindings.sql +920 -0
- package/drizzle/0236_browser_identity_lifecycle.sql +39 -0
- package/drizzle/0236_session_visibility_slack_policy.sql +72 -0
- package/drizzle/0237_interaction_transition_reaper.sql +263 -0
- package/drizzle/0238_goal_persistence_policy.sql +471 -0
- package/drizzle/0238_supergrok_realtime_model.sql +29 -0
- package/drizzle/0239_supergrok_video_funding.sql +50 -0
- package/drizzle/0239_task_tree_notes.sql +990 -0
- package/package.json +13 -5
- package/src/browser-auth.ts +2600 -123
- package/src/browser-downloads.ts +517 -0
- package/src/browser-identities.ts +220 -3
- package/src/browser-sessions.ts +334 -45
- package/src/browser-state-artifacts.ts +402 -12
- package/src/canonical-human-identities.ts +317 -0
- package/src/capability-integrations.ts +121 -213
- package/src/database.ts +41 -1
- package/src/index.ts +4157 -394
- package/src/insights.ts +109 -28
- package/src/integration-bindings.ts +101 -101
- package/src/{integration-features.ts → integration-facets.ts} +187 -184
- package/src/interaction-revisions.ts +33 -3
- package/src/interaction-schema.ts +311 -8
- package/src/pack-components.ts +43 -43
- package/src/pack-installations.ts +0 -43
- package/src/plugin-packages.ts +9 -9
- package/src/provision-roles.ts +232 -0
- package/src/runtime-posture.ts +227 -14
- package/src/schema.ts +1188 -75
- package/src/session-control.ts +122 -37
- package/src/session-queue-commands.ts +78 -1
- package/src/session-tenancy.ts +188 -0
- package/src/session-tool-call-settlement.ts +9 -3
- package/src/slack-task-policy-schema.ts +130 -0
- package/src/slack-task-policy.ts +341 -0
- package/src/task-notes-schema.ts +135 -0
- package/src/task-notes.ts +178 -0
- package/src/video-generation.ts +90 -12
- package/src/workspace-artifacts.ts +1 -1
- package/src/xai-subscription.ts +1887 -0
- package/dist/chunk-ISI2TIUG.js.map +0 -1
- package/dist/chunk-MWDVXQOL.js.map +0 -1
- package/dist/chunk-NBE6CHRI.js.map +0 -1
- package/dist/chunk-YHZXQ7HP.js.map +0 -1
- package/dist/integration-features.d.ts +0 -99
- /package/dist/{chunk-F5FT7BEZ.js.map → chunk-P3RE4D2B.js.map} +0 -0
|
@@ -0,0 +1,1139 @@
|
|
|
1
|
+
-- deployment-mode: rolling
|
|
2
|
+
-- Add explicit workspace/user xAI subscription authority, encrypted multi-account
|
|
3
|
+
-- persistence, exact-turn leases, session pins, quota/cooldown metadata, durable
|
|
4
|
+
-- capacity waiters, and immutable identifier-free acceptance snapshots. This
|
|
5
|
+
-- migration activates no API, worker, SDK, or provider transport implementation.
|
|
6
|
+
|
|
7
|
+
SET LOCAL lock_timeout = '5s';
|
|
8
|
+
SET LOCAL statement_timeout = '10min';
|
|
9
|
+
|
|
10
|
+
CREATE TABLE opengeni_private.xai_subscription_runtime_capabilities (
|
|
11
|
+
"backend_pid" integer NOT NULL,
|
|
12
|
+
"transaction_id" xid8 NOT NULL,
|
|
13
|
+
"capability_kind" text NOT NULL,
|
|
14
|
+
"created_at" timestamptz NOT NULL DEFAULT clock_timestamp(),
|
|
15
|
+
CONSTRAINT "xai_subscription_runtime_capabilities_kind_chk" CHECK (
|
|
16
|
+
"capability_kind" IN ('lifecycle', 'resolve')
|
|
17
|
+
),
|
|
18
|
+
CONSTRAINT "xai_subscription_runtime_capabilities_pk" PRIMARY KEY (
|
|
19
|
+
"backend_pid", "transaction_id", "capability_kind"
|
|
20
|
+
)
|
|
21
|
+
);
|
|
22
|
+
REVOKE ALL ON TABLE opengeni_private.xai_subscription_runtime_capabilities FROM PUBLIC;
|
|
23
|
+
|
|
24
|
+
DO $xai_capability_revoke$
|
|
25
|
+
BEGIN
|
|
26
|
+
IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'opengeni_app') THEN
|
|
27
|
+
REVOKE ALL ON TABLE opengeni_private.xai_subscription_runtime_capabilities
|
|
28
|
+
FROM opengeni_app;
|
|
29
|
+
END IF;
|
|
30
|
+
END
|
|
31
|
+
$xai_capability_revoke$;
|
|
32
|
+
|
|
33
|
+
CREATE UNIQUE INDEX IF NOT EXISTS "organization_user_resource_authorities_xai_tuple_uq"
|
|
34
|
+
ON "organization_user_resource_authorities" (
|
|
35
|
+
"id", "account_id", "organization_membership_id", "resource_kind",
|
|
36
|
+
"resource_id", "generation"
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
-- Add a separate permissive policy used only by the exact xAI SECURITY DEFINER
|
|
40
|
+
-- routines. Existing organization-tenancy lifecycle/resource policies remain
|
|
41
|
+
-- intact, so this is compatible with either protected main or PR #1373 first.
|
|
42
|
+
DROP POLICY IF EXISTS xai_subscription_capability_read ON "organization_memberships";
|
|
43
|
+
CREATE POLICY xai_subscription_capability_read ON "organization_memberships"
|
|
44
|
+
FOR SELECT USING (
|
|
45
|
+
current_user = pg_catalog.pg_get_userbyid(
|
|
46
|
+
(SELECT relation.relowner FROM pg_catalog.pg_class relation
|
|
47
|
+
WHERE relation.oid = 'organization_memberships'::pg_catalog.regclass)
|
|
48
|
+
)
|
|
49
|
+
AND EXISTS (
|
|
50
|
+
SELECT 1 FROM opengeni_private.xai_subscription_runtime_capabilities capability
|
|
51
|
+
WHERE capability.backend_pid = pg_catalog.pg_backend_pid()
|
|
52
|
+
AND capability.transaction_id = pg_catalog.pg_current_xact_id_if_assigned()
|
|
53
|
+
AND capability.capability_kind IN ('lifecycle', 'resolve')
|
|
54
|
+
)
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
DROP POLICY IF EXISTS xai_subscription_capability_read
|
|
58
|
+
ON "organization_user_resource_authorities";
|
|
59
|
+
CREATE POLICY xai_subscription_capability_read ON "organization_user_resource_authorities"
|
|
60
|
+
FOR SELECT USING (
|
|
61
|
+
current_user = pg_catalog.pg_get_userbyid(
|
|
62
|
+
(SELECT relation.relowner FROM pg_catalog.pg_class relation
|
|
63
|
+
WHERE relation.oid = 'organization_user_resource_authorities'::pg_catalog.regclass)
|
|
64
|
+
)
|
|
65
|
+
AND EXISTS (
|
|
66
|
+
SELECT 1 FROM opengeni_private.xai_subscription_runtime_capabilities capability
|
|
67
|
+
WHERE capability.backend_pid = pg_catalog.pg_backend_pid()
|
|
68
|
+
AND capability.transaction_id = pg_catalog.pg_current_xact_id_if_assigned()
|
|
69
|
+
AND capability.capability_kind IN ('lifecycle', 'resolve')
|
|
70
|
+
)
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
DROP POLICY IF EXISTS xai_subscription_capability_insert
|
|
74
|
+
ON "organization_user_resource_authorities";
|
|
75
|
+
CREATE POLICY xai_subscription_capability_insert ON "organization_user_resource_authorities"
|
|
76
|
+
FOR INSERT WITH CHECK (
|
|
77
|
+
current_user = pg_catalog.pg_get_userbyid(
|
|
78
|
+
(SELECT relation.relowner FROM pg_catalog.pg_class relation
|
|
79
|
+
WHERE relation.oid = 'organization_user_resource_authorities'::pg_catalog.regclass)
|
|
80
|
+
)
|
|
81
|
+
AND EXISTS (
|
|
82
|
+
SELECT 1 FROM opengeni_private.xai_subscription_runtime_capabilities capability
|
|
83
|
+
WHERE capability.backend_pid = pg_catalog.pg_backend_pid()
|
|
84
|
+
AND capability.transaction_id = pg_catalog.pg_current_xact_id_if_assigned()
|
|
85
|
+
AND capability.capability_kind = 'lifecycle'
|
|
86
|
+
)
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
CREATE TABLE "xai_subscription_credentials" (
|
|
90
|
+
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
91
|
+
"account_id" uuid NOT NULL REFERENCES "managed_accounts"("id") ON DELETE CASCADE,
|
|
92
|
+
"workspace_id" uuid NOT NULL REFERENCES "workspaces"("id") ON DELETE CASCADE,
|
|
93
|
+
"credential_encrypted" text NOT NULL,
|
|
94
|
+
"provider_account_id" text,
|
|
95
|
+
"label" text,
|
|
96
|
+
"account_email" text,
|
|
97
|
+
"plan_type" text,
|
|
98
|
+
"status" text NOT NULL DEFAULT 'active',
|
|
99
|
+
"expires_at" timestamptz,
|
|
100
|
+
"last_refresh_at" timestamptz,
|
|
101
|
+
"last_error" text,
|
|
102
|
+
"version" integer NOT NULL DEFAULT 1,
|
|
103
|
+
"allocator_enabled" boolean NOT NULL DEFAULT true,
|
|
104
|
+
"allocator_version" integer NOT NULL DEFAULT 1,
|
|
105
|
+
"allocator_updated_at" timestamptz,
|
|
106
|
+
"quota_used_percent" integer,
|
|
107
|
+
"quota_reset_at" timestamptz,
|
|
108
|
+
"quota_checked_at" timestamptz,
|
|
109
|
+
"exhausted_until" timestamptz,
|
|
110
|
+
"selection_count" integer NOT NULL DEFAULT 0,
|
|
111
|
+
"last_selected_at" timestamptz,
|
|
112
|
+
"authority_scope" text NOT NULL DEFAULT 'workspace',
|
|
113
|
+
"owner_organization_membership_id" uuid,
|
|
114
|
+
"organization_user_resource_authority_id" uuid,
|
|
115
|
+
"organization_user_resource_kind" text,
|
|
116
|
+
"organization_user_resource_authority_generation" bigint,
|
|
117
|
+
"connected_by_subject_id" text,
|
|
118
|
+
"created_at" timestamptz NOT NULL DEFAULT now(),
|
|
119
|
+
"updated_at" timestamptz NOT NULL DEFAULT now(),
|
|
120
|
+
CONSTRAINT "xai_subscription_credentials_workspace_account_fk"
|
|
121
|
+
FOREIGN KEY ("workspace_id", "account_id")
|
|
122
|
+
REFERENCES "workspaces"("id", "account_id") ON DELETE CASCADE,
|
|
123
|
+
CONSTRAINT "xai_subscription_credentials_owner_membership_fk"
|
|
124
|
+
FOREIGN KEY ("owner_organization_membership_id", "account_id")
|
|
125
|
+
REFERENCES "organization_memberships"("id", "account_id") ON DELETE RESTRICT,
|
|
126
|
+
CONSTRAINT "xai_subscription_credentials_user_authority_fk"
|
|
127
|
+
FOREIGN KEY (
|
|
128
|
+
"organization_user_resource_authority_id", "account_id",
|
|
129
|
+
"owner_organization_membership_id", "organization_user_resource_kind",
|
|
130
|
+
"id", "organization_user_resource_authority_generation"
|
|
131
|
+
) REFERENCES "organization_user_resource_authorities"(
|
|
132
|
+
"id", "account_id", "organization_membership_id", "resource_kind",
|
|
133
|
+
"resource_id", "generation"
|
|
134
|
+
) ON DELETE RESTRICT,
|
|
135
|
+
CONSTRAINT "xai_subscription_credentials_authority_scope_chk" CHECK (
|
|
136
|
+
"authority_scope" IN ('workspace', 'user')
|
|
137
|
+
),
|
|
138
|
+
CONSTRAINT "xai_subscription_credentials_authority_shape_chk" CHECK (
|
|
139
|
+
(
|
|
140
|
+
"authority_scope" = 'workspace'
|
|
141
|
+
AND "owner_organization_membership_id" IS NULL
|
|
142
|
+
AND "organization_user_resource_authority_id" IS NULL
|
|
143
|
+
AND "organization_user_resource_kind" IS NULL
|
|
144
|
+
AND "organization_user_resource_authority_generation" IS NULL
|
|
145
|
+
) OR (
|
|
146
|
+
"authority_scope" = 'user'
|
|
147
|
+
AND "owner_organization_membership_id" IS NOT NULL
|
|
148
|
+
AND "organization_user_resource_authority_id" IS NOT NULL
|
|
149
|
+
AND "organization_user_resource_kind" = 'xai_subscription'
|
|
150
|
+
AND "organization_user_resource_authority_generation" > 0
|
|
151
|
+
)
|
|
152
|
+
),
|
|
153
|
+
CONSTRAINT "xai_subscription_credentials_status_chk" CHECK (
|
|
154
|
+
"status" IN ('active', 'needs_relogin', 'error', 'disabled')
|
|
155
|
+
),
|
|
156
|
+
CONSTRAINT "xai_subscription_credentials_versions_chk" CHECK (
|
|
157
|
+
"version" > 0 AND "allocator_version" > 0
|
|
158
|
+
),
|
|
159
|
+
CONSTRAINT "xai_subscription_credentials_quota_chk" CHECK (
|
|
160
|
+
"quota_used_percent" IS NULL OR "quota_used_percent" BETWEEN 0 AND 100
|
|
161
|
+
),
|
|
162
|
+
CONSTRAINT "xai_subscription_credentials_selection_chk" CHECK (
|
|
163
|
+
"selection_count" >= 0
|
|
164
|
+
),
|
|
165
|
+
CONSTRAINT "xai_subscription_credentials_subject_chk" CHECK (
|
|
166
|
+
"connected_by_subject_id" IS NULL
|
|
167
|
+
OR length(btrim("connected_by_subject_id")) BETWEEN 1 AND 1024
|
|
168
|
+
)
|
|
169
|
+
);
|
|
170
|
+
CREATE UNIQUE INDEX "xai_subscription_credentials_workspace_id_uq"
|
|
171
|
+
ON "xai_subscription_credentials" ("workspace_id", "id");
|
|
172
|
+
CREATE UNIQUE INDEX "xai_subscription_credentials_workspace_account_id_uq"
|
|
173
|
+
ON "xai_subscription_credentials" ("workspace_id", "account_id", "id");
|
|
174
|
+
CREATE UNIQUE INDEX "xai_subscription_credentials_provider_identity_uq"
|
|
175
|
+
ON "xai_subscription_credentials" (
|
|
176
|
+
"workspace_id", "authority_scope", "owner_organization_membership_id",
|
|
177
|
+
"provider_account_id"
|
|
178
|
+
) NULLS NOT DISTINCT
|
|
179
|
+
WHERE "provider_account_id" IS NOT NULL;
|
|
180
|
+
CREATE INDEX "xai_subscription_credentials_workspace_status_idx"
|
|
181
|
+
ON "xai_subscription_credentials" ("workspace_id", "status", "allocator_enabled");
|
|
182
|
+
|
|
183
|
+
CREATE TABLE "xai_rotation_settings" (
|
|
184
|
+
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
185
|
+
"account_id" uuid NOT NULL REFERENCES "managed_accounts"("id") ON DELETE CASCADE,
|
|
186
|
+
"workspace_id" uuid NOT NULL REFERENCES "workspaces"("id") ON DELETE CASCADE,
|
|
187
|
+
"authority_scope" text NOT NULL DEFAULT 'workspace',
|
|
188
|
+
"owner_organization_membership_id" uuid,
|
|
189
|
+
"active_credential_id" uuid,
|
|
190
|
+
"rotation_enabled" boolean NOT NULL DEFAULT true,
|
|
191
|
+
"fairness_cursor" bigint NOT NULL DEFAULT 0,
|
|
192
|
+
"version" integer NOT NULL DEFAULT 1,
|
|
193
|
+
"created_at" timestamptz NOT NULL DEFAULT now(),
|
|
194
|
+
"updated_at" timestamptz NOT NULL DEFAULT now(),
|
|
195
|
+
CONSTRAINT "xai_rotation_settings_workspace_account_fk"
|
|
196
|
+
FOREIGN KEY ("workspace_id", "account_id")
|
|
197
|
+
REFERENCES "workspaces"("id", "account_id") ON DELETE CASCADE,
|
|
198
|
+
CONSTRAINT "xai_rotation_settings_owner_membership_fk"
|
|
199
|
+
FOREIGN KEY ("owner_organization_membership_id", "account_id")
|
|
200
|
+
REFERENCES "organization_memberships"("id", "account_id") ON DELETE RESTRICT,
|
|
201
|
+
CONSTRAINT "xai_rotation_settings_active_credential_fk"
|
|
202
|
+
FOREIGN KEY ("workspace_id", "account_id", "active_credential_id")
|
|
203
|
+
REFERENCES "xai_subscription_credentials"("workspace_id", "account_id", "id")
|
|
204
|
+
ON DELETE SET NULL ("active_credential_id"),
|
|
205
|
+
CONSTRAINT "xai_rotation_settings_scope_chk" CHECK (
|
|
206
|
+
("authority_scope" = 'workspace' AND "owner_organization_membership_id" IS NULL)
|
|
207
|
+
OR ("authority_scope" = 'user' AND "owner_organization_membership_id" IS NOT NULL)
|
|
208
|
+
),
|
|
209
|
+
CONSTRAINT "xai_rotation_settings_counters_chk" CHECK (
|
|
210
|
+
"fairness_cursor" >= 0 AND "version" > 0
|
|
211
|
+
)
|
|
212
|
+
);
|
|
213
|
+
CREATE UNIQUE INDEX "xai_rotation_settings_workspace_pool_uq"
|
|
214
|
+
ON "xai_rotation_settings" (
|
|
215
|
+
"workspace_id", "authority_scope", "owner_organization_membership_id"
|
|
216
|
+
) NULLS NOT DISTINCT;
|
|
217
|
+
|
|
218
|
+
CREATE TABLE "xai_credential_leases" (
|
|
219
|
+
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
220
|
+
"account_id" uuid NOT NULL REFERENCES "managed_accounts"("id") ON DELETE CASCADE,
|
|
221
|
+
"workspace_id" uuid NOT NULL REFERENCES "workspaces"("id") ON DELETE CASCADE,
|
|
222
|
+
"authority_scope" text NOT NULL,
|
|
223
|
+
"owner_organization_membership_id" uuid,
|
|
224
|
+
"credential_id" uuid NOT NULL,
|
|
225
|
+
"turn_id" uuid NOT NULL,
|
|
226
|
+
"holder_id" text NOT NULL,
|
|
227
|
+
"generation" integer NOT NULL DEFAULT 1,
|
|
228
|
+
"leased_until" timestamptz NOT NULL,
|
|
229
|
+
"created_at" timestamptz NOT NULL DEFAULT now(),
|
|
230
|
+
"updated_at" timestamptz NOT NULL DEFAULT now(),
|
|
231
|
+
CONSTRAINT "xai_credential_leases_workspace_account_fk"
|
|
232
|
+
FOREIGN KEY ("workspace_id", "account_id")
|
|
233
|
+
REFERENCES "workspaces"("id", "account_id") ON DELETE CASCADE,
|
|
234
|
+
CONSTRAINT "xai_credential_leases_owner_membership_fk"
|
|
235
|
+
FOREIGN KEY ("owner_organization_membership_id", "account_id")
|
|
236
|
+
REFERENCES "organization_memberships"("id", "account_id") ON DELETE RESTRICT,
|
|
237
|
+
CONSTRAINT "xai_credential_leases_credential_fk"
|
|
238
|
+
FOREIGN KEY ("workspace_id", "account_id", "credential_id")
|
|
239
|
+
REFERENCES "xai_subscription_credentials"("workspace_id", "account_id", "id")
|
|
240
|
+
ON DELETE CASCADE,
|
|
241
|
+
CONSTRAINT "xai_credential_leases_turn_fk"
|
|
242
|
+
FOREIGN KEY ("workspace_id", "turn_id")
|
|
243
|
+
REFERENCES "session_turns"("workspace_id", "id") ON DELETE CASCADE,
|
|
244
|
+
CONSTRAINT "xai_credential_leases_scope_chk" CHECK (
|
|
245
|
+
("authority_scope" = 'workspace' AND "owner_organization_membership_id" IS NULL)
|
|
246
|
+
OR ("authority_scope" = 'user' AND "owner_organization_membership_id" IS NOT NULL)
|
|
247
|
+
),
|
|
248
|
+
CONSTRAINT "xai_credential_leases_generation_chk" CHECK ("generation" > 0),
|
|
249
|
+
CONSTRAINT "xai_credential_leases_holder_chk" CHECK (
|
|
250
|
+
length(btrim("holder_id")) BETWEEN 1 AND 1024
|
|
251
|
+
)
|
|
252
|
+
);
|
|
253
|
+
CREATE UNIQUE INDEX "xai_credential_leases_workspace_turn_uq"
|
|
254
|
+
ON "xai_credential_leases" ("workspace_id", "turn_id");
|
|
255
|
+
CREATE INDEX "xai_credential_leases_active_credential_idx"
|
|
256
|
+
ON "xai_credential_leases" ("workspace_id", "credential_id", "leased_until");
|
|
257
|
+
CREATE INDEX "xai_credential_leases_expiry_idx"
|
|
258
|
+
ON "xai_credential_leases" ("leased_until");
|
|
259
|
+
|
|
260
|
+
CREATE TABLE "xai_session_account_pins" (
|
|
261
|
+
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
262
|
+
"account_id" uuid NOT NULL REFERENCES "managed_accounts"("id") ON DELETE CASCADE,
|
|
263
|
+
"workspace_id" uuid NOT NULL REFERENCES "workspaces"("id") ON DELETE CASCADE,
|
|
264
|
+
"session_id" uuid NOT NULL,
|
|
265
|
+
"authority_scope" text NOT NULL DEFAULT 'workspace',
|
|
266
|
+
"owner_organization_membership_id" uuid,
|
|
267
|
+
"pinned_credential_id" uuid,
|
|
268
|
+
"pin_source" text,
|
|
269
|
+
"last_credential_id" uuid,
|
|
270
|
+
"version" integer NOT NULL DEFAULT 1,
|
|
271
|
+
"created_at" timestamptz NOT NULL DEFAULT now(),
|
|
272
|
+
"updated_at" timestamptz NOT NULL DEFAULT now(),
|
|
273
|
+
CONSTRAINT "xai_session_account_pins_workspace_account_fk"
|
|
274
|
+
FOREIGN KEY ("workspace_id", "account_id")
|
|
275
|
+
REFERENCES "workspaces"("id", "account_id") ON DELETE CASCADE,
|
|
276
|
+
CONSTRAINT "xai_session_account_pins_session_fk"
|
|
277
|
+
FOREIGN KEY ("workspace_id", "session_id")
|
|
278
|
+
REFERENCES "sessions"("workspace_id", "id") ON DELETE CASCADE,
|
|
279
|
+
CONSTRAINT "xai_session_account_pins_owner_membership_fk"
|
|
280
|
+
FOREIGN KEY ("owner_organization_membership_id", "account_id")
|
|
281
|
+
REFERENCES "organization_memberships"("id", "account_id") ON DELETE RESTRICT,
|
|
282
|
+
CONSTRAINT "xai_session_account_pins_pinned_credential_fk"
|
|
283
|
+
FOREIGN KEY ("workspace_id", "account_id", "pinned_credential_id")
|
|
284
|
+
REFERENCES "xai_subscription_credentials"("workspace_id", "account_id", "id")
|
|
285
|
+
ON DELETE SET NULL ("pinned_credential_id"),
|
|
286
|
+
CONSTRAINT "xai_session_account_pins_last_credential_fk"
|
|
287
|
+
FOREIGN KEY ("workspace_id", "account_id", "last_credential_id")
|
|
288
|
+
REFERENCES "xai_subscription_credentials"("workspace_id", "account_id", "id")
|
|
289
|
+
ON DELETE SET NULL ("last_credential_id"),
|
|
290
|
+
CONSTRAINT "xai_session_account_pins_scope_chk" CHECK (
|
|
291
|
+
("authority_scope" = 'workspace' AND "owner_organization_membership_id" IS NULL)
|
|
292
|
+
OR ("authority_scope" = 'user' AND "owner_organization_membership_id" IS NOT NULL)
|
|
293
|
+
),
|
|
294
|
+
CONSTRAINT "xai_session_account_pins_pin_chk" CHECK (
|
|
295
|
+
("pinned_credential_id" IS NULL AND "pin_source" IS NULL)
|
|
296
|
+
OR ("pinned_credential_id" IS NOT NULL AND "pin_source" IN ('manual', 'policy'))
|
|
297
|
+
),
|
|
298
|
+
CONSTRAINT "xai_session_account_pins_version_chk" CHECK ("version" > 0)
|
|
299
|
+
);
|
|
300
|
+
CREATE UNIQUE INDEX "xai_session_account_pins_workspace_session_uq"
|
|
301
|
+
ON "xai_session_account_pins" (
|
|
302
|
+
"workspace_id", "session_id", "authority_scope",
|
|
303
|
+
"owner_organization_membership_id"
|
|
304
|
+
) NULLS NOT DISTINCT;
|
|
305
|
+
|
|
306
|
+
CREATE TABLE "xai_capacity_waiters" (
|
|
307
|
+
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
308
|
+
"account_id" uuid NOT NULL REFERENCES "managed_accounts"("id") ON DELETE CASCADE,
|
|
309
|
+
"workspace_id" uuid NOT NULL REFERENCES "workspaces"("id") ON DELETE CASCADE,
|
|
310
|
+
"session_id" uuid NOT NULL,
|
|
311
|
+
"goal_id" uuid,
|
|
312
|
+
"goal_version" integer,
|
|
313
|
+
"blocked_turn_id" uuid NOT NULL,
|
|
314
|
+
"blocked_turn_generation" integer NOT NULL,
|
|
315
|
+
"workflow_id" text NOT NULL,
|
|
316
|
+
"authority_scope" text NOT NULL,
|
|
317
|
+
"owner_organization_membership_id" uuid,
|
|
318
|
+
"status" text NOT NULL DEFAULT 'waiting',
|
|
319
|
+
"generation" integer NOT NULL DEFAULT 1,
|
|
320
|
+
"earliest_reset_at" timestamptz,
|
|
321
|
+
"next_check_at" timestamptz NOT NULL,
|
|
322
|
+
"wake_revision" integer NOT NULL DEFAULT 1,
|
|
323
|
+
"observed_wake_revision" integer NOT NULL DEFAULT 0,
|
|
324
|
+
"last_wake_reason" text NOT NULL DEFAULT 'capacity_wait_armed',
|
|
325
|
+
"created_at" timestamptz NOT NULL DEFAULT now(),
|
|
326
|
+
"updated_at" timestamptz NOT NULL DEFAULT now(),
|
|
327
|
+
CONSTRAINT "xai_capacity_waiters_workspace_account_fk"
|
|
328
|
+
FOREIGN KEY ("workspace_id", "account_id")
|
|
329
|
+
REFERENCES "workspaces"("id", "account_id") ON DELETE CASCADE,
|
|
330
|
+
CONSTRAINT "xai_capacity_waiters_session_fk"
|
|
331
|
+
FOREIGN KEY ("workspace_id", "session_id")
|
|
332
|
+
REFERENCES "sessions"("workspace_id", "id") ON DELETE CASCADE,
|
|
333
|
+
CONSTRAINT "xai_capacity_waiters_turn_fk"
|
|
334
|
+
FOREIGN KEY ("workspace_id", "blocked_turn_id")
|
|
335
|
+
REFERENCES "session_turns"("workspace_id", "id") ON DELETE CASCADE,
|
|
336
|
+
CONSTRAINT "xai_capacity_waiters_goal_fk"
|
|
337
|
+
FOREIGN KEY ("workspace_id", "goal_id")
|
|
338
|
+
REFERENCES "session_goals"("workspace_id", "id") ON DELETE CASCADE,
|
|
339
|
+
CONSTRAINT "xai_capacity_waiters_owner_membership_fk"
|
|
340
|
+
FOREIGN KEY ("owner_organization_membership_id", "account_id")
|
|
341
|
+
REFERENCES "organization_memberships"("id", "account_id") ON DELETE RESTRICT,
|
|
342
|
+
CONSTRAINT "xai_capacity_waiters_scope_chk" CHECK (
|
|
343
|
+
("authority_scope" = 'workspace' AND "owner_organization_membership_id" IS NULL)
|
|
344
|
+
OR ("authority_scope" = 'user' AND "owner_organization_membership_id" IS NOT NULL)
|
|
345
|
+
),
|
|
346
|
+
CONSTRAINT "xai_capacity_waiters_status_chk" CHECK (
|
|
347
|
+
"status" IN ('waiting', 'resumed', 'superseded')
|
|
348
|
+
),
|
|
349
|
+
CONSTRAINT "xai_capacity_waiters_counters_chk" CHECK (
|
|
350
|
+
"blocked_turn_generation" >= 0 AND "generation" > 0
|
|
351
|
+
AND "wake_revision" > 0 AND "observed_wake_revision" >= 0
|
|
352
|
+
AND "observed_wake_revision" <= "wake_revision"
|
|
353
|
+
),
|
|
354
|
+
CONSTRAINT "xai_capacity_waiters_goal_fence_chk" CHECK (
|
|
355
|
+
("goal_id" IS NULL AND "goal_version" IS NULL)
|
|
356
|
+
OR ("goal_id" IS NOT NULL AND "goal_version" > 0)
|
|
357
|
+
),
|
|
358
|
+
CONSTRAINT "xai_capacity_waiters_workflow_chk" CHECK (
|
|
359
|
+
length(btrim("workflow_id")) BETWEEN 1 AND 1024
|
|
360
|
+
AND length(btrim("last_wake_reason")) BETWEEN 1 AND 256
|
|
361
|
+
)
|
|
362
|
+
);
|
|
363
|
+
CREATE UNIQUE INDEX "xai_capacity_waiters_workspace_session_uq"
|
|
364
|
+
ON "xai_capacity_waiters" (
|
|
365
|
+
"workspace_id", "session_id", "authority_scope",
|
|
366
|
+
"owner_organization_membership_id"
|
|
367
|
+
) NULLS NOT DISTINCT;
|
|
368
|
+
CREATE INDEX "xai_capacity_waiters_pending_idx"
|
|
369
|
+
ON "xai_capacity_waiters" ("workspace_id", "status", "next_check_at");
|
|
370
|
+
CREATE INDEX "xai_capacity_waiters_wake_repair_idx"
|
|
371
|
+
ON "xai_capacity_waiters" ("status", "wake_revision", "observed_wake_revision");
|
|
372
|
+
|
|
373
|
+
DO $xai_authority_functions$
|
|
374
|
+
DECLARE
|
|
375
|
+
data_schema text := current_schema();
|
|
376
|
+
BEGIN
|
|
377
|
+
EXECUTE format($ddl$
|
|
378
|
+
CREATE OR REPLACE FUNCTION %1$I.xai_provider_account_authority_snapshot_v1_valid(
|
|
379
|
+
snapshot jsonb
|
|
380
|
+
) RETURNS boolean
|
|
381
|
+
LANGUAGE sql IMMUTABLE STRICT
|
|
382
|
+
AS $body$
|
|
383
|
+
SELECT snapshot = '{"version":1,"scope":"workspace"}'::jsonb
|
|
384
|
+
OR (
|
|
385
|
+
jsonb_typeof(snapshot) = 'object'
|
|
386
|
+
AND (SELECT count(*) FROM jsonb_object_keys(snapshot)) = 3
|
|
387
|
+
AND snapshot ?& ARRAY['version', 'scope', 'authorityGeneration']
|
|
388
|
+
AND snapshot -> 'version' = '1'::jsonb
|
|
389
|
+
AND snapshot ->> 'scope' = 'user'
|
|
390
|
+
AND jsonb_typeof(snapshot -> 'authorityGeneration') = 'number'
|
|
391
|
+
AND snapshot ->> 'authorityGeneration' ~ '^[1-9][0-9]*$'
|
|
392
|
+
AND (snapshot ->> 'authorityGeneration')::numeric <= 9007199254740991
|
|
393
|
+
)
|
|
394
|
+
$body$;
|
|
395
|
+
$ddl$, data_schema);
|
|
396
|
+
|
|
397
|
+
EXECUTE format($ddl$
|
|
398
|
+
CREATE OR REPLACE FUNCTION %1$I.xai_subscription_authority_live(
|
|
399
|
+
p_account_id uuid,
|
|
400
|
+
p_workspace_id uuid,
|
|
401
|
+
p_subject_id text,
|
|
402
|
+
p_credential_id uuid,
|
|
403
|
+
p_authority_scope text,
|
|
404
|
+
p_owner_membership_id uuid,
|
|
405
|
+
p_authority_id uuid,
|
|
406
|
+
p_authority_generation bigint
|
|
407
|
+
) RETURNS boolean
|
|
408
|
+
LANGUAGE plpgsql SECURITY DEFINER
|
|
409
|
+
SET search_path = %1$I, pg_catalog
|
|
410
|
+
AS $body$
|
|
411
|
+
DECLARE exact_count integer;
|
|
412
|
+
BEGIN
|
|
413
|
+
IF p_account_id IS DISTINCT FROM NULLIF(current_setting('opengeni.account_id', true), '')::uuid
|
|
414
|
+
OR p_workspace_id IS DISTINCT FROM NULLIF(current_setting('opengeni.workspace_id', true), '')::uuid
|
|
415
|
+
OR p_subject_id IS DISTINCT FROM NULLIF(current_setting('opengeni.subject_id', true), '')
|
|
416
|
+
THEN RETURN false; END IF;
|
|
417
|
+
IF p_authority_scope = 'workspace' THEN
|
|
418
|
+
RETURN p_owner_membership_id IS NULL
|
|
419
|
+
AND p_authority_id IS NULL
|
|
420
|
+
AND p_authority_generation IS NULL;
|
|
421
|
+
END IF;
|
|
422
|
+
IF p_authority_scope <> 'user' OR p_subject_id IS NULL THEN RETURN false; END IF;
|
|
423
|
+
INSERT INTO opengeni_private.xai_subscription_runtime_capabilities (
|
|
424
|
+
backend_pid, transaction_id, capability_kind
|
|
425
|
+
) VALUES (pg_catalog.pg_backend_pid(), pg_catalog.pg_current_xact_id(), 'resolve')
|
|
426
|
+
ON CONFLICT DO NOTHING;
|
|
427
|
+
SELECT count(*) INTO exact_count
|
|
428
|
+
FROM organization_memberships membership
|
|
429
|
+
INNER JOIN workspace_memberships workspace_grant
|
|
430
|
+
ON workspace_grant.account_id = membership.account_id
|
|
431
|
+
AND workspace_grant.subject_id = membership.subject_id
|
|
432
|
+
AND workspace_grant.workspace_id = p_workspace_id
|
|
433
|
+
INNER JOIN organization_user_resource_authorities authority
|
|
434
|
+
ON authority.account_id = membership.account_id
|
|
435
|
+
AND authority.organization_membership_id = membership.id
|
|
436
|
+
WHERE membership.id = p_owner_membership_id
|
|
437
|
+
AND membership.account_id = p_account_id
|
|
438
|
+
AND membership.subject_id = p_subject_id
|
|
439
|
+
AND membership.status = 'active'
|
|
440
|
+
AND membership.revoked_at IS NULL
|
|
441
|
+
AND authority.id = p_authority_id
|
|
442
|
+
AND authority.resource_kind = 'xai_subscription'
|
|
443
|
+
AND authority.resource_id = p_credential_id
|
|
444
|
+
AND authority.generation = p_authority_generation
|
|
445
|
+
AND authority.status = 'active'
|
|
446
|
+
AND authority.revoked_at IS NULL;
|
|
447
|
+
DELETE FROM opengeni_private.xai_subscription_runtime_capabilities
|
|
448
|
+
WHERE backend_pid = pg_catalog.pg_backend_pid()
|
|
449
|
+
AND transaction_id = pg_catalog.pg_current_xact_id_if_assigned()
|
|
450
|
+
AND capability_kind = 'resolve';
|
|
451
|
+
RETURN exact_count = 1;
|
|
452
|
+
EXCEPTION WHEN OTHERS THEN
|
|
453
|
+
DELETE FROM opengeni_private.xai_subscription_runtime_capabilities
|
|
454
|
+
WHERE backend_pid = pg_catalog.pg_backend_pid()
|
|
455
|
+
AND transaction_id = pg_catalog.pg_current_xact_id_if_assigned()
|
|
456
|
+
AND capability_kind = 'resolve';
|
|
457
|
+
RAISE;
|
|
458
|
+
END
|
|
459
|
+
$body$;
|
|
460
|
+
$ddl$, data_schema);
|
|
461
|
+
|
|
462
|
+
EXECUTE format($ddl$
|
|
463
|
+
CREATE OR REPLACE FUNCTION %1$I.xai_subscription_pool_visible(
|
|
464
|
+
p_account_id uuid,
|
|
465
|
+
p_workspace_id uuid,
|
|
466
|
+
p_subject_id text,
|
|
467
|
+
p_authority_scope text,
|
|
468
|
+
p_owner_membership_id uuid
|
|
469
|
+
) RETURNS boolean
|
|
470
|
+
LANGUAGE plpgsql SECURITY DEFINER
|
|
471
|
+
SET search_path = %1$I, pg_catalog
|
|
472
|
+
AS $body$
|
|
473
|
+
DECLARE exact_count integer;
|
|
474
|
+
BEGIN
|
|
475
|
+
IF p_account_id IS DISTINCT FROM NULLIF(current_setting('opengeni.account_id', true), '')::uuid
|
|
476
|
+
OR p_workspace_id IS DISTINCT FROM NULLIF(current_setting('opengeni.workspace_id', true), '')::uuid
|
|
477
|
+
OR p_subject_id IS DISTINCT FROM NULLIF(current_setting('opengeni.subject_id', true), '')
|
|
478
|
+
THEN RETURN false; END IF;
|
|
479
|
+
IF p_authority_scope = 'workspace' THEN
|
|
480
|
+
RETURN p_owner_membership_id IS NULL;
|
|
481
|
+
END IF;
|
|
482
|
+
IF p_authority_scope <> 'user' OR p_subject_id IS NULL THEN RETURN false; END IF;
|
|
483
|
+
INSERT INTO opengeni_private.xai_subscription_runtime_capabilities (
|
|
484
|
+
backend_pid, transaction_id, capability_kind
|
|
485
|
+
) VALUES (pg_catalog.pg_backend_pid(), pg_catalog.pg_current_xact_id(), 'resolve')
|
|
486
|
+
ON CONFLICT DO NOTHING;
|
|
487
|
+
SELECT count(*) INTO exact_count
|
|
488
|
+
FROM organization_memberships membership
|
|
489
|
+
INNER JOIN workspace_memberships workspace_grant
|
|
490
|
+
ON workspace_grant.account_id = membership.account_id
|
|
491
|
+
AND workspace_grant.subject_id = membership.subject_id
|
|
492
|
+
AND workspace_grant.workspace_id = p_workspace_id
|
|
493
|
+
WHERE membership.id = p_owner_membership_id
|
|
494
|
+
AND membership.account_id = p_account_id
|
|
495
|
+
AND membership.subject_id = p_subject_id
|
|
496
|
+
AND membership.status = 'active'
|
|
497
|
+
AND membership.revoked_at IS NULL;
|
|
498
|
+
DELETE FROM opengeni_private.xai_subscription_runtime_capabilities
|
|
499
|
+
WHERE backend_pid = pg_catalog.pg_backend_pid()
|
|
500
|
+
AND transaction_id = pg_catalog.pg_current_xact_id_if_assigned()
|
|
501
|
+
AND capability_kind = 'resolve';
|
|
502
|
+
RETURN exact_count = 1;
|
|
503
|
+
EXCEPTION WHEN OTHERS THEN
|
|
504
|
+
DELETE FROM opengeni_private.xai_subscription_runtime_capabilities
|
|
505
|
+
WHERE backend_pid = pg_catalog.pg_backend_pid()
|
|
506
|
+
AND transaction_id = pg_catalog.pg_current_xact_id_if_assigned()
|
|
507
|
+
AND capability_kind = 'resolve';
|
|
508
|
+
RAISE;
|
|
509
|
+
END
|
|
510
|
+
$body$;
|
|
511
|
+
$ddl$, data_schema);
|
|
512
|
+
|
|
513
|
+
EXECUTE format($ddl$
|
|
514
|
+
CREATE OR REPLACE FUNCTION %1$I.create_xai_subscription_credential(
|
|
515
|
+
p_account_id uuid,
|
|
516
|
+
p_workspace_id uuid,
|
|
517
|
+
p_subject_id text,
|
|
518
|
+
p_authority_scope text,
|
|
519
|
+
p_credential_encrypted text,
|
|
520
|
+
p_provider_account_id text,
|
|
521
|
+
p_label text,
|
|
522
|
+
p_account_email text,
|
|
523
|
+
p_plan_type text,
|
|
524
|
+
p_expires_at timestamptz
|
|
525
|
+
) RETURNS TABLE (credential_id uuid, authority_generation bigint)
|
|
526
|
+
LANGUAGE plpgsql SECURITY DEFINER
|
|
527
|
+
SET search_path = %1$I, pg_catalog
|
|
528
|
+
AS $body$
|
|
529
|
+
DECLARE
|
|
530
|
+
membership_row record;
|
|
531
|
+
created_credential_id uuid := gen_random_uuid();
|
|
532
|
+
authority_row record;
|
|
533
|
+
BEGIN
|
|
534
|
+
IF p_account_id IS DISTINCT FROM NULLIF(current_setting('opengeni.account_id', true), '')::uuid
|
|
535
|
+
OR p_workspace_id IS DISTINCT FROM NULLIF(current_setting('opengeni.workspace_id', true), '')::uuid
|
|
536
|
+
OR p_subject_id IS DISTINCT FROM NULLIF(current_setting('opengeni.subject_id', true), '')
|
|
537
|
+
OR p_authority_scope NOT IN ('workspace', 'user')
|
|
538
|
+
OR p_credential_encrypted IS NULL
|
|
539
|
+
OR length(p_credential_encrypted) < 1
|
|
540
|
+
THEN
|
|
541
|
+
RAISE EXCEPTION 'xAI credential lifecycle authority denied' USING ERRCODE = '42501';
|
|
542
|
+
END IF;
|
|
543
|
+
IF NOT opengeni_private.workspace_rls_visible(p_account_id, p_workspace_id) THEN
|
|
544
|
+
RAISE EXCEPTION 'xAI credential workspace authority denied' USING ERRCODE = '42501';
|
|
545
|
+
END IF;
|
|
546
|
+
IF NOT EXISTS (
|
|
547
|
+
SELECT 1
|
|
548
|
+
FROM workspace_memberships workspace_grant
|
|
549
|
+
WHERE workspace_grant.account_id = p_account_id
|
|
550
|
+
AND workspace_grant.workspace_id = p_workspace_id
|
|
551
|
+
AND workspace_grant.subject_id = p_subject_id
|
|
552
|
+
) THEN
|
|
553
|
+
RAISE EXCEPTION 'active workspace grant required' USING ERRCODE = '42501';
|
|
554
|
+
END IF;
|
|
555
|
+
|
|
556
|
+
IF p_authority_scope = 'workspace' THEN
|
|
557
|
+
INSERT INTO xai_subscription_credentials (
|
|
558
|
+
id, account_id, workspace_id, credential_encrypted,
|
|
559
|
+
provider_account_id, label, account_email, plan_type, expires_at,
|
|
560
|
+
authority_scope, connected_by_subject_id
|
|
561
|
+
) VALUES (
|
|
562
|
+
created_credential_id, p_account_id, p_workspace_id, p_credential_encrypted,
|
|
563
|
+
p_provider_account_id, p_label, p_account_email, p_plan_type, p_expires_at,
|
|
564
|
+
'workspace', p_subject_id
|
|
565
|
+
);
|
|
566
|
+
credential_id := created_credential_id;
|
|
567
|
+
authority_generation := NULL;
|
|
568
|
+
RETURN NEXT;
|
|
569
|
+
RETURN;
|
|
570
|
+
END IF;
|
|
571
|
+
|
|
572
|
+
INSERT INTO opengeni_private.xai_subscription_runtime_capabilities (
|
|
573
|
+
backend_pid, transaction_id, capability_kind
|
|
574
|
+
) VALUES (pg_catalog.pg_backend_pid(), pg_catalog.pg_current_xact_id(), 'lifecycle');
|
|
575
|
+
SELECT membership.id INTO membership_row
|
|
576
|
+
FROM organization_memberships membership
|
|
577
|
+
INNER JOIN workspace_memberships workspace_grant
|
|
578
|
+
ON workspace_grant.account_id = membership.account_id
|
|
579
|
+
AND workspace_grant.subject_id = membership.subject_id
|
|
580
|
+
AND workspace_grant.workspace_id = p_workspace_id
|
|
581
|
+
WHERE membership.account_id = p_account_id
|
|
582
|
+
AND membership.subject_id = p_subject_id
|
|
583
|
+
AND membership.status = 'active'
|
|
584
|
+
AND membership.revoked_at IS NULL
|
|
585
|
+
FOR UPDATE OF membership;
|
|
586
|
+
IF membership_row.id IS NULL THEN
|
|
587
|
+
RAISE EXCEPTION 'active organization membership and workspace grant required'
|
|
588
|
+
USING ERRCODE = '42501';
|
|
589
|
+
END IF;
|
|
590
|
+
|
|
591
|
+
INSERT INTO organization_user_resource_authorities (
|
|
592
|
+
account_id, organization_membership_id, resource_kind, resource_id,
|
|
593
|
+
origin_workspace_id
|
|
594
|
+
) VALUES (
|
|
595
|
+
p_account_id, membership_row.id, 'xai_subscription', created_credential_id,
|
|
596
|
+
p_workspace_id
|
|
597
|
+
) RETURNING id, generation INTO authority_row;
|
|
598
|
+
|
|
599
|
+
INSERT INTO xai_subscription_credentials (
|
|
600
|
+
id, account_id, workspace_id, credential_encrypted,
|
|
601
|
+
provider_account_id, label, account_email, plan_type, expires_at,
|
|
602
|
+
authority_scope, owner_organization_membership_id,
|
|
603
|
+
organization_user_resource_authority_id, organization_user_resource_kind,
|
|
604
|
+
organization_user_resource_authority_generation, connected_by_subject_id
|
|
605
|
+
) VALUES (
|
|
606
|
+
created_credential_id, p_account_id, p_workspace_id, p_credential_encrypted,
|
|
607
|
+
p_provider_account_id, p_label, p_account_email, p_plan_type, p_expires_at,
|
|
608
|
+
'user', membership_row.id, authority_row.id, 'xai_subscription',
|
|
609
|
+
authority_row.generation, p_subject_id
|
|
610
|
+
);
|
|
611
|
+
DELETE FROM opengeni_private.xai_subscription_runtime_capabilities
|
|
612
|
+
WHERE backend_pid = pg_catalog.pg_backend_pid()
|
|
613
|
+
AND transaction_id = pg_catalog.pg_current_xact_id_if_assigned()
|
|
614
|
+
AND capability_kind = 'lifecycle';
|
|
615
|
+
credential_id := created_credential_id;
|
|
616
|
+
authority_generation := authority_row.generation;
|
|
617
|
+
RETURN NEXT;
|
|
618
|
+
EXCEPTION WHEN OTHERS THEN
|
|
619
|
+
DELETE FROM opengeni_private.xai_subscription_runtime_capabilities
|
|
620
|
+
WHERE backend_pid = pg_catalog.pg_backend_pid()
|
|
621
|
+
AND transaction_id = pg_catalog.pg_current_xact_id_if_assigned()
|
|
622
|
+
AND capability_kind = 'lifecycle';
|
|
623
|
+
RAISE;
|
|
624
|
+
END
|
|
625
|
+
$body$;
|
|
626
|
+
$ddl$, data_schema);
|
|
627
|
+
|
|
628
|
+
EXECUTE format($ddl$
|
|
629
|
+
CREATE OR REPLACE FUNCTION %1$I.resolve_xai_authority_pool(
|
|
630
|
+
p_account_id uuid,
|
|
631
|
+
p_workspace_id uuid,
|
|
632
|
+
p_subject_id text,
|
|
633
|
+
p_snapshot jsonb
|
|
634
|
+
) RETURNS TABLE (organization_membership_id uuid)
|
|
635
|
+
LANGUAGE plpgsql SECURITY DEFINER
|
|
636
|
+
SET search_path = %1$I, pg_catalog
|
|
637
|
+
AS $body$
|
|
638
|
+
DECLARE snapshot_generation bigint;
|
|
639
|
+
BEGIN
|
|
640
|
+
IF NOT xai_provider_account_authority_snapshot_v1_valid(p_snapshot)
|
|
641
|
+
OR p_snapshot ->> 'scope' <> 'user'
|
|
642
|
+
OR p_account_id IS DISTINCT FROM NULLIF(current_setting('opengeni.account_id', true), '')::uuid
|
|
643
|
+
OR p_workspace_id IS DISTINCT FROM NULLIF(current_setting('opengeni.workspace_id', true), '')::uuid
|
|
644
|
+
OR p_subject_id IS DISTINCT FROM NULLIF(current_setting('opengeni.subject_id', true), '')
|
|
645
|
+
THEN RETURN; END IF;
|
|
646
|
+
snapshot_generation := (p_snapshot ->> 'authorityGeneration')::bigint;
|
|
647
|
+
INSERT INTO opengeni_private.xai_subscription_runtime_capabilities (
|
|
648
|
+
backend_pid, transaction_id, capability_kind
|
|
649
|
+
) VALUES (pg_catalog.pg_backend_pid(), pg_catalog.pg_current_xact_id(), 'resolve')
|
|
650
|
+
ON CONFLICT DO NOTHING;
|
|
651
|
+
RETURN QUERY
|
|
652
|
+
SELECT membership.id
|
|
653
|
+
FROM organization_memberships membership
|
|
654
|
+
INNER JOIN workspace_memberships workspace_grant
|
|
655
|
+
ON workspace_grant.account_id = membership.account_id
|
|
656
|
+
AND workspace_grant.subject_id = membership.subject_id
|
|
657
|
+
AND workspace_grant.workspace_id = p_workspace_id
|
|
658
|
+
WHERE membership.account_id = p_account_id
|
|
659
|
+
AND membership.subject_id = p_subject_id
|
|
660
|
+
AND membership.status = 'active'
|
|
661
|
+
AND membership.revoked_at IS NULL
|
|
662
|
+
AND EXISTS (
|
|
663
|
+
SELECT 1 FROM organization_user_resource_authorities authority
|
|
664
|
+
WHERE authority.account_id = membership.account_id
|
|
665
|
+
AND authority.organization_membership_id = membership.id
|
|
666
|
+
AND authority.resource_kind = 'xai_subscription'
|
|
667
|
+
AND authority.generation = snapshot_generation
|
|
668
|
+
AND authority.status = 'active'
|
|
669
|
+
AND authority.revoked_at IS NULL
|
|
670
|
+
);
|
|
671
|
+
DELETE FROM opengeni_private.xai_subscription_runtime_capabilities
|
|
672
|
+
WHERE backend_pid = pg_catalog.pg_backend_pid()
|
|
673
|
+
AND transaction_id = pg_catalog.pg_current_xact_id_if_assigned()
|
|
674
|
+
AND capability_kind = 'resolve';
|
|
675
|
+
EXCEPTION WHEN OTHERS THEN
|
|
676
|
+
DELETE FROM opengeni_private.xai_subscription_runtime_capabilities
|
|
677
|
+
WHERE backend_pid = pg_catalog.pg_backend_pid()
|
|
678
|
+
AND transaction_id = pg_catalog.pg_current_xact_id_if_assigned()
|
|
679
|
+
AND capability_kind = 'resolve';
|
|
680
|
+
RAISE;
|
|
681
|
+
END
|
|
682
|
+
$body$;
|
|
683
|
+
$ddl$, data_schema);
|
|
684
|
+
|
|
685
|
+
EXECUTE format($ddl$
|
|
686
|
+
CREATE OR REPLACE FUNCTION %1$I.revalidate_xai_subscription_authority(
|
|
687
|
+
p_workspace_id uuid,
|
|
688
|
+
p_subject_id text,
|
|
689
|
+
p_credential_id uuid,
|
|
690
|
+
p_snapshot jsonb
|
|
691
|
+
) RETURNS TABLE (id uuid)
|
|
692
|
+
LANGUAGE sql SECURITY DEFINER
|
|
693
|
+
SET search_path = %1$I, pg_catalog
|
|
694
|
+
AS $body$
|
|
695
|
+
SELECT credential.id
|
|
696
|
+
FROM xai_subscription_credentials credential
|
|
697
|
+
WHERE credential.workspace_id = p_workspace_id
|
|
698
|
+
AND credential.id = p_credential_id
|
|
699
|
+
AND credential.status = 'active'
|
|
700
|
+
AND credential.account_id = NULLIF(current_setting('opengeni.account_id', true), '')::uuid
|
|
701
|
+
AND p_workspace_id = NULLIF(current_setting('opengeni.workspace_id', true), '')::uuid
|
|
702
|
+
AND p_subject_id = NULLIF(current_setting('opengeni.subject_id', true), '')
|
|
703
|
+
AND xai_provider_account_authority_snapshot_v1_valid(p_snapshot)
|
|
704
|
+
AND (
|
|
705
|
+
(p_snapshot ->> 'scope' = 'workspace'
|
|
706
|
+
AND credential.authority_scope = 'workspace')
|
|
707
|
+
OR
|
|
708
|
+
(p_snapshot ->> 'scope' = 'user'
|
|
709
|
+
AND credential.authority_scope = 'user'
|
|
710
|
+
AND credential.organization_user_resource_authority_generation =
|
|
711
|
+
(p_snapshot ->> 'authorityGeneration')::bigint
|
|
712
|
+
AND xai_subscription_authority_live(
|
|
713
|
+
credential.account_id, credential.workspace_id, p_subject_id,
|
|
714
|
+
credential.id, credential.authority_scope,
|
|
715
|
+
credential.owner_organization_membership_id,
|
|
716
|
+
credential.organization_user_resource_authority_id,
|
|
717
|
+
credential.organization_user_resource_authority_generation
|
|
718
|
+
))
|
|
719
|
+
)
|
|
720
|
+
$body$;
|
|
721
|
+
$ddl$, data_schema);
|
|
722
|
+
|
|
723
|
+
EXECUTE format($ddl$
|
|
724
|
+
CREATE OR REPLACE FUNCTION %1$I.disconnect_xai_subscription_credential(
|
|
725
|
+
p_account_id uuid,
|
|
726
|
+
p_workspace_id uuid,
|
|
727
|
+
p_subject_id text,
|
|
728
|
+
p_credential_id uuid,
|
|
729
|
+
p_snapshot jsonb
|
|
730
|
+
) RETURNS boolean
|
|
731
|
+
LANGUAGE plpgsql SECURITY DEFINER
|
|
732
|
+
SET search_path = %1$I, pg_catalog
|
|
733
|
+
AS $body$
|
|
734
|
+
DECLARE
|
|
735
|
+
credential_row record;
|
|
736
|
+
BEGIN
|
|
737
|
+
IF p_account_id IS DISTINCT FROM NULLIF(current_setting('opengeni.account_id', true), '')::uuid
|
|
738
|
+
OR p_workspace_id IS DISTINCT FROM NULLIF(current_setting('opengeni.workspace_id', true), '')::uuid
|
|
739
|
+
OR p_subject_id IS DISTINCT FROM NULLIF(current_setting('opengeni.subject_id', true), '')
|
|
740
|
+
THEN
|
|
741
|
+
RAISE EXCEPTION 'xAI credential lifecycle authority denied' USING ERRCODE = '42501';
|
|
742
|
+
END IF;
|
|
743
|
+
|
|
744
|
+
SELECT credential.* INTO credential_row
|
|
745
|
+
FROM revalidate_xai_subscription_authority(
|
|
746
|
+
p_workspace_id, p_subject_id, p_credential_id, p_snapshot
|
|
747
|
+
) authorized
|
|
748
|
+
INNER JOIN xai_subscription_credentials credential ON credential.id = authorized.id
|
|
749
|
+
FOR UPDATE OF credential;
|
|
750
|
+
IF credential_row.id IS NULL THEN RETURN false; END IF;
|
|
751
|
+
|
|
752
|
+
INSERT INTO opengeni_private.xai_subscription_runtime_capabilities (
|
|
753
|
+
backend_pid, transaction_id, capability_kind
|
|
754
|
+
) VALUES (pg_catalog.pg_backend_pid(), pg_catalog.pg_current_xact_id(), 'lifecycle')
|
|
755
|
+
ON CONFLICT DO NOTHING;
|
|
756
|
+
|
|
757
|
+
DELETE FROM xai_subscription_credentials WHERE id = credential_row.id;
|
|
758
|
+
IF credential_row.authority_scope = 'user' THEN
|
|
759
|
+
UPDATE organization_user_resource_authorities
|
|
760
|
+
SET status = 'revoked', revoked_at = now(), updated_at = now()
|
|
761
|
+
WHERE id = credential_row.organization_user_resource_authority_id
|
|
762
|
+
AND account_id = credential_row.account_id
|
|
763
|
+
AND organization_membership_id = credential_row.owner_organization_membership_id
|
|
764
|
+
AND resource_kind = 'xai_subscription'
|
|
765
|
+
AND resource_id = credential_row.id
|
|
766
|
+
AND generation = credential_row.organization_user_resource_authority_generation;
|
|
767
|
+
END IF;
|
|
768
|
+
|
|
769
|
+
DELETE FROM opengeni_private.xai_subscription_runtime_capabilities
|
|
770
|
+
WHERE backend_pid = pg_catalog.pg_backend_pid()
|
|
771
|
+
AND transaction_id = pg_catalog.pg_current_xact_id_if_assigned()
|
|
772
|
+
AND capability_kind = 'lifecycle';
|
|
773
|
+
RETURN true;
|
|
774
|
+
EXCEPTION WHEN OTHERS THEN
|
|
775
|
+
DELETE FROM opengeni_private.xai_subscription_runtime_capabilities
|
|
776
|
+
WHERE backend_pid = pg_catalog.pg_backend_pid()
|
|
777
|
+
AND transaction_id = pg_catalog.pg_current_xact_id_if_assigned()
|
|
778
|
+
AND capability_kind = 'lifecycle';
|
|
779
|
+
RAISE;
|
|
780
|
+
END
|
|
781
|
+
$body$;
|
|
782
|
+
$ddl$, data_schema);
|
|
783
|
+
END
|
|
784
|
+
$xai_authority_functions$;
|
|
785
|
+
|
|
786
|
+
REVOKE ALL ON FUNCTION xai_provider_account_authority_snapshot_v1_valid(jsonb) FROM PUBLIC;
|
|
787
|
+
REVOKE ALL ON FUNCTION xai_subscription_authority_live(
|
|
788
|
+
uuid, uuid, text, uuid, text, uuid, uuid, bigint
|
|
789
|
+
) FROM PUBLIC;
|
|
790
|
+
REVOKE ALL ON FUNCTION xai_subscription_pool_visible(uuid, uuid, text, text, uuid)
|
|
791
|
+
FROM PUBLIC;
|
|
792
|
+
|
|
793
|
+
-- Exact-subject RLS for user pools. Workspace scope preserves the default
|
|
794
|
+
-- shared behavior for any caller with the ordinary workspace grant.
|
|
795
|
+
DO $xai_rls$
|
|
796
|
+
DECLARE
|
|
797
|
+
data_schema text := current_schema();
|
|
798
|
+
table_name text;
|
|
799
|
+
policy_expression text;
|
|
800
|
+
BEGIN
|
|
801
|
+
ALTER TABLE "xai_subscription_credentials" ENABLE ROW LEVEL SECURITY;
|
|
802
|
+
ALTER TABLE "xai_subscription_credentials" FORCE ROW LEVEL SECURITY;
|
|
803
|
+
ALTER TABLE "xai_rotation_settings" ENABLE ROW LEVEL SECURITY;
|
|
804
|
+
ALTER TABLE "xai_rotation_settings" FORCE ROW LEVEL SECURITY;
|
|
805
|
+
ALTER TABLE "xai_credential_leases" ENABLE ROW LEVEL SECURITY;
|
|
806
|
+
ALTER TABLE "xai_credential_leases" FORCE ROW LEVEL SECURITY;
|
|
807
|
+
ALTER TABLE "xai_session_account_pins" ENABLE ROW LEVEL SECURITY;
|
|
808
|
+
ALTER TABLE "xai_session_account_pins" FORCE ROW LEVEL SECURITY;
|
|
809
|
+
ALTER TABLE "xai_capacity_waiters" ENABLE ROW LEVEL SECURITY;
|
|
810
|
+
ALTER TABLE "xai_capacity_waiters" FORCE ROW LEVEL SECURITY;
|
|
811
|
+
|
|
812
|
+
EXECUTE format($policy$
|
|
813
|
+
CREATE POLICY xai_subscription_scope ON %1$I.xai_subscription_credentials
|
|
814
|
+
USING (
|
|
815
|
+
opengeni_private.workspace_rls_visible(account_id, workspace_id)
|
|
816
|
+
AND (
|
|
817
|
+
authority_scope = 'workspace'
|
|
818
|
+
OR %1$I.xai_subscription_authority_live(
|
|
819
|
+
account_id, workspace_id,
|
|
820
|
+
NULLIF(current_setting('opengeni.subject_id', true), ''),
|
|
821
|
+
id, authority_scope, owner_organization_membership_id,
|
|
822
|
+
organization_user_resource_authority_id,
|
|
823
|
+
organization_user_resource_authority_generation
|
|
824
|
+
)
|
|
825
|
+
)
|
|
826
|
+
)
|
|
827
|
+
WITH CHECK (
|
|
828
|
+
opengeni_private.workspace_rls_visible(account_id, workspace_id)
|
|
829
|
+
AND (
|
|
830
|
+
authority_scope = 'workspace'
|
|
831
|
+
OR %1$I.xai_subscription_authority_live(
|
|
832
|
+
account_id, workspace_id,
|
|
833
|
+
NULLIF(current_setting('opengeni.subject_id', true), ''),
|
|
834
|
+
id, authority_scope, owner_organization_membership_id,
|
|
835
|
+
organization_user_resource_authority_id,
|
|
836
|
+
organization_user_resource_authority_generation
|
|
837
|
+
)
|
|
838
|
+
)
|
|
839
|
+
)
|
|
840
|
+
$policy$, data_schema);
|
|
841
|
+
|
|
842
|
+
FOREACH table_name IN ARRAY ARRAY[
|
|
843
|
+
'xai_rotation_settings', 'xai_credential_leases',
|
|
844
|
+
'xai_session_account_pins', 'xai_capacity_waiters'
|
|
845
|
+
] LOOP
|
|
846
|
+
EXECUTE format($policy$
|
|
847
|
+
CREATE POLICY xai_subscription_pool_scope ON %1$I.%2$I
|
|
848
|
+
USING (
|
|
849
|
+
opengeni_private.workspace_rls_visible(account_id, workspace_id)
|
|
850
|
+
AND %1$I.xai_subscription_pool_visible(
|
|
851
|
+
account_id, workspace_id,
|
|
852
|
+
NULLIF(current_setting('opengeni.subject_id', true), ''),
|
|
853
|
+
authority_scope, owner_organization_membership_id
|
|
854
|
+
)
|
|
855
|
+
)
|
|
856
|
+
WITH CHECK (
|
|
857
|
+
opengeni_private.workspace_rls_visible(account_id, workspace_id)
|
|
858
|
+
AND %1$I.xai_subscription_pool_visible(
|
|
859
|
+
account_id, workspace_id,
|
|
860
|
+
NULLIF(current_setting('opengeni.subject_id', true), ''),
|
|
861
|
+
authority_scope, owner_organization_membership_id
|
|
862
|
+
)
|
|
863
|
+
)
|
|
864
|
+
$policy$, data_schema, table_name);
|
|
865
|
+
END LOOP;
|
|
866
|
+
END
|
|
867
|
+
$xai_rls$;
|
|
868
|
+
|
|
869
|
+
DO $xai_immutability$
|
|
870
|
+
DECLARE data_schema text := current_schema();
|
|
871
|
+
BEGIN
|
|
872
|
+
EXECUTE format($ddl$
|
|
873
|
+
CREATE OR REPLACE FUNCTION %1$I.prevent_xai_authority_mutation()
|
|
874
|
+
RETURNS trigger LANGUAGE plpgsql AS $body$
|
|
875
|
+
BEGIN
|
|
876
|
+
IF NEW.authority_scope IS DISTINCT FROM OLD.authority_scope
|
|
877
|
+
OR NEW.owner_organization_membership_id
|
|
878
|
+
IS DISTINCT FROM OLD.owner_organization_membership_id
|
|
879
|
+
OR NEW.organization_user_resource_authority_id
|
|
880
|
+
IS DISTINCT FROM OLD.organization_user_resource_authority_id
|
|
881
|
+
OR NEW.organization_user_resource_kind
|
|
882
|
+
IS DISTINCT FROM OLD.organization_user_resource_kind
|
|
883
|
+
OR NEW.organization_user_resource_authority_generation
|
|
884
|
+
IS DISTINCT FROM OLD.organization_user_resource_authority_generation
|
|
885
|
+
THEN
|
|
886
|
+
RAISE EXCEPTION 'xAI credential authority is immutable' USING ERRCODE = '23514';
|
|
887
|
+
END IF;
|
|
888
|
+
RETURN NEW;
|
|
889
|
+
END
|
|
890
|
+
$body$;
|
|
891
|
+
$ddl$, data_schema);
|
|
892
|
+
EXECUTE format($ddl$
|
|
893
|
+
CREATE TRIGGER xai_subscription_credentials_authority_immutable_trg
|
|
894
|
+
BEFORE UPDATE OF authority_scope, owner_organization_membership_id,
|
|
895
|
+
organization_user_resource_authority_id, organization_user_resource_kind,
|
|
896
|
+
organization_user_resource_authority_generation
|
|
897
|
+
ON %1$I.xai_subscription_credentials
|
|
898
|
+
FOR EACH ROW EXECUTE FUNCTION %1$I.prevent_xai_authority_mutation()
|
|
899
|
+
$ddl$, data_schema);
|
|
900
|
+
|
|
901
|
+
EXECUTE format($ddl$
|
|
902
|
+
CREATE OR REPLACE FUNCTION %1$I.prevent_xai_snapshot_mutation()
|
|
903
|
+
RETURNS trigger LANGUAGE plpgsql AS $body$
|
|
904
|
+
BEGIN
|
|
905
|
+
IF TG_TABLE_NAME = 'sessions' THEN
|
|
906
|
+
IF NEW.initial_xai_provider_account_authority_snapshot
|
|
907
|
+
IS DISTINCT FROM OLD.initial_xai_provider_account_authority_snapshot
|
|
908
|
+
THEN
|
|
909
|
+
RAISE EXCEPTION 'session initial xAI provider-account authority snapshot is immutable'
|
|
910
|
+
USING ERRCODE = '23514';
|
|
911
|
+
END IF;
|
|
912
|
+
ELSIF NEW.xai_provider_account_authority_snapshot
|
|
913
|
+
IS DISTINCT FROM OLD.xai_provider_account_authority_snapshot
|
|
914
|
+
THEN
|
|
915
|
+
RAISE EXCEPTION '%% xAI provider-account authority snapshot is immutable', TG_TABLE_NAME
|
|
916
|
+
USING ERRCODE = '23514';
|
|
917
|
+
END IF;
|
|
918
|
+
RETURN NEW;
|
|
919
|
+
END
|
|
920
|
+
$body$;
|
|
921
|
+
$ddl$, data_schema);
|
|
922
|
+
END
|
|
923
|
+
$xai_immutability$;
|
|
924
|
+
|
|
925
|
+
ALTER TABLE "session_turns"
|
|
926
|
+
ADD COLUMN "xai_provider_account_authority_snapshot" jsonb
|
|
927
|
+
NOT NULL DEFAULT '{"version":1,"scope":"workspace"}'::jsonb,
|
|
928
|
+
ADD CONSTRAINT "session_turns_xai_authority_snapshot_chk" CHECK (
|
|
929
|
+
xai_provider_account_authority_snapshot_v1_valid(
|
|
930
|
+
"xai_provider_account_authority_snapshot"
|
|
931
|
+
)
|
|
932
|
+
);
|
|
933
|
+
ALTER TABLE "sessions"
|
|
934
|
+
ADD COLUMN "initial_xai_provider_account_authority_snapshot" jsonb
|
|
935
|
+
NOT NULL DEFAULT '{"version":1,"scope":"workspace"}'::jsonb,
|
|
936
|
+
ADD CONSTRAINT "sessions_initial_xai_authority_snapshot_chk" CHECK (
|
|
937
|
+
xai_provider_account_authority_snapshot_v1_valid(
|
|
938
|
+
"initial_xai_provider_account_authority_snapshot"
|
|
939
|
+
)
|
|
940
|
+
);
|
|
941
|
+
ALTER TABLE "scheduled_tasks"
|
|
942
|
+
ADD COLUMN "xai_provider_account_authority_snapshot" jsonb
|
|
943
|
+
NOT NULL DEFAULT '{"version":1,"scope":"workspace"}'::jsonb,
|
|
944
|
+
ADD CONSTRAINT "scheduled_tasks_xai_authority_snapshot_chk" CHECK (
|
|
945
|
+
xai_provider_account_authority_snapshot_v1_valid(
|
|
946
|
+
"xai_provider_account_authority_snapshot"
|
|
947
|
+
)
|
|
948
|
+
);
|
|
949
|
+
ALTER TABLE "session_system_updates"
|
|
950
|
+
ADD COLUMN "xai_provider_account_authority_snapshot" jsonb
|
|
951
|
+
NOT NULL DEFAULT '{"version":1,"scope":"workspace"}'::jsonb,
|
|
952
|
+
ADD CONSTRAINT "session_system_updates_xai_authority_snapshot_chk" CHECK (
|
|
953
|
+
xai_provider_account_authority_snapshot_v1_valid(
|
|
954
|
+
"xai_provider_account_authority_snapshot"
|
|
955
|
+
)
|
|
956
|
+
);
|
|
957
|
+
ALTER TABLE "session_system_update_outbox"
|
|
958
|
+
ADD COLUMN "xai_provider_account_authority_snapshot" jsonb
|
|
959
|
+
NOT NULL DEFAULT '{"version":1,"scope":"workspace"}'::jsonb,
|
|
960
|
+
ADD CONSTRAINT "session_system_update_outbox_xai_authority_snapshot_chk" CHECK (
|
|
961
|
+
xai_provider_account_authority_snapshot_v1_valid(
|
|
962
|
+
"xai_provider_account_authority_snapshot"
|
|
963
|
+
)
|
|
964
|
+
);
|
|
965
|
+
|
|
966
|
+
CREATE TRIGGER session_turns_xai_authority_snapshot_immutable_trg
|
|
967
|
+
BEFORE UPDATE OF xai_provider_account_authority_snapshot ON "session_turns"
|
|
968
|
+
FOR EACH ROW EXECUTE FUNCTION prevent_xai_snapshot_mutation();
|
|
969
|
+
CREATE TRIGGER sessions_initial_xai_authority_snapshot_immutable_trg
|
|
970
|
+
BEFORE UPDATE OF initial_xai_provider_account_authority_snapshot ON "sessions"
|
|
971
|
+
FOR EACH ROW EXECUTE FUNCTION prevent_xai_snapshot_mutation();
|
|
972
|
+
CREATE TRIGGER scheduled_tasks_xai_authority_snapshot_immutable_trg
|
|
973
|
+
BEFORE UPDATE OF xai_provider_account_authority_snapshot ON "scheduled_tasks"
|
|
974
|
+
FOR EACH ROW EXECUTE FUNCTION prevent_xai_snapshot_mutation();
|
|
975
|
+
CREATE TRIGGER session_system_updates_xai_authority_snapshot_immutable_trg
|
|
976
|
+
BEFORE UPDATE OF xai_provider_account_authority_snapshot ON "session_system_updates"
|
|
977
|
+
FOR EACH ROW EXECUTE FUNCTION prevent_xai_snapshot_mutation();
|
|
978
|
+
CREATE TRIGGER system_update_outbox_xai_snapshot_immutable_trg
|
|
979
|
+
BEFORE UPDATE OF xai_provider_account_authority_snapshot ON "session_system_update_outbox"
|
|
980
|
+
FOR EACH ROW EXECUTE FUNCTION prevent_xai_snapshot_mutation();
|
|
981
|
+
|
|
982
|
+
-- Preserve the immutable snapshot through the existing global child-result
|
|
983
|
+
-- outbox claim without changing any producer or runtime implementation. PR
|
|
984
|
+
-- #1361 may land before this migration and append its Codex snapshot first, so
|
|
985
|
+
-- preserve that column when it is present instead of replacing its boundary.
|
|
986
|
+
DROP FUNCTION opengeni_private.claim_session_system_update_outbox(integer);
|
|
987
|
+
DO $xai_outbox_claim$
|
|
988
|
+
DECLARE
|
|
989
|
+
data_schema text := current_schema();
|
|
990
|
+
has_codex_snapshot boolean;
|
|
991
|
+
BEGIN
|
|
992
|
+
SELECT EXISTS (
|
|
993
|
+
SELECT 1
|
|
994
|
+
FROM information_schema.columns
|
|
995
|
+
WHERE table_schema = data_schema
|
|
996
|
+
AND table_name = 'session_system_update_outbox'
|
|
997
|
+
AND column_name = 'codex_provider_account_authority_snapshot'
|
|
998
|
+
) INTO has_codex_snapshot;
|
|
999
|
+
|
|
1000
|
+
IF has_codex_snapshot THEN
|
|
1001
|
+
EXECUTE $ddl$
|
|
1002
|
+
CREATE FUNCTION opengeni_private.claim_session_system_update_outbox(p_limit integer)
|
|
1003
|
+
RETURNS TABLE (
|
|
1004
|
+
id uuid, account_id uuid, workspace_id uuid, source_session_id uuid,
|
|
1005
|
+
target_session_id uuid, dedupe_key text, kind text, classification text,
|
|
1006
|
+
source_id text, summary text, summary_codec_version integer,
|
|
1007
|
+
payload jsonb, payload_codec_version integer, lineage jsonb,
|
|
1008
|
+
personal_connection_delegations jsonb,
|
|
1009
|
+
codex_provider_account_authority_snapshot jsonb,
|
|
1010
|
+
xai_provider_account_authority_snapshot jsonb
|
|
1011
|
+
)
|
|
1012
|
+
LANGUAGE plpgsql SECURITY DEFINER
|
|
1013
|
+
AS $function$
|
|
1014
|
+
BEGIN
|
|
1015
|
+
RETURN QUERY
|
|
1016
|
+
WITH claimed AS (
|
|
1017
|
+
SELECT o.id FROM session_system_update_outbox o
|
|
1018
|
+
WHERE o.status = 'pending'
|
|
1019
|
+
ORDER BY o.created_at, o.id
|
|
1020
|
+
FOR UPDATE SKIP LOCKED
|
|
1021
|
+
LIMIT greatest(1, least(coalesce(p_limit, 100), 100))
|
|
1022
|
+
)
|
|
1023
|
+
UPDATE session_system_update_outbox o
|
|
1024
|
+
SET attempts = o.attempts + 1, updated_at = now()
|
|
1025
|
+
FROM claimed c WHERE o.id = c.id
|
|
1026
|
+
RETURNING o.id, o.account_id, o.workspace_id, o.source_session_id,
|
|
1027
|
+
o.target_session_id, o.dedupe_key, o.kind, o.classification,
|
|
1028
|
+
o.source_id, o.summary, o.summary_codec_version,
|
|
1029
|
+
o.payload, o.payload_codec_version, o.lineage,
|
|
1030
|
+
o.personal_connection_delegations,
|
|
1031
|
+
o.codex_provider_account_authority_snapshot,
|
|
1032
|
+
o.xai_provider_account_authority_snapshot;
|
|
1033
|
+
END
|
|
1034
|
+
$function$
|
|
1035
|
+
$ddl$;
|
|
1036
|
+
ELSE
|
|
1037
|
+
EXECUTE $ddl$
|
|
1038
|
+
CREATE FUNCTION opengeni_private.claim_session_system_update_outbox(p_limit integer)
|
|
1039
|
+
RETURNS TABLE (
|
|
1040
|
+
id uuid, account_id uuid, workspace_id uuid, source_session_id uuid,
|
|
1041
|
+
target_session_id uuid, dedupe_key text, kind text, classification text,
|
|
1042
|
+
source_id text, summary text, summary_codec_version integer,
|
|
1043
|
+
payload jsonb, payload_codec_version integer, lineage jsonb,
|
|
1044
|
+
personal_connection_delegations jsonb,
|
|
1045
|
+
xai_provider_account_authority_snapshot jsonb
|
|
1046
|
+
)
|
|
1047
|
+
LANGUAGE plpgsql SECURITY DEFINER
|
|
1048
|
+
AS $function$
|
|
1049
|
+
BEGIN
|
|
1050
|
+
RETURN QUERY
|
|
1051
|
+
WITH claimed AS (
|
|
1052
|
+
SELECT o.id FROM session_system_update_outbox o
|
|
1053
|
+
WHERE o.status = 'pending'
|
|
1054
|
+
ORDER BY o.created_at, o.id
|
|
1055
|
+
FOR UPDATE SKIP LOCKED
|
|
1056
|
+
LIMIT greatest(1, least(coalesce(p_limit, 100), 100))
|
|
1057
|
+
)
|
|
1058
|
+
UPDATE session_system_update_outbox o
|
|
1059
|
+
SET attempts = o.attempts + 1, updated_at = now()
|
|
1060
|
+
FROM claimed c WHERE o.id = c.id
|
|
1061
|
+
RETURNING o.id, o.account_id, o.workspace_id, o.source_session_id,
|
|
1062
|
+
o.target_session_id, o.dedupe_key, o.kind, o.classification,
|
|
1063
|
+
o.source_id, o.summary, o.summary_codec_version,
|
|
1064
|
+
o.payload, o.payload_codec_version, o.lineage,
|
|
1065
|
+
o.personal_connection_delegations,
|
|
1066
|
+
o.xai_provider_account_authority_snapshot;
|
|
1067
|
+
END
|
|
1068
|
+
$function$
|
|
1069
|
+
$ddl$;
|
|
1070
|
+
END IF;
|
|
1071
|
+
END
|
|
1072
|
+
$xai_outbox_claim$;
|
|
1073
|
+
|
|
1074
|
+
DO $xai_outbox_search_path$
|
|
1075
|
+
DECLARE data_schema text := current_schema();
|
|
1076
|
+
BEGIN
|
|
1077
|
+
EXECUTE format(
|
|
1078
|
+
'ALTER FUNCTION opengeni_private.claim_session_system_update_outbox(integer) SET search_path = pg_catalog, %I',
|
|
1079
|
+
data_schema
|
|
1080
|
+
);
|
|
1081
|
+
END
|
|
1082
|
+
$xai_outbox_search_path$;
|
|
1083
|
+
|
|
1084
|
+
REVOKE ALL ON FUNCTION create_xai_subscription_credential(
|
|
1085
|
+
uuid, uuid, text, text, text, text, text, text, text, timestamptz
|
|
1086
|
+
) FROM PUBLIC;
|
|
1087
|
+
REVOKE ALL ON FUNCTION resolve_xai_authority_pool(uuid, uuid, text, jsonb) FROM PUBLIC;
|
|
1088
|
+
REVOKE ALL ON FUNCTION revalidate_xai_subscription_authority(uuid, text, uuid, jsonb)
|
|
1089
|
+
FROM PUBLIC;
|
|
1090
|
+
REVOKE ALL ON FUNCTION disconnect_xai_subscription_credential(uuid, uuid, text, uuid, jsonb)
|
|
1091
|
+
FROM PUBLIC;
|
|
1092
|
+
REVOKE ALL ON FUNCTION opengeni_private.claim_session_system_update_outbox(integer)
|
|
1093
|
+
FROM PUBLIC;
|
|
1094
|
+
|
|
1095
|
+
DO $xai_runtime_grants$
|
|
1096
|
+
BEGIN
|
|
1097
|
+
IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'opengeni_app') THEN
|
|
1098
|
+
GRANT SELECT, INSERT, UPDATE, DELETE ON
|
|
1099
|
+
"xai_subscription_credentials", "xai_rotation_settings",
|
|
1100
|
+
"xai_credential_leases", "xai_session_account_pins", "xai_capacity_waiters"
|
|
1101
|
+
TO opengeni_app;
|
|
1102
|
+
GRANT EXECUTE ON FUNCTION create_xai_subscription_credential(
|
|
1103
|
+
uuid, uuid, text, text, text, text, text, text, text, timestamptz
|
|
1104
|
+
) TO opengeni_app;
|
|
1105
|
+
GRANT EXECUTE ON FUNCTION xai_provider_account_authority_snapshot_v1_valid(jsonb)
|
|
1106
|
+
TO opengeni_app;
|
|
1107
|
+
GRANT EXECUTE ON FUNCTION xai_subscription_authority_live(
|
|
1108
|
+
uuid, uuid, text, uuid, text, uuid, uuid, bigint
|
|
1109
|
+
) TO opengeni_app;
|
|
1110
|
+
GRANT EXECUTE ON FUNCTION xai_subscription_pool_visible(uuid, uuid, text, text, uuid)
|
|
1111
|
+
TO opengeni_app;
|
|
1112
|
+
GRANT EXECUTE ON FUNCTION resolve_xai_authority_pool(uuid, uuid, text, jsonb)
|
|
1113
|
+
TO opengeni_app;
|
|
1114
|
+
GRANT EXECUTE ON FUNCTION revalidate_xai_subscription_authority(
|
|
1115
|
+
uuid, text, uuid, jsonb
|
|
1116
|
+
) TO opengeni_app;
|
|
1117
|
+
GRANT EXECUTE ON FUNCTION disconnect_xai_subscription_credential(
|
|
1118
|
+
uuid, uuid, text, uuid, jsonb
|
|
1119
|
+
) TO opengeni_app;
|
|
1120
|
+
GRANT EXECUTE ON FUNCTION opengeni_private.claim_session_system_update_outbox(integer)
|
|
1121
|
+
TO opengeni_app;
|
|
1122
|
+
END IF;
|
|
1123
|
+
END
|
|
1124
|
+
$xai_runtime_grants$;
|
|
1125
|
+
|
|
1126
|
+
COMMENT ON COLUMN "xai_subscription_credentials"."credential_encrypted" IS
|
|
1127
|
+
'Authenticated-encrypted xAI credential JSON; never returned by metadata list/read APIs.';
|
|
1128
|
+
COMMENT ON COLUMN "xai_subscription_credentials"."connected_by_subject_id" IS
|
|
1129
|
+
'Connection audit attribution only; never ownership or executable authority.';
|
|
1130
|
+
COMMENT ON COLUMN "session_turns"."xai_provider_account_authority_snapshot" IS
|
|
1131
|
+
'Immutable identifier-free xAI provider-account authority snapshot for the accepted logical turn.';
|
|
1132
|
+
COMMENT ON COLUMN "sessions"."initial_xai_provider_account_authority_snapshot" IS
|
|
1133
|
+
'Immutable create-time xAI provider-account authority staging snapshot copied to the first turn.';
|
|
1134
|
+
COMMENT ON COLUMN "scheduled_tasks"."xai_provider_account_authority_snapshot" IS
|
|
1135
|
+
'Immutable identifier-free xAI provider-account authority snapshot for accepted schedule work.';
|
|
1136
|
+
COMMENT ON COLUMN "session_system_updates"."xai_provider_account_authority_snapshot" IS
|
|
1137
|
+
'Immutable identifier-free xAI provider-account authority snapshot for accepted internal input.';
|
|
1138
|
+
COMMENT ON COLUMN "session_system_update_outbox"."xai_provider_account_authority_snapshot" IS
|
|
1139
|
+
'Immutable identifier-free xAI provider-account authority snapshot preserved through child-result delivery.';
|