@opengeni/db 3.2.0-canary.0 → 3.4.0-canary.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/canonical-human-identities.js +3 -3
- package/dist/{chunk-SIBYBA2D.js → chunk-6DPJA36C.js} +30 -11
- package/dist/chunk-6DPJA36C.js.map +1 -0
- package/dist/{chunk-KRLPEMLH.js → chunk-C2AFP7SB.js} +184 -6
- package/dist/chunk-C2AFP7SB.js.map +1 -0
- package/dist/{chunk-AZHW7R5V.js → chunk-H7MXYG7R.js} +12 -8
- package/dist/chunk-H7MXYG7R.js.map +1 -0
- package/dist/{chunk-2PRS4J5Q.js → chunk-HY3F5Q4E.js} +3 -3
- package/dist/{chunk-NAB6FKFN.js → chunk-O6FTELKH.js} +3 -3
- package/dist/{chunk-UZNXG44K.js → chunk-PYMY3AJW.js} +324 -8
- package/dist/chunk-PYMY3AJW.js.map +1 -0
- package/dist/{chunk-6HMM2R5T.js → chunk-TRBOWUG3.js} +98 -4
- package/dist/chunk-TRBOWUG3.js.map +1 -0
- package/dist/{chunk-E6CLMKEE.js → chunk-V3TRUXFJ.js} +2 -2
- package/dist/{chunk-2EH4WRHL.js → chunk-ZWRIPCTR.js} +2 -2
- package/dist/editable-artifact-durable-export.js +2 -2
- package/dist/editable-artifacts.js +3 -3
- package/dist/governed-learning-activation.d.ts +16 -0
- package/dist/index.d.ts +108 -7
- package/dist/index.js +3605 -1417
- package/dist/index.js.map +1 -1
- package/dist/insights-model-bundle.d.ts +30 -0
- package/dist/insights-usage-bundle.d.ts +32 -0
- package/dist/insights.d.ts +10 -2
- package/dist/lossless-json.d.ts +1 -1
- package/dist/managed-user-setup.d.ts +82 -0
- package/dist/memory-domain.d.ts +2 -2
- package/dist/migrate.d.ts +3 -1
- package/dist/migrate.js +1 -1
- package/dist/new-session-drafts.d.ts +4 -4
- package/dist/organization-membership-lifecycle.d.ts +60 -1
- package/dist/pr-review.d.ts +44 -3
- package/dist/provision-roles.js +1 -1
- package/dist/runtime-posture.d.ts +12 -7
- package/dist/schema.d.ts +839 -101
- package/dist/schema.js +9 -1
- package/dist/session-background-commands.js +3 -3
- package/dist/session-tenancy.d.ts +12 -1
- package/dist/session-tenancy.js +3 -3
- package/dist/video-generation.js +3 -3
- package/drizzle/0348_named_signup_and_user_setup.sql +838 -0
- package/drizzle/0349_greenfield_session_tenancy_activation.sql +792 -0
- package/drizzle/0350_organization_shared_workspace_administration.sql +889 -0
- package/drizzle/0351_organization_user_setup_delivery.sql +978 -0
- package/drizzle/0352_session_variable_set_attachments.sql +1661 -0
- package/drizzle/0353_automatic_session_title_policy_fence.sql +476 -0
- package/drizzle/0354_automatic_session_title_quarantine_index.sql +9 -0
- package/drizzle/0355_automatic_session_title_quarantine.sql +92 -0
- package/drizzle/0356_set_based_insights_session_visibility.sql +237 -0
- package/drizzle/0357_rig_platform_base_only.sql +44 -0
- package/drizzle/0358_pr_review_managed_github_app.sql +108 -0
- package/drizzle/0359_insights_force_rls_read_capability.sql +936 -0
- package/drizzle/0360_organization_identity_confirmation_prompt.sql +103 -0
- package/drizzle/0361_remember_knowledge_memory_materialization.sql +249 -0
- package/package.json +6 -6
- package/src/database.ts +12 -8
- package/src/governed-learning-activation.ts +74 -2
- package/src/index.ts +879 -92
- package/src/insights-model-bundle.ts +681 -0
- package/src/insights-usage-bundle.ts +240 -0
- package/src/insights.ts +265 -152
- package/src/lossless-json.ts +2 -1
- package/src/managed-user-setup.ts +316 -0
- package/src/memory-domain.ts +3 -3
- package/src/migrate.ts +38 -14
- package/src/new-session-drafts.ts +22 -15
- package/src/organization-membership-lifecycle.ts +253 -1
- package/src/pr-review.ts +449 -6
- package/src/provision-roles.ts +92 -0
- package/src/runtime-posture.ts +247 -4
- package/src/schema.ts +210 -4
- package/src/session-tenancy.ts +120 -2
- package/dist/chunk-6HMM2R5T.js.map +0 -1
- package/dist/chunk-AZHW7R5V.js.map +0 -1
- package/dist/chunk-KRLPEMLH.js.map +0 -1
- package/dist/chunk-SIBYBA2D.js.map +0 -1
- package/dist/chunk-UZNXG44K.js.map +0 -1
- /package/dist/{chunk-2PRS4J5Q.js.map → chunk-HY3F5Q4E.js.map} +0 -0
- /package/dist/{chunk-NAB6FKFN.js.map → chunk-O6FTELKH.js.map} +0 -0
- /package/dist/{chunk-E6CLMKEE.js.map → chunk-V3TRUXFJ.js.map} +0 -0
- /package/dist/{chunk-2EH4WRHL.js.map → chunk-ZWRIPCTR.js.map} +0 -0
|
@@ -0,0 +1,936 @@
|
|
|
1
|
+
-- deployment-mode: rolling
|
|
2
|
+
-- Migration 0356 moved Insights visibility into set-based SECURITY DEFINER
|
|
3
|
+
-- scans, but a production migration owner is deliberately NOSUPERUSER and
|
|
4
|
+
-- NOBYPASSRLS. FORCE RLS therefore still ran the restrictive scalar
|
|
5
|
+
-- session_reference_visible() predicate once per fact. Open one exact,
|
|
6
|
+
-- transaction-local read capability while each audited function is active and
|
|
7
|
+
-- add that owner-only capability only to the SELECT form of the two fact-table
|
|
8
|
+
-- visibility policies. Sessions retain their ordinary policy, and every fact
|
|
9
|
+
-- write keeps the original predicate. The capability is a private row bound to
|
|
10
|
+
-- backend PID + xid + exact tenant/actor context, not a caller-forgeable GUC.
|
|
11
|
+
|
|
12
|
+
SET LOCAL lock_timeout = '5s';
|
|
13
|
+
SET LOCAL statement_timeout = '10min';
|
|
14
|
+
|
|
15
|
+
CREATE TABLE opengeni_private.insights_fact_read_runtime_capabilities (
|
|
16
|
+
backend_pid integer NOT NULL,
|
|
17
|
+
transaction_id xid8 NOT NULL,
|
|
18
|
+
capability_kind text NOT NULL,
|
|
19
|
+
account_id uuid NOT NULL,
|
|
20
|
+
workspace_id uuid NOT NULL,
|
|
21
|
+
subject_id text,
|
|
22
|
+
initiating_human_subject_id text,
|
|
23
|
+
created_at timestamp with time zone NOT NULL DEFAULT pg_catalog.clock_timestamp(),
|
|
24
|
+
CONSTRAINT insights_fact_read_runtime_capabilities_kind_chk CHECK (
|
|
25
|
+
capability_kind IN ('model_call_facts', 'usage_events')
|
|
26
|
+
),
|
|
27
|
+
CONSTRAINT insights_fact_read_runtime_capabilities_pk PRIMARY KEY (
|
|
28
|
+
backend_pid, transaction_id, capability_kind
|
|
29
|
+
)
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
REVOKE ALL ON TABLE
|
|
33
|
+
opengeni_private.insights_fact_read_runtime_capabilities
|
|
34
|
+
FROM PUBLIC;
|
|
35
|
+
|
|
36
|
+
-- Owner ALTER DEFAULT PRIVILEGES may have admitted arbitrary roles before this
|
|
37
|
+
-- migration. Strip every explicit non-owner table grantee before constructing
|
|
38
|
+
-- the allow-list from the configured application roles below.
|
|
39
|
+
DO $insights_fact_read_capability_table_acl_reset$
|
|
40
|
+
DECLARE
|
|
41
|
+
role_name text;
|
|
42
|
+
BEGIN
|
|
43
|
+
FOR role_name IN
|
|
44
|
+
SELECT grantee_role.rolname
|
|
45
|
+
FROM pg_catalog.pg_class relation
|
|
46
|
+
CROSS JOIN LATERAL pg_catalog.aclexplode(
|
|
47
|
+
coalesce(
|
|
48
|
+
relation.relacl,
|
|
49
|
+
pg_catalog.acldefault('r', relation.relowner)
|
|
50
|
+
)
|
|
51
|
+
) privilege
|
|
52
|
+
INNER JOIN pg_catalog.pg_roles grantee_role
|
|
53
|
+
ON grantee_role.oid = privilege.grantee
|
|
54
|
+
WHERE relation.oid =
|
|
55
|
+
'opengeni_private.insights_fact_read_runtime_capabilities'::pg_catalog.regclass
|
|
56
|
+
AND privilege.grantee <> 0
|
|
57
|
+
AND privilege.grantee <> relation.relowner
|
|
58
|
+
GROUP BY grantee_role.rolname
|
|
59
|
+
ORDER BY grantee_role.rolname COLLATE "C"
|
|
60
|
+
LOOP
|
|
61
|
+
EXECUTE pg_catalog.format(
|
|
62
|
+
'REVOKE ALL ON TABLE '
|
|
63
|
+
|| 'opengeni_private.insights_fact_read_runtime_capabilities FROM %I',
|
|
64
|
+
role_name
|
|
65
|
+
);
|
|
66
|
+
END LOOP;
|
|
67
|
+
END
|
|
68
|
+
$insights_fact_read_capability_table_acl_reset$;
|
|
69
|
+
|
|
70
|
+
-- PostgreSQL checks EXECUTE on every function referenced by an RLS policy
|
|
71
|
+
-- before it can short-circuit an owner-only branch. Put the value-free policy
|
|
72
|
+
-- guard in the fact-table schema and make only that guard public, so ordinary
|
|
73
|
+
-- reporting roles can keep using scalar fact visibility without widening
|
|
74
|
+
-- their private-schema ACLs or receiving EXECUTE on either analytical entry
|
|
75
|
+
-- point. A direct caller can spoof the two role arguments, but can only observe
|
|
76
|
+
-- a same-backend, same-transaction capability that it cannot mint.
|
|
77
|
+
DO $insights_fact_read_policy_capability_function$
|
|
78
|
+
DECLARE
|
|
79
|
+
data_schema text := pg_catalog.current_schema();
|
|
80
|
+
BEGIN
|
|
81
|
+
EXECUTE pg_catalog.format($ddl$
|
|
82
|
+
CREATE OR REPLACE FUNCTION %1$I.insights_fact_read_policy_capability_active(
|
|
83
|
+
p_actor text,
|
|
84
|
+
p_expected_owner text,
|
|
85
|
+
p_capability_kind text
|
|
86
|
+
) RETURNS boolean
|
|
87
|
+
LANGUAGE sql
|
|
88
|
+
STABLE
|
|
89
|
+
SECURITY DEFINER
|
|
90
|
+
SET search_path = pg_catalog
|
|
91
|
+
AS $function$
|
|
92
|
+
SELECT p_actor = p_expected_owner AND EXISTS (
|
|
93
|
+
SELECT 1
|
|
94
|
+
FROM opengeni_private.insights_fact_read_runtime_capabilities capability
|
|
95
|
+
WHERE capability.backend_pid = pg_catalog.pg_backend_pid()
|
|
96
|
+
AND capability.transaction_id = pg_catalog.pg_current_xact_id_if_assigned()
|
|
97
|
+
AND capability.capability_kind = p_capability_kind
|
|
98
|
+
AND capability.account_id IS NOT DISTINCT FROM nullif(
|
|
99
|
+
pg_catalog.current_setting('opengeni.account_id', true), ''
|
|
100
|
+
)::uuid
|
|
101
|
+
AND capability.workspace_id IS NOT DISTINCT FROM nullif(
|
|
102
|
+
pg_catalog.current_setting('opengeni.workspace_id', true), ''
|
|
103
|
+
)::uuid
|
|
104
|
+
AND capability.subject_id IS NOT DISTINCT FROM nullif(
|
|
105
|
+
pg_catalog.current_setting('opengeni.subject_id', true), ''
|
|
106
|
+
)
|
|
107
|
+
AND capability.initiating_human_subject_id IS NOT DISTINCT FROM nullif(
|
|
108
|
+
pg_catalog.current_setting(
|
|
109
|
+
'opengeni.initiating_human_subject_id', true
|
|
110
|
+
), ''
|
|
111
|
+
)
|
|
112
|
+
)
|
|
113
|
+
$function$;
|
|
114
|
+
REVOKE ALL ON FUNCTION
|
|
115
|
+
%1$I.insights_fact_read_policy_capability_active(text, text, text)
|
|
116
|
+
FROM PUBLIC;
|
|
117
|
+
GRANT EXECUTE ON FUNCTION
|
|
118
|
+
%1$I.insights_fact_read_policy_capability_active(text, text, text)
|
|
119
|
+
TO PUBLIC;
|
|
120
|
+
$ddl$, data_schema);
|
|
121
|
+
END
|
|
122
|
+
$insights_fact_read_policy_capability_function$;
|
|
123
|
+
|
|
124
|
+
-- Split the existing restrictive FOR ALL policy into command-specific forms.
|
|
125
|
+
-- SELECT alone receives the owner+private-capability alternative. INSERT,
|
|
126
|
+
-- UPDATE, and DELETE retain the exact installed expression, including all
|
|
127
|
+
-- session-tenancy owner/fence behavior on sessions. Refuse definition drift
|
|
128
|
+
-- instead of weakening an unknown future policy.
|
|
129
|
+
DO $insights_fact_read_select_policies$
|
|
130
|
+
DECLARE
|
|
131
|
+
data_schema text := pg_catalog.current_schema();
|
|
132
|
+
target record;
|
|
133
|
+
installed record;
|
|
134
|
+
capability_expression text;
|
|
135
|
+
BEGIN
|
|
136
|
+
FOR target IN
|
|
137
|
+
SELECT *
|
|
138
|
+
FROM (VALUES
|
|
139
|
+
('model_call_facts'::text, 'model_call_facts'::text),
|
|
140
|
+
('usage_events'::text, 'usage_events'::text)
|
|
141
|
+
) target_row(table_name, capability_kind)
|
|
142
|
+
LOOP
|
|
143
|
+
SELECT
|
|
144
|
+
policy.polpermissive AS permissive,
|
|
145
|
+
policy.polcmd AS command,
|
|
146
|
+
pg_catalog.pg_get_expr(policy.polqual, policy.polrelid) AS using_expression,
|
|
147
|
+
pg_catalog.pg_get_expr(policy.polwithcheck, policy.polrelid) AS check_expression
|
|
148
|
+
INTO installed
|
|
149
|
+
FROM pg_catalog.pg_policy policy
|
|
150
|
+
INNER JOIN pg_catalog.pg_class relation ON relation.oid = policy.polrelid
|
|
151
|
+
INNER JOIN pg_catalog.pg_namespace namespace ON namespace.oid = relation.relnamespace
|
|
152
|
+
WHERE namespace.nspname = data_schema
|
|
153
|
+
AND relation.relname = target.table_name
|
|
154
|
+
AND policy.polname = 'session_visibility_isolation';
|
|
155
|
+
|
|
156
|
+
IF NOT FOUND
|
|
157
|
+
OR installed.permissive
|
|
158
|
+
OR installed.command <> '*'
|
|
159
|
+
OR installed.using_expression IS NULL
|
|
160
|
+
OR installed.check_expression IS DISTINCT FROM installed.using_expression
|
|
161
|
+
THEN
|
|
162
|
+
RAISE EXCEPTION '0359 unexpected session visibility policy on %.%',
|
|
163
|
+
data_schema, target.table_name
|
|
164
|
+
USING ERRCODE = '55000';
|
|
165
|
+
END IF;
|
|
166
|
+
|
|
167
|
+
capability_expression := pg_catalog.format(
|
|
168
|
+
'%1$I.insights_fact_read_policy_capability_active('
|
|
169
|
+
|| 'current_user, pg_catalog.pg_get_userbyid(('
|
|
170
|
+
|| 'SELECT relation.relowner FROM pg_catalog.pg_class relation '
|
|
171
|
+
|| 'WHERE relation.oid = %2$L::pg_catalog.regclass)), %3$L)',
|
|
172
|
+
data_schema,
|
|
173
|
+
pg_catalog.format('%I.%I', data_schema, target.table_name),
|
|
174
|
+
target.capability_kind
|
|
175
|
+
);
|
|
176
|
+
|
|
177
|
+
EXECUTE pg_catalog.format(
|
|
178
|
+
'DROP POLICY session_visibility_isolation ON %I.%I',
|
|
179
|
+
data_schema,
|
|
180
|
+
target.table_name
|
|
181
|
+
);
|
|
182
|
+
EXECUTE pg_catalog.format(
|
|
183
|
+
'DROP POLICY IF EXISTS session_visibility_insert_isolation ON %I.%I',
|
|
184
|
+
data_schema,
|
|
185
|
+
target.table_name
|
|
186
|
+
);
|
|
187
|
+
EXECUTE pg_catalog.format(
|
|
188
|
+
'DROP POLICY IF EXISTS session_visibility_update_isolation ON %I.%I',
|
|
189
|
+
data_schema,
|
|
190
|
+
target.table_name
|
|
191
|
+
);
|
|
192
|
+
EXECUTE pg_catalog.format(
|
|
193
|
+
'DROP POLICY IF EXISTS session_visibility_delete_isolation ON %I.%I',
|
|
194
|
+
data_schema,
|
|
195
|
+
target.table_name
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
EXECUTE pg_catalog.format(
|
|
199
|
+
'CREATE POLICY session_visibility_isolation ON %I.%I AS RESTRICTIVE '
|
|
200
|
+
|| 'FOR SELECT USING (CASE WHEN (%s) THEN true ELSE (%s) END)',
|
|
201
|
+
data_schema,
|
|
202
|
+
target.table_name,
|
|
203
|
+
capability_expression,
|
|
204
|
+
installed.using_expression
|
|
205
|
+
);
|
|
206
|
+
EXECUTE pg_catalog.format(
|
|
207
|
+
'CREATE POLICY session_visibility_insert_isolation ON %I.%I AS RESTRICTIVE '
|
|
208
|
+
|| 'FOR INSERT WITH CHECK (%s)',
|
|
209
|
+
data_schema,
|
|
210
|
+
target.table_name,
|
|
211
|
+
installed.check_expression
|
|
212
|
+
);
|
|
213
|
+
EXECUTE pg_catalog.format(
|
|
214
|
+
'CREATE POLICY session_visibility_update_isolation ON %I.%I AS RESTRICTIVE '
|
|
215
|
+
|| 'FOR UPDATE USING (%s) WITH CHECK (%s)',
|
|
216
|
+
data_schema,
|
|
217
|
+
target.table_name,
|
|
218
|
+
installed.using_expression,
|
|
219
|
+
installed.check_expression
|
|
220
|
+
);
|
|
221
|
+
EXECUTE pg_catalog.format(
|
|
222
|
+
'CREATE POLICY session_visibility_delete_isolation ON %I.%I AS RESTRICTIVE '
|
|
223
|
+
|| 'FOR DELETE USING (%s)',
|
|
224
|
+
data_schema,
|
|
225
|
+
target.table_name,
|
|
226
|
+
installed.using_expression
|
|
227
|
+
);
|
|
228
|
+
END LOOP;
|
|
229
|
+
END
|
|
230
|
+
$insights_fact_read_select_policies$;
|
|
231
|
+
|
|
232
|
+
DO $insights_model_fact_read_functions$
|
|
233
|
+
DECLARE
|
|
234
|
+
data_schema text := pg_catalog.current_schema();
|
|
235
|
+
BEGIN
|
|
236
|
+
EXECUTE pg_catalog.format($ddl$
|
|
237
|
+
CREATE OR REPLACE FUNCTION opengeni_private.visible_workspace_insights_model_call_facts(
|
|
238
|
+
p_workspace_id uuid,
|
|
239
|
+
p_since timestamp with time zone,
|
|
240
|
+
p_until timestamp with time zone,
|
|
241
|
+
p_provider text,
|
|
242
|
+
p_model text
|
|
243
|
+
) RETURNS SETOF %1$I.model_call_facts
|
|
244
|
+
LANGUAGE plpgsql
|
|
245
|
+
VOLATILE
|
|
246
|
+
SECURITY DEFINER
|
|
247
|
+
SET search_path = pg_catalog, %1$I, opengeni_private, pg_temp
|
|
248
|
+
AS $function$
|
|
249
|
+
DECLARE
|
|
250
|
+
context_account_id uuid;
|
|
251
|
+
context_workspace_id uuid;
|
|
252
|
+
context_subject_id text;
|
|
253
|
+
context_initiating_human_subject_id text;
|
|
254
|
+
BEGIN
|
|
255
|
+
PERFORM opengeni_private.session_variable_set_attachments_protocol_v1_active();
|
|
256
|
+
BEGIN
|
|
257
|
+
context_account_id := nullif(
|
|
258
|
+
pg_catalog.current_setting('opengeni.account_id', true), ''
|
|
259
|
+
)::uuid;
|
|
260
|
+
context_workspace_id := nullif(
|
|
261
|
+
pg_catalog.current_setting('opengeni.workspace_id', true), ''
|
|
262
|
+
)::uuid;
|
|
263
|
+
EXCEPTION WHEN invalid_text_representation THEN
|
|
264
|
+
RAISE EXCEPTION 'Insights RLS context is malformed'
|
|
265
|
+
USING ERRCODE = '42501';
|
|
266
|
+
END;
|
|
267
|
+
context_subject_id := nullif(
|
|
268
|
+
pg_catalog.current_setting('opengeni.subject_id', true), ''
|
|
269
|
+
);
|
|
270
|
+
context_initiating_human_subject_id := nullif(
|
|
271
|
+
pg_catalog.current_setting('opengeni.initiating_human_subject_id', true), ''
|
|
272
|
+
);
|
|
273
|
+
IF context_account_id IS NULL
|
|
274
|
+
OR context_workspace_id IS NULL
|
|
275
|
+
OR context_workspace_id IS DISTINCT FROM p_workspace_id
|
|
276
|
+
THEN
|
|
277
|
+
RAISE EXCEPTION 'Insights RLS context does not match the requested workspace'
|
|
278
|
+
USING ERRCODE = '42501';
|
|
279
|
+
END IF;
|
|
280
|
+
IF p_since IS NULL
|
|
281
|
+
OR p_until IS NULL
|
|
282
|
+
OR p_since IN (
|
|
283
|
+
'-infinity'::timestamp with time zone,
|
|
284
|
+
'infinity'::timestamp with time zone
|
|
285
|
+
)
|
|
286
|
+
OR p_until = '-infinity'::timestamp with time zone
|
|
287
|
+
OR p_until < p_since
|
|
288
|
+
OR (
|
|
289
|
+
p_until <> 'infinity'::timestamp with time zone
|
|
290
|
+
AND p_until - p_since > interval '370 days'
|
|
291
|
+
)
|
|
292
|
+
OR (
|
|
293
|
+
p_until = 'infinity'::timestamp with time zone
|
|
294
|
+
AND p_since < CURRENT_TIMESTAMP - interval '370 days'
|
|
295
|
+
)
|
|
296
|
+
THEN
|
|
297
|
+
RAISE EXCEPTION 'Insights fact window must be non-negative and at most 370 days'
|
|
298
|
+
USING ERRCODE = '22023';
|
|
299
|
+
END IF;
|
|
300
|
+
IF (p_provider IS NOT NULL AND (
|
|
301
|
+
pg_catalog.btrim(p_provider) = ''
|
|
302
|
+
OR pg_catalog.octet_length(p_provider) > 256
|
|
303
|
+
))
|
|
304
|
+
OR (p_model IS NOT NULL AND (
|
|
305
|
+
pg_catalog.btrim(p_model) = ''
|
|
306
|
+
OR pg_catalog.octet_length(p_model) > 512
|
|
307
|
+
))
|
|
308
|
+
THEN
|
|
309
|
+
RAISE EXCEPTION 'Insights model filters are invalid'
|
|
310
|
+
USING ERRCODE = '22023';
|
|
311
|
+
END IF;
|
|
312
|
+
IF p_until = p_since THEN
|
|
313
|
+
RETURN;
|
|
314
|
+
END IF;
|
|
315
|
+
|
|
316
|
+
INSERT INTO opengeni_private.insights_fact_read_runtime_capabilities (
|
|
317
|
+
backend_pid,
|
|
318
|
+
transaction_id,
|
|
319
|
+
capability_kind,
|
|
320
|
+
account_id,
|
|
321
|
+
workspace_id,
|
|
322
|
+
subject_id,
|
|
323
|
+
initiating_human_subject_id
|
|
324
|
+
) VALUES (
|
|
325
|
+
pg_catalog.pg_backend_pid(),
|
|
326
|
+
pg_catalog.pg_current_xact_id(),
|
|
327
|
+
'model_call_facts',
|
|
328
|
+
context_account_id,
|
|
329
|
+
context_workspace_id,
|
|
330
|
+
context_subject_id,
|
|
331
|
+
context_initiating_human_subject_id
|
|
332
|
+
);
|
|
333
|
+
BEGIN
|
|
334
|
+
-- Keep each nullability shape static. A cached generic PL/pgSQL plan
|
|
335
|
+
-- for nullable OR predicates can abandon the selective
|
|
336
|
+
-- workspace/provider/model/occurred_at index after repeated calls.
|
|
337
|
+
IF p_provider IS NULL AND p_model IS NULL THEN
|
|
338
|
+
RETURN QUERY
|
|
339
|
+
WITH visible_sessions AS MATERIALIZED (
|
|
340
|
+
SELECT
|
|
341
|
+
id, account_id, workspace_id, visibility,
|
|
342
|
+
owner_organization_membership_id, owner_subject_id
|
|
343
|
+
FROM %1$I.sessions
|
|
344
|
+
WHERE account_id = context_account_id
|
|
345
|
+
AND workspace_id = p_workspace_id
|
|
346
|
+
)
|
|
347
|
+
SELECT fact.*
|
|
348
|
+
FROM %1$I.model_call_facts fact
|
|
349
|
+
INNER JOIN visible_sessions session_row
|
|
350
|
+
ON session_row.account_id = fact.account_id
|
|
351
|
+
AND session_row.workspace_id = fact.workspace_id
|
|
352
|
+
AND session_row.id = fact.session_id
|
|
353
|
+
WHERE fact.account_id = context_account_id
|
|
354
|
+
AND fact.workspace_id = p_workspace_id
|
|
355
|
+
AND fact.occurred_at >= p_since
|
|
356
|
+
AND fact.occurred_at < p_until
|
|
357
|
+
AND (
|
|
358
|
+
context_subject_id IS NULL
|
|
359
|
+
OR session_row.visibility = 'workspace_shared'
|
|
360
|
+
OR %1$I.session_private_actor_visible(
|
|
361
|
+
session_row.account_id,
|
|
362
|
+
session_row.workspace_id,
|
|
363
|
+
session_row.owner_organization_membership_id,
|
|
364
|
+
session_row.owner_subject_id
|
|
365
|
+
)
|
|
366
|
+
);
|
|
367
|
+
ELSIF p_provider IS NOT NULL AND p_model IS NULL THEN
|
|
368
|
+
RETURN QUERY
|
|
369
|
+
WITH visible_sessions AS MATERIALIZED (
|
|
370
|
+
SELECT
|
|
371
|
+
id, account_id, workspace_id, visibility,
|
|
372
|
+
owner_organization_membership_id, owner_subject_id
|
|
373
|
+
FROM %1$I.sessions
|
|
374
|
+
WHERE account_id = context_account_id
|
|
375
|
+
AND workspace_id = p_workspace_id
|
|
376
|
+
)
|
|
377
|
+
SELECT fact.*
|
|
378
|
+
FROM %1$I.model_call_facts fact
|
|
379
|
+
INNER JOIN visible_sessions session_row
|
|
380
|
+
ON session_row.account_id = fact.account_id
|
|
381
|
+
AND session_row.workspace_id = fact.workspace_id
|
|
382
|
+
AND session_row.id = fact.session_id
|
|
383
|
+
WHERE fact.account_id = context_account_id
|
|
384
|
+
AND fact.workspace_id = p_workspace_id
|
|
385
|
+
AND fact.provider = p_provider
|
|
386
|
+
AND fact.occurred_at >= p_since
|
|
387
|
+
AND fact.occurred_at < p_until
|
|
388
|
+
AND (
|
|
389
|
+
context_subject_id IS NULL
|
|
390
|
+
OR session_row.visibility = 'workspace_shared'
|
|
391
|
+
OR %1$I.session_private_actor_visible(
|
|
392
|
+
session_row.account_id,
|
|
393
|
+
session_row.workspace_id,
|
|
394
|
+
session_row.owner_organization_membership_id,
|
|
395
|
+
session_row.owner_subject_id
|
|
396
|
+
)
|
|
397
|
+
);
|
|
398
|
+
ELSIF p_provider IS NULL AND p_model IS NOT NULL THEN
|
|
399
|
+
RETURN QUERY
|
|
400
|
+
WITH visible_sessions AS MATERIALIZED (
|
|
401
|
+
SELECT
|
|
402
|
+
id, account_id, workspace_id, visibility,
|
|
403
|
+
owner_organization_membership_id, owner_subject_id
|
|
404
|
+
FROM %1$I.sessions
|
|
405
|
+
WHERE account_id = context_account_id
|
|
406
|
+
AND workspace_id = p_workspace_id
|
|
407
|
+
)
|
|
408
|
+
SELECT fact.*
|
|
409
|
+
FROM %1$I.model_call_facts fact
|
|
410
|
+
INNER JOIN visible_sessions session_row
|
|
411
|
+
ON session_row.account_id = fact.account_id
|
|
412
|
+
AND session_row.workspace_id = fact.workspace_id
|
|
413
|
+
AND session_row.id = fact.session_id
|
|
414
|
+
WHERE fact.account_id = context_account_id
|
|
415
|
+
AND fact.workspace_id = p_workspace_id
|
|
416
|
+
AND fact.model = p_model
|
|
417
|
+
AND fact.occurred_at >= p_since
|
|
418
|
+
AND fact.occurred_at < p_until
|
|
419
|
+
AND (
|
|
420
|
+
context_subject_id IS NULL
|
|
421
|
+
OR session_row.visibility = 'workspace_shared'
|
|
422
|
+
OR %1$I.session_private_actor_visible(
|
|
423
|
+
session_row.account_id,
|
|
424
|
+
session_row.workspace_id,
|
|
425
|
+
session_row.owner_organization_membership_id,
|
|
426
|
+
session_row.owner_subject_id
|
|
427
|
+
)
|
|
428
|
+
);
|
|
429
|
+
ELSE
|
|
430
|
+
RETURN QUERY
|
|
431
|
+
WITH visible_sessions AS MATERIALIZED (
|
|
432
|
+
SELECT
|
|
433
|
+
id, account_id, workspace_id, visibility,
|
|
434
|
+
owner_organization_membership_id, owner_subject_id
|
|
435
|
+
FROM %1$I.sessions
|
|
436
|
+
WHERE account_id = context_account_id
|
|
437
|
+
AND workspace_id = p_workspace_id
|
|
438
|
+
)
|
|
439
|
+
SELECT fact.*
|
|
440
|
+
FROM %1$I.model_call_facts fact
|
|
441
|
+
INNER JOIN visible_sessions session_row
|
|
442
|
+
ON session_row.account_id = fact.account_id
|
|
443
|
+
AND session_row.workspace_id = fact.workspace_id
|
|
444
|
+
AND session_row.id = fact.session_id
|
|
445
|
+
WHERE fact.account_id = context_account_id
|
|
446
|
+
AND fact.workspace_id = p_workspace_id
|
|
447
|
+
AND fact.provider = p_provider
|
|
448
|
+
AND fact.model = p_model
|
|
449
|
+
AND fact.occurred_at >= p_since
|
|
450
|
+
AND fact.occurred_at < p_until
|
|
451
|
+
AND (
|
|
452
|
+
context_subject_id IS NULL
|
|
453
|
+
OR session_row.visibility = 'workspace_shared'
|
|
454
|
+
OR %1$I.session_private_actor_visible(
|
|
455
|
+
session_row.account_id,
|
|
456
|
+
session_row.workspace_id,
|
|
457
|
+
session_row.owner_organization_membership_id,
|
|
458
|
+
session_row.owner_subject_id
|
|
459
|
+
)
|
|
460
|
+
);
|
|
461
|
+
END IF;
|
|
462
|
+
|
|
463
|
+
DELETE FROM opengeni_private.insights_fact_read_runtime_capabilities
|
|
464
|
+
WHERE backend_pid = pg_catalog.pg_backend_pid()
|
|
465
|
+
AND transaction_id = pg_catalog.pg_current_xact_id_if_assigned()
|
|
466
|
+
AND capability_kind = 'model_call_facts';
|
|
467
|
+
RETURN;
|
|
468
|
+
EXCEPTION WHEN OTHERS THEN
|
|
469
|
+
DELETE FROM opengeni_private.insights_fact_read_runtime_capabilities
|
|
470
|
+
WHERE backend_pid = pg_catalog.pg_backend_pid()
|
|
471
|
+
AND transaction_id = pg_catalog.pg_current_xact_id_if_assigned()
|
|
472
|
+
AND capability_kind = 'model_call_facts';
|
|
473
|
+
RAISE;
|
|
474
|
+
END;
|
|
475
|
+
END
|
|
476
|
+
$function$;
|
|
477
|
+
$ddl$, data_schema);
|
|
478
|
+
|
|
479
|
+
EXECUTE pg_catalog.format($ddl$
|
|
480
|
+
CREATE OR REPLACE FUNCTION opengeni_private.visible_workspace_insights_model_call_facts(
|
|
481
|
+
p_workspace_id uuid,
|
|
482
|
+
p_since timestamp with time zone,
|
|
483
|
+
p_until timestamp with time zone
|
|
484
|
+
) RETURNS SETOF %1$I.model_call_facts
|
|
485
|
+
LANGUAGE sql
|
|
486
|
+
VOLATILE
|
|
487
|
+
SECURITY DEFINER
|
|
488
|
+
SET search_path = pg_catalog, %1$I, opengeni_private, pg_temp
|
|
489
|
+
AS $function$
|
|
490
|
+
SELECT *
|
|
491
|
+
FROM opengeni_private.visible_workspace_insights_model_call_facts(
|
|
492
|
+
p_workspace_id, p_since, p_until, NULL, NULL
|
|
493
|
+
)
|
|
494
|
+
$function$;
|
|
495
|
+
$ddl$, data_schema);
|
|
496
|
+
END
|
|
497
|
+
$insights_model_fact_read_functions$;
|
|
498
|
+
|
|
499
|
+
DO $insights_usage_fact_read_functions$
|
|
500
|
+
DECLARE
|
|
501
|
+
data_schema text := pg_catalog.current_schema();
|
|
502
|
+
BEGIN
|
|
503
|
+
EXECUTE pg_catalog.format($ddl$
|
|
504
|
+
CREATE OR REPLACE FUNCTION opengeni_private.visible_workspace_insights_usage_events(
|
|
505
|
+
p_workspace_id uuid,
|
|
506
|
+
p_since timestamp with time zone,
|
|
507
|
+
p_until timestamp with time zone
|
|
508
|
+
) RETURNS SETOF %1$I.usage_events
|
|
509
|
+
LANGUAGE plpgsql
|
|
510
|
+
VOLATILE
|
|
511
|
+
SECURITY DEFINER
|
|
512
|
+
SET search_path = pg_catalog, %1$I, opengeni_private, pg_temp
|
|
513
|
+
AS $function$
|
|
514
|
+
DECLARE
|
|
515
|
+
context_account_id uuid;
|
|
516
|
+
context_workspace_id uuid;
|
|
517
|
+
context_subject_id text;
|
|
518
|
+
context_initiating_human_subject_id text;
|
|
519
|
+
BEGIN
|
|
520
|
+
PERFORM opengeni_private.session_variable_set_attachments_protocol_v1_active();
|
|
521
|
+
BEGIN
|
|
522
|
+
context_account_id := nullif(
|
|
523
|
+
pg_catalog.current_setting('opengeni.account_id', true), ''
|
|
524
|
+
)::uuid;
|
|
525
|
+
context_workspace_id := nullif(
|
|
526
|
+
pg_catalog.current_setting('opengeni.workspace_id', true), ''
|
|
527
|
+
)::uuid;
|
|
528
|
+
EXCEPTION WHEN invalid_text_representation THEN
|
|
529
|
+
RAISE EXCEPTION 'Insights RLS context is malformed'
|
|
530
|
+
USING ERRCODE = '42501';
|
|
531
|
+
END;
|
|
532
|
+
context_subject_id := nullif(
|
|
533
|
+
pg_catalog.current_setting('opengeni.subject_id', true), ''
|
|
534
|
+
);
|
|
535
|
+
context_initiating_human_subject_id := nullif(
|
|
536
|
+
pg_catalog.current_setting('opengeni.initiating_human_subject_id', true), ''
|
|
537
|
+
);
|
|
538
|
+
IF context_account_id IS NULL
|
|
539
|
+
OR context_workspace_id IS NULL
|
|
540
|
+
OR context_workspace_id IS DISTINCT FROM p_workspace_id
|
|
541
|
+
THEN
|
|
542
|
+
RAISE EXCEPTION 'Insights RLS context does not match the requested workspace'
|
|
543
|
+
USING ERRCODE = '42501';
|
|
544
|
+
END IF;
|
|
545
|
+
IF p_since IS NULL
|
|
546
|
+
OR p_until IS NULL
|
|
547
|
+
OR p_since IN (
|
|
548
|
+
'-infinity'::timestamp with time zone,
|
|
549
|
+
'infinity'::timestamp with time zone
|
|
550
|
+
)
|
|
551
|
+
OR p_until = '-infinity'::timestamp with time zone
|
|
552
|
+
OR p_until < p_since
|
|
553
|
+
OR (
|
|
554
|
+
p_until <> 'infinity'::timestamp with time zone
|
|
555
|
+
AND p_until - p_since > interval '370 days'
|
|
556
|
+
)
|
|
557
|
+
OR (
|
|
558
|
+
p_until = 'infinity'::timestamp with time zone
|
|
559
|
+
AND p_since < CURRENT_TIMESTAMP - interval '370 days'
|
|
560
|
+
)
|
|
561
|
+
THEN
|
|
562
|
+
RAISE EXCEPTION 'Insights fact window must be non-negative and at most 370 days'
|
|
563
|
+
USING ERRCODE = '22023';
|
|
564
|
+
END IF;
|
|
565
|
+
IF p_until = p_since THEN
|
|
566
|
+
RETURN;
|
|
567
|
+
END IF;
|
|
568
|
+
|
|
569
|
+
INSERT INTO opengeni_private.insights_fact_read_runtime_capabilities (
|
|
570
|
+
backend_pid,
|
|
571
|
+
transaction_id,
|
|
572
|
+
capability_kind,
|
|
573
|
+
account_id,
|
|
574
|
+
workspace_id,
|
|
575
|
+
subject_id,
|
|
576
|
+
initiating_human_subject_id
|
|
577
|
+
) VALUES (
|
|
578
|
+
pg_catalog.pg_backend_pid(),
|
|
579
|
+
pg_catalog.pg_current_xact_id(),
|
|
580
|
+
'usage_events',
|
|
581
|
+
context_account_id,
|
|
582
|
+
context_workspace_id,
|
|
583
|
+
context_subject_id,
|
|
584
|
+
context_initiating_human_subject_id
|
|
585
|
+
);
|
|
586
|
+
BEGIN
|
|
587
|
+
RETURN QUERY
|
|
588
|
+
WITH visible_sessions AS MATERIALIZED (
|
|
589
|
+
SELECT
|
|
590
|
+
id, account_id, workspace_id, visibility,
|
|
591
|
+
owner_organization_membership_id, owner_subject_id
|
|
592
|
+
FROM %1$I.sessions
|
|
593
|
+
WHERE account_id = context_account_id
|
|
594
|
+
AND workspace_id = p_workspace_id
|
|
595
|
+
)
|
|
596
|
+
SELECT usage_row.*
|
|
597
|
+
FROM %1$I.usage_events usage_row
|
|
598
|
+
LEFT JOIN visible_sessions session_row
|
|
599
|
+
ON session_row.account_id = usage_row.account_id
|
|
600
|
+
AND session_row.workspace_id = usage_row.workspace_id
|
|
601
|
+
AND session_row.id = usage_row.session_id
|
|
602
|
+
WHERE usage_row.account_id = context_account_id
|
|
603
|
+
AND usage_row.workspace_id = p_workspace_id
|
|
604
|
+
AND usage_row.occurred_at >= p_since
|
|
605
|
+
AND usage_row.occurred_at < p_until
|
|
606
|
+
AND (
|
|
607
|
+
usage_row.session_id IS NULL
|
|
608
|
+
OR (
|
|
609
|
+
session_row.id IS NOT NULL
|
|
610
|
+
AND (
|
|
611
|
+
context_subject_id IS NULL
|
|
612
|
+
OR session_row.visibility = 'workspace_shared'
|
|
613
|
+
OR %1$I.session_private_actor_visible(
|
|
614
|
+
session_row.account_id,
|
|
615
|
+
session_row.workspace_id,
|
|
616
|
+
session_row.owner_organization_membership_id,
|
|
617
|
+
session_row.owner_subject_id
|
|
618
|
+
)
|
|
619
|
+
)
|
|
620
|
+
)
|
|
621
|
+
);
|
|
622
|
+
|
|
623
|
+
DELETE FROM opengeni_private.insights_fact_read_runtime_capabilities
|
|
624
|
+
WHERE backend_pid = pg_catalog.pg_backend_pid()
|
|
625
|
+
AND transaction_id = pg_catalog.pg_current_xact_id_if_assigned()
|
|
626
|
+
AND capability_kind = 'usage_events';
|
|
627
|
+
RETURN;
|
|
628
|
+
EXCEPTION WHEN OTHERS THEN
|
|
629
|
+
DELETE FROM opengeni_private.insights_fact_read_runtime_capabilities
|
|
630
|
+
WHERE backend_pid = pg_catalog.pg_backend_pid()
|
|
631
|
+
AND transaction_id = pg_catalog.pg_current_xact_id_if_assigned()
|
|
632
|
+
AND capability_kind = 'usage_events';
|
|
633
|
+
RAISE;
|
|
634
|
+
END;
|
|
635
|
+
END
|
|
636
|
+
$function$;
|
|
637
|
+
$ddl$, data_schema);
|
|
638
|
+
|
|
639
|
+
EXECUTE pg_catalog.format($ddl$
|
|
640
|
+
CREATE OR REPLACE FUNCTION opengeni_private.visible_workspace_insights_usage_events(
|
|
641
|
+
p_workspace_id uuid,
|
|
642
|
+
p_since timestamp with time zone,
|
|
643
|
+
p_until timestamp with time zone,
|
|
644
|
+
p_event_types text[]
|
|
645
|
+
) RETURNS SETOF %1$I.usage_events
|
|
646
|
+
LANGUAGE plpgsql
|
|
647
|
+
VOLATILE
|
|
648
|
+
SECURITY DEFINER
|
|
649
|
+
SET search_path = pg_catalog, %1$I, opengeni_private, pg_temp
|
|
650
|
+
AS $function$
|
|
651
|
+
DECLARE
|
|
652
|
+
context_account_id uuid;
|
|
653
|
+
context_workspace_id uuid;
|
|
654
|
+
context_subject_id text;
|
|
655
|
+
context_initiating_human_subject_id text;
|
|
656
|
+
BEGIN
|
|
657
|
+
PERFORM opengeni_private.session_variable_set_attachments_protocol_v1_active();
|
|
658
|
+
BEGIN
|
|
659
|
+
context_account_id := nullif(
|
|
660
|
+
pg_catalog.current_setting('opengeni.account_id', true), ''
|
|
661
|
+
)::uuid;
|
|
662
|
+
context_workspace_id := nullif(
|
|
663
|
+
pg_catalog.current_setting('opengeni.workspace_id', true), ''
|
|
664
|
+
)::uuid;
|
|
665
|
+
EXCEPTION WHEN invalid_text_representation THEN
|
|
666
|
+
RAISE EXCEPTION 'Insights RLS context is malformed'
|
|
667
|
+
USING ERRCODE = '42501';
|
|
668
|
+
END;
|
|
669
|
+
context_subject_id := nullif(
|
|
670
|
+
pg_catalog.current_setting('opengeni.subject_id', true), ''
|
|
671
|
+
);
|
|
672
|
+
context_initiating_human_subject_id := nullif(
|
|
673
|
+
pg_catalog.current_setting('opengeni.initiating_human_subject_id', true), ''
|
|
674
|
+
);
|
|
675
|
+
IF context_account_id IS NULL
|
|
676
|
+
OR context_workspace_id IS NULL
|
|
677
|
+
OR context_workspace_id IS DISTINCT FROM p_workspace_id
|
|
678
|
+
THEN
|
|
679
|
+
RAISE EXCEPTION 'Insights RLS context does not match the requested workspace'
|
|
680
|
+
USING ERRCODE = '42501';
|
|
681
|
+
END IF;
|
|
682
|
+
IF p_since IS NULL
|
|
683
|
+
OR p_until IS NULL
|
|
684
|
+
OR p_since IN (
|
|
685
|
+
'-infinity'::timestamp with time zone,
|
|
686
|
+
'infinity'::timestamp with time zone
|
|
687
|
+
)
|
|
688
|
+
OR p_until = '-infinity'::timestamp with time zone
|
|
689
|
+
OR p_until < p_since
|
|
690
|
+
OR (
|
|
691
|
+
p_until <> 'infinity'::timestamp with time zone
|
|
692
|
+
AND p_until - p_since > interval '370 days'
|
|
693
|
+
)
|
|
694
|
+
OR (
|
|
695
|
+
p_until = 'infinity'::timestamp with time zone
|
|
696
|
+
AND p_since < CURRENT_TIMESTAMP - interval '370 days'
|
|
697
|
+
)
|
|
698
|
+
THEN
|
|
699
|
+
RAISE EXCEPTION 'Insights fact window must be non-negative and at most 370 days'
|
|
700
|
+
USING ERRCODE = '22023';
|
|
701
|
+
END IF;
|
|
702
|
+
IF p_event_types IS NULL
|
|
703
|
+
OR pg_catalog.array_ndims(p_event_types) <> 1
|
|
704
|
+
OR pg_catalog.cardinality(p_event_types) < 1
|
|
705
|
+
OR pg_catalog.cardinality(p_event_types) > 16
|
|
706
|
+
OR EXISTS (
|
|
707
|
+
SELECT 1
|
|
708
|
+
FROM pg_catalog.unnest(p_event_types) event_type(value)
|
|
709
|
+
WHERE event_type.value IS NULL
|
|
710
|
+
OR pg_catalog.btrim(event_type.value) = ''
|
|
711
|
+
OR pg_catalog.octet_length(event_type.value) > 256
|
|
712
|
+
)
|
|
713
|
+
OR (
|
|
714
|
+
SELECT pg_catalog.count(DISTINCT event_type.value COLLATE "C")
|
|
715
|
+
FROM pg_catalog.unnest(p_event_types) event_type(value)
|
|
716
|
+
) <> pg_catalog.cardinality(p_event_types)
|
|
717
|
+
THEN
|
|
718
|
+
RAISE EXCEPTION 'Insights usage event types must contain 1-16 unique bounded values'
|
|
719
|
+
USING ERRCODE = '22023';
|
|
720
|
+
END IF;
|
|
721
|
+
IF p_until = p_since THEN
|
|
722
|
+
RETURN;
|
|
723
|
+
END IF;
|
|
724
|
+
|
|
725
|
+
INSERT INTO opengeni_private.insights_fact_read_runtime_capabilities (
|
|
726
|
+
backend_pid,
|
|
727
|
+
transaction_id,
|
|
728
|
+
capability_kind,
|
|
729
|
+
account_id,
|
|
730
|
+
workspace_id,
|
|
731
|
+
subject_id,
|
|
732
|
+
initiating_human_subject_id
|
|
733
|
+
) VALUES (
|
|
734
|
+
pg_catalog.pg_backend_pid(),
|
|
735
|
+
pg_catalog.pg_current_xact_id(),
|
|
736
|
+
'usage_events',
|
|
737
|
+
context_account_id,
|
|
738
|
+
context_workspace_id,
|
|
739
|
+
context_subject_id,
|
|
740
|
+
context_initiating_human_subject_id
|
|
741
|
+
);
|
|
742
|
+
BEGIN
|
|
743
|
+
RETURN QUERY
|
|
744
|
+
WITH visible_sessions AS MATERIALIZED (
|
|
745
|
+
SELECT
|
|
746
|
+
id, account_id, workspace_id, visibility,
|
|
747
|
+
owner_organization_membership_id, owner_subject_id
|
|
748
|
+
FROM %1$I.sessions
|
|
749
|
+
WHERE account_id = context_account_id
|
|
750
|
+
AND workspace_id = p_workspace_id
|
|
751
|
+
)
|
|
752
|
+
SELECT usage_row.*
|
|
753
|
+
FROM %1$I.usage_events usage_row
|
|
754
|
+
LEFT JOIN visible_sessions session_row
|
|
755
|
+
ON session_row.account_id = usage_row.account_id
|
|
756
|
+
AND session_row.workspace_id = usage_row.workspace_id
|
|
757
|
+
AND session_row.id = usage_row.session_id
|
|
758
|
+
WHERE usage_row.account_id = context_account_id
|
|
759
|
+
AND usage_row.workspace_id = p_workspace_id
|
|
760
|
+
AND usage_row.event_type = ANY (p_event_types)
|
|
761
|
+
AND usage_row.occurred_at >= p_since
|
|
762
|
+
AND usage_row.occurred_at < p_until
|
|
763
|
+
AND (
|
|
764
|
+
usage_row.session_id IS NULL
|
|
765
|
+
OR (
|
|
766
|
+
session_row.id IS NOT NULL
|
|
767
|
+
AND (
|
|
768
|
+
context_subject_id IS NULL
|
|
769
|
+
OR session_row.visibility = 'workspace_shared'
|
|
770
|
+
OR %1$I.session_private_actor_visible(
|
|
771
|
+
session_row.account_id,
|
|
772
|
+
session_row.workspace_id,
|
|
773
|
+
session_row.owner_organization_membership_id,
|
|
774
|
+
session_row.owner_subject_id
|
|
775
|
+
)
|
|
776
|
+
)
|
|
777
|
+
)
|
|
778
|
+
);
|
|
779
|
+
|
|
780
|
+
DELETE FROM opengeni_private.insights_fact_read_runtime_capabilities
|
|
781
|
+
WHERE backend_pid = pg_catalog.pg_backend_pid()
|
|
782
|
+
AND transaction_id = pg_catalog.pg_current_xact_id_if_assigned()
|
|
783
|
+
AND capability_kind = 'usage_events';
|
|
784
|
+
RETURN;
|
|
785
|
+
EXCEPTION WHEN OTHERS THEN
|
|
786
|
+
DELETE FROM opengeni_private.insights_fact_read_runtime_capabilities
|
|
787
|
+
WHERE backend_pid = pg_catalog.pg_backend_pid()
|
|
788
|
+
AND transaction_id = pg_catalog.pg_current_xact_id_if_assigned()
|
|
789
|
+
AND capability_kind = 'usage_events';
|
|
790
|
+
RAISE;
|
|
791
|
+
END;
|
|
792
|
+
END
|
|
793
|
+
$function$;
|
|
794
|
+
$ddl$, data_schema);
|
|
795
|
+
END
|
|
796
|
+
$insights_usage_fact_read_functions$;
|
|
797
|
+
|
|
798
|
+
REVOKE ALL ON FUNCTION
|
|
799
|
+
opengeni_private.visible_workspace_insights_model_call_facts(
|
|
800
|
+
uuid, timestamp with time zone, timestamp with time zone
|
|
801
|
+
)
|
|
802
|
+
FROM PUBLIC;
|
|
803
|
+
REVOKE ALL ON FUNCTION
|
|
804
|
+
opengeni_private.visible_workspace_insights_model_call_facts(
|
|
805
|
+
uuid, timestamp with time zone, timestamp with time zone, text, text
|
|
806
|
+
)
|
|
807
|
+
FROM PUBLIC;
|
|
808
|
+
REVOKE ALL ON FUNCTION
|
|
809
|
+
opengeni_private.visible_workspace_insights_usage_events(
|
|
810
|
+
uuid, timestamp with time zone, timestamp with time zone
|
|
811
|
+
)
|
|
812
|
+
FROM PUBLIC;
|
|
813
|
+
REVOKE ALL ON FUNCTION
|
|
814
|
+
opengeni_private.visible_workspace_insights_usage_events(
|
|
815
|
+
uuid, timestamp with time zone, timestamp with time zone, text[]
|
|
816
|
+
)
|
|
817
|
+
FROM PUBLIC;
|
|
818
|
+
|
|
819
|
+
-- All entry points are subject to explicit or owner-default ACL drift. Reset
|
|
820
|
+
-- every non-owner grantee, including the released functions, then rebuild the
|
|
821
|
+
-- allow-list only from the migration runner's exact configured application
|
|
822
|
+
-- roles and 0356's dual-fact-SELECT eligibility rule.
|
|
823
|
+
DO $insights_fact_read_function_acl_reset$
|
|
824
|
+
DECLARE
|
|
825
|
+
role_name text;
|
|
826
|
+
target record;
|
|
827
|
+
BEGIN
|
|
828
|
+
FOR target IN
|
|
829
|
+
SELECT *
|
|
830
|
+
FROM (VALUES
|
|
831
|
+
(
|
|
832
|
+
'visible_workspace_insights_model_call_facts'::text,
|
|
833
|
+
'p_workspace_id uuid, p_since timestamp with time zone, p_until timestamp with time zone'::text,
|
|
834
|
+
'uuid, timestamp with time zone, timestamp with time zone'::text
|
|
835
|
+
),
|
|
836
|
+
(
|
|
837
|
+
'visible_workspace_insights_model_call_facts'::text,
|
|
838
|
+
'p_workspace_id uuid, p_since timestamp with time zone, p_until timestamp with time zone, p_provider text, p_model text'::text,
|
|
839
|
+
'uuid, timestamp with time zone, timestamp with time zone, text, text'::text
|
|
840
|
+
),
|
|
841
|
+
(
|
|
842
|
+
'visible_workspace_insights_usage_events'::text,
|
|
843
|
+
'p_workspace_id uuid, p_since timestamp with time zone, p_until timestamp with time zone'::text,
|
|
844
|
+
'uuid, timestamp with time zone, timestamp with time zone'::text
|
|
845
|
+
),
|
|
846
|
+
(
|
|
847
|
+
'visible_workspace_insights_usage_events'::text,
|
|
848
|
+
'p_workspace_id uuid, p_since timestamp with time zone, p_until timestamp with time zone, p_event_types text[]'::text,
|
|
849
|
+
'uuid, timestamp with time zone, timestamp with time zone, text[]'::text
|
|
850
|
+
)
|
|
851
|
+
) target_row(function_name, identity_arguments, call_arguments)
|
|
852
|
+
LOOP
|
|
853
|
+
FOR role_name IN
|
|
854
|
+
SELECT grantee_role.rolname
|
|
855
|
+
FROM pg_catalog.pg_proc procedure
|
|
856
|
+
INNER JOIN pg_catalog.pg_namespace namespace
|
|
857
|
+
ON namespace.oid = procedure.pronamespace
|
|
858
|
+
CROSS JOIN LATERAL pg_catalog.aclexplode(
|
|
859
|
+
coalesce(
|
|
860
|
+
procedure.proacl,
|
|
861
|
+
pg_catalog.acldefault('f', procedure.proowner)
|
|
862
|
+
)
|
|
863
|
+
) privilege
|
|
864
|
+
INNER JOIN pg_catalog.pg_roles grantee_role
|
|
865
|
+
ON grantee_role.oid = privilege.grantee
|
|
866
|
+
WHERE namespace.nspname = 'opengeni_private'
|
|
867
|
+
AND procedure.proname = target.function_name
|
|
868
|
+
AND pg_catalog.pg_get_function_identity_arguments(procedure.oid) =
|
|
869
|
+
target.identity_arguments
|
|
870
|
+
AND privilege.grantee <> 0
|
|
871
|
+
AND privilege.grantee <> procedure.proowner
|
|
872
|
+
GROUP BY grantee_role.rolname
|
|
873
|
+
ORDER BY grantee_role.rolname COLLATE "C"
|
|
874
|
+
LOOP
|
|
875
|
+
EXECUTE pg_catalog.format(
|
|
876
|
+
'REVOKE ALL ON FUNCTION opengeni_private.%I(%s) FROM %I',
|
|
877
|
+
target.function_name,
|
|
878
|
+
target.call_arguments,
|
|
879
|
+
role_name
|
|
880
|
+
);
|
|
881
|
+
END LOOP;
|
|
882
|
+
END LOOP;
|
|
883
|
+
END
|
|
884
|
+
$insights_fact_read_function_acl_reset$;
|
|
885
|
+
|
|
886
|
+
DO $insights_fact_read_function_grants$
|
|
887
|
+
DECLARE
|
|
888
|
+
data_schema text := pg_catalog.current_schema();
|
|
889
|
+
role_name text;
|
|
890
|
+
BEGIN
|
|
891
|
+
FOR role_name IN
|
|
892
|
+
SELECT role_row.rolname
|
|
893
|
+
FROM pg_catalog.jsonb_array_elements_text(
|
|
894
|
+
pg_catalog.current_setting('opengeni.migration_application_roles')::jsonb
|
|
895
|
+
) configured(value)
|
|
896
|
+
INNER JOIN pg_catalog.pg_roles role_row
|
|
897
|
+
ON role_row.rolname = configured.value
|
|
898
|
+
WHERE pg_catalog.has_table_privilege(
|
|
899
|
+
role_row.rolname,
|
|
900
|
+
pg_catalog.format('%I.model_call_facts', data_schema),
|
|
901
|
+
'SELECT'
|
|
902
|
+
)
|
|
903
|
+
AND pg_catalog.has_table_privilege(
|
|
904
|
+
role_row.rolname,
|
|
905
|
+
pg_catalog.format('%I.usage_events', data_schema),
|
|
906
|
+
'SELECT'
|
|
907
|
+
)
|
|
908
|
+
ORDER BY role_row.rolname COLLATE "C"
|
|
909
|
+
LOOP
|
|
910
|
+
EXECUTE pg_catalog.format(
|
|
911
|
+
'REVOKE ALL ON TABLE '
|
|
912
|
+
|| 'opengeni_private.insights_fact_read_runtime_capabilities FROM %I',
|
|
913
|
+
role_name
|
|
914
|
+
);
|
|
915
|
+
EXECUTE pg_catalog.format(
|
|
916
|
+
'GRANT USAGE ON SCHEMA opengeni_private TO %I',
|
|
917
|
+
role_name
|
|
918
|
+
);
|
|
919
|
+
EXECUTE pg_catalog.format(
|
|
920
|
+
'GRANT EXECUTE ON FUNCTION '
|
|
921
|
+
|| 'opengeni_private.visible_workspace_insights_model_call_facts('
|
|
922
|
+
|| 'uuid, timestamp with time zone, timestamp with time zone), '
|
|
923
|
+
|| 'opengeni_private.visible_workspace_insights_model_call_facts('
|
|
924
|
+
|| 'uuid, timestamp with time zone, timestamp with time zone, text, text), '
|
|
925
|
+
|| 'opengeni_private.visible_workspace_insights_usage_events('
|
|
926
|
+
|| 'uuid, timestamp with time zone, timestamp with time zone), '
|
|
927
|
+
|| 'opengeni_private.visible_workspace_insights_usage_events('
|
|
928
|
+
|| 'uuid, timestamp with time zone, timestamp with time zone, text[]) TO %I',
|
|
929
|
+
role_name
|
|
930
|
+
);
|
|
931
|
+
END LOOP;
|
|
932
|
+
END
|
|
933
|
+
$insights_fact_read_function_grants$;
|
|
934
|
+
|
|
935
|
+
RESET statement_timeout;
|
|
936
|
+
RESET lock_timeout;
|