@opengeni/db 0.28.9 → 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/attached-browser-devices.d.ts +42 -0
- package/dist/attempt-tool-catalogs.d.ts +16 -0
- package/dist/browser-auth.d.ts +299 -0
- package/dist/browser-downloads.d.ts +51 -0
- package/dist/browser-identities.d.ts +137 -0
- package/dist/browser-sessions.d.ts +354 -0
- package/dist/browser-state-artifacts.d.ts +91 -0
- 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-components.d.ts +37 -0
- package/dist/capability-integrations.d.ts +194 -0
- package/dist/chunk-5KTIEDX7.js +13200 -0
- package/dist/chunk-5KTIEDX7.js.map +1 -0
- package/dist/chunk-CQZ4QSP5.js +995 -0
- 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-JC5QPLUM.js +666 -0
- package/dist/chunk-JC5QPLUM.js.map +1 -0
- package/dist/chunk-P3RE4D2B.js +3535 -0
- package/dist/chunk-P3RE4D2B.js.map +1 -0
- package/dist/chunk-TAUTWOS5.js +259 -0
- package/dist/chunk-TAUTWOS5.js.map +1 -0
- package/dist/chunk-VKLB2ZGI.js +2389 -0
- package/dist/chunk-VKLB2ZGI.js.map +1 -0
- package/dist/codemode-operations.d.ts +117 -0
- package/dist/codex-token-resolver.d.ts +2 -2
- package/dist/company-profile-schema.d.ts +798 -0
- package/dist/company-profile.d.ts +268 -0
- package/dist/computer-sessions.d.ts +109 -0
- package/dist/connection-token-resolver.d.ts +9 -4
- package/dist/database.d.ts +57 -3
- package/dist/editable-artifact-durable-export.d.ts +153 -0
- package/dist/editable-artifact-durable-export.js +788 -0
- package/dist/editable-artifact-durable-export.js.map +1 -0
- package/dist/editable-artifact-materialization.d.ts +123 -0
- package/dist/editable-artifacts-schema.d.ts +4152 -0
- package/dist/editable-artifacts.d.ts +610 -0
- package/dist/editable-artifacts.js +26 -0
- package/dist/editable-artifacts.js.map +1 -0
- package/dist/generated-images.d.ts +139 -0
- package/dist/index.d.ts +1122 -126
- package/dist/index.js +42329 -18407
- package/dist/index.js.map +1 -1
- package/dist/insights.d.ts +73 -10
- package/dist/integration-bindings.d.ts +70 -0
- package/dist/integration-facets.d.ts +99 -0
- package/dist/interaction-revisions.d.ts +14 -0
- package/dist/interaction-schema.d.ts +6036 -0
- package/dist/knowledge-source-sync-schema.d.ts +1679 -0
- package/dist/knowledge-source-sync.d.ts +274 -0
- package/dist/memory-governance.d.ts +2 -2
- package/dist/memory-slack-delivery.d.ts +101 -0
- package/dist/new-session-drafts.d.ts +2 -2
- package/dist/pack-components.d.ts +76 -0
- package/dist/pack-installations.d.ts +86 -0
- package/dist/persistence-errors.d.ts +3 -3
- package/dist/plugin-packages.d.ts +126 -0
- package/dist/preference-registry.d.ts +1 -1
- package/dist/provision-roles.d.ts +9 -1
- package/dist/provision-roles.js +1 -1
- package/dist/runtime-posture.d.ts +19 -6
- package/dist/schema.d.ts +22654 -9359
- package/dist/schema.js +209 -3
- package/dist/scoped-knowledge.d.ts +97 -1
- package/dist/session-control.d.ts +33 -7
- package/dist/session-queue-commands.d.ts +19 -11
- package/dist/session-realtime-context.d.ts +2 -2
- package/dist/session-realtime-ledger.d.ts +4 -4
- package/dist/session-realtime-mirror.d.ts +2 -2
- package/dist/session-realtime-state.d.ts +1 -1
- package/dist/session-realtime-terminal.d.ts +1 -1
- package/dist/session-realtime.d.ts +7 -7
- 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/session-tool-call-settlement.d.ts +1 -1
- package/dist/slack-task-policy-schema.d.ts +847 -0
- package/dist/slack-task-policy.d.ts +65 -0
- package/dist/slack-user-link-access.d.ts +54 -0
- package/dist/task-notes-schema.d.ts +924 -0
- package/dist/task-notes.d.ts +85 -0
- package/dist/transcription-recordings.d.ts +2 -2
- package/dist/turn-initiator.d.ts +2 -2
- package/dist/video-generation.d.ts +225 -0
- package/dist/video-generation.js +68 -0
- package/dist/video-generation.js.map +1 -0
- package/dist/workspace-artifacts.d.ts +1 -1
- package/dist/workspace-instruction-policies.d.ts +1 -1
- package/dist/workspace-learning-policy-schema.d.ts +932 -0
- package/dist/workspace-learning-policy.d.ts +161 -0
- package/dist/xai-subscription.d.ts +326 -0
- package/drizzle/0183_model_call_provider_cost_estimates.sql +39 -0
- package/drizzle/0184_sandbox_drain_teardown_fence.sql +682 -0
- package/drizzle/0185_temporal_schedule_cleanup_outbox.sql +168 -0
- package/drizzle/0186_sandbox_capture_provider_contract.sql +400 -0
- package/drizzle/0187_generated_image_artifacts.sql +173 -0
- package/drizzle/0188_image_generation_retention_failure.sql +25 -0
- package/drizzle/0189_retained_session_image_formats.sql +13 -0
- package/drizzle/0190_timeline_annotations.sql +31 -0
- package/drizzle/0191_editable_artifact_engine.sql +3853 -0
- package/drizzle/0192_editable_artifact_live_tickets.sql +338 -0
- package/drizzle/0193_editable_artifact_authorization.sql +190 -0
- package/drizzle/0194_editable_artifact_durable_exports.sql +160 -0
- package/drizzle/0195_editable_artifact_import_authorization.sql +203 -0
- package/drizzle/0196_rig_provider_images.sql +152 -0
- package/drizzle/0197_knowledge_source_sync_schedules.sql +523 -0
- package/drizzle/0198_memory_slack_publication_delivery.sql +393 -0
- package/drizzle/0199_workspace_learning_policy.sql +980 -0
- package/drizzle/0201_company_profile_authority.sql +849 -0
- package/drizzle/0202_document_index_checkpoints.sql +85 -0
- package/drizzle/0203_durable_video_generation.sql +353 -0
- package/drizzle/0204_video_generation_funding.sql +44 -0
- package/drizzle/0205_attempt_tool_catalogs.sql +230 -0
- package/drizzle/0206_browser_sessions.sql +646 -0
- package/drizzle/0207_browser_identities.sql +379 -0
- package/drizzle/0208_attached_browser_devices.sql +165 -0
- package/drizzle/0209_computer_sessions.sql +575 -0
- package/drizzle/0210_browser_auth_network_interventions.sql +441 -0
- package/drizzle/0211_editable_artifact_session_links.sql +58 -0
- package/drizzle/0212_browser_state_transfer_hardening.sql +560 -0
- package/drizzle/0212_slack_installation_bindings.sql +348 -0
- package/drizzle/0213_browser_interaction_authority.sql +67 -0
- package/drizzle/0213_slack_user_link_access_requests.sql +177 -0
- package/drizzle/0214_browser_download_saves.sql +34 -0
- package/drizzle/0214_session_activity_commit_gate.sql +262 -0
- package/drizzle/0215_browser_controller_host.sql +385 -0
- package/drizzle/0215_capabilities_platform.sql +980 -0
- package/drizzle/0216_browser_auth_health_evidence.sql +137 -0
- package/drizzle/0216_pack_component_ownership.sql +235 -0
- package/drizzle/0217_capability_definition_delete_authority.sql +32 -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 +26 -5
- package/src/attached-browser-devices.ts +371 -0
- package/src/attempt-tool-catalogs.ts +131 -0
- package/src/browser-auth.ts +4373 -0
- package/src/browser-downloads.ts +517 -0
- package/src/browser-identities.ts +1385 -0
- package/src/browser-sessions.ts +2294 -0
- package/src/browser-state-artifacts.ts +449 -0
- package/src/canonical-human-identities.ts +317 -0
- package/src/capability-components.ts +166 -0
- package/src/capability-integrations.ts +1571 -0
- package/src/codemode-operations.ts +674 -0
- package/src/company-profile-schema.ts +143 -0
- package/src/company-profile.ts +968 -0
- package/src/computer-sessions.ts +1130 -0
- package/src/connection-token-resolver.ts +270 -25
- package/src/database.ts +468 -24
- package/src/editable-artifact-durable-export.ts +1201 -0
- package/src/editable-artifact-materialization.ts +893 -0
- package/src/editable-artifacts-schema.ts +879 -0
- package/src/editable-artifacts.ts +5404 -0
- package/src/generated-images.ts +740 -0
- package/src/index.ts +9963 -1465
- package/src/insights.ts +251 -23
- package/src/integration-bindings.ts +455 -0
- package/src/integration-facets.ts +862 -0
- package/src/interaction-revisions.ts +70 -0
- package/src/interaction-schema.ts +1606 -0
- package/src/knowledge-source-sync-schema.ts +192 -0
- package/src/knowledge-source-sync.ts +1922 -0
- package/src/memory-slack-delivery.ts +801 -0
- package/src/pack-components.ts +954 -0
- package/src/pack-installations.ts +886 -0
- package/src/persistence-errors.ts +4 -7
- package/src/plugin-packages.ts +1186 -0
- package/src/provision-roles.ts +534 -1
- package/src/runtime-posture-cli.ts +9 -0
- package/src/runtime-posture.ts +721 -5
- package/src/schema.ts +6270 -3159
- package/src/scoped-knowledge-schema.ts +1 -1
- package/src/scoped-knowledge.ts +655 -3
- package/src/session-control.ts +130 -42
- package/src/session-queue-commands.ts +265 -15
- package/src/session-realtime-context.ts +2 -2
- package/src/session-realtime-ledger.ts +3 -3
- package/src/session-realtime.ts +7 -7
- package/src/session-tenancy.ts +188 -0
- package/src/session-tool-call-settlement.ts +18 -3
- package/src/slack-task-policy-schema.ts +130 -0
- package/src/slack-task-policy.ts +341 -0
- package/src/slack-user-link-access.ts +702 -0
- package/src/task-notes-schema.ts +135 -0
- package/src/task-notes.ts +178 -0
- package/src/video-generation.ts +1530 -0
- package/src/workspace-artifacts.ts +1 -1
- package/src/workspace-learning-policy-schema.ts +139 -0
- package/src/workspace-learning-policy.ts +595 -0
- package/src/xai-subscription.ts +1887 -0
- package/dist/chunk-P6CUHXQZ.js +0 -7248
- package/dist/chunk-P6CUHXQZ.js.map +0 -1
- package/dist/chunk-VHBFHMPC.js +0 -1219
- package/dist/chunk-VHBFHMPC.js.map +0 -1
|
@@ -0,0 +1,980 @@
|
|
|
1
|
+
-- deployment-mode: rolling
|
|
2
|
+
-- Add the versioned workspace learning-policy domain and accepted-attempt
|
|
3
|
+
-- snapshot service. This migration does not add a learning router, evaluator,
|
|
4
|
+
-- activation controller, prompt composition, command/tool surface, UI, or
|
|
5
|
+
-- connector-specific behavior. Existing Memory and memory_save paths remain
|
|
6
|
+
-- unchanged.
|
|
7
|
+
|
|
8
|
+
SET LOCAL lock_timeout = '5s';
|
|
9
|
+
SET LOCAL statement_timeout = '10min';
|
|
10
|
+
|
|
11
|
+
CREATE SEQUENCE "workspace_learning_policy_revision_seq" AS bigint;
|
|
12
|
+
|
|
13
|
+
CREATE OR REPLACE FUNCTION workspace_learning_policy_source_overrides_valid(value jsonb)
|
|
14
|
+
RETURNS boolean
|
|
15
|
+
LANGUAGE plpgsql
|
|
16
|
+
IMMUTABLE
|
|
17
|
+
AS $$
|
|
18
|
+
DECLARE
|
|
19
|
+
entry jsonb;
|
|
20
|
+
canonical jsonb;
|
|
21
|
+
BEGIN
|
|
22
|
+
IF jsonb_typeof(value) IS DISTINCT FROM 'array'
|
|
23
|
+
OR jsonb_array_length(value) > 256
|
|
24
|
+
OR octet_length(convert_to(value::text, 'UTF8')) > 65536
|
|
25
|
+
THEN
|
|
26
|
+
RETURN false;
|
|
27
|
+
END IF;
|
|
28
|
+
|
|
29
|
+
FOR entry IN SELECT item FROM jsonb_array_elements(value) AS entries(item) LOOP
|
|
30
|
+
IF jsonb_typeof(entry) IS DISTINCT FROM 'object'
|
|
31
|
+
OR (SELECT count(*) FROM jsonb_object_keys(entry)) <> 3
|
|
32
|
+
OR NOT (entry ? 'kind' AND entry ? 'id' AND entry ? 'mode')
|
|
33
|
+
OR jsonb_typeof(entry->'kind') IS DISTINCT FROM 'string'
|
|
34
|
+
OR jsonb_typeof(entry->'id') IS DISTINCT FROM 'string'
|
|
35
|
+
OR jsonb_typeof(entry->'mode') IS DISTINCT FROM 'string'
|
|
36
|
+
OR entry->>'kind' IS DISTINCT FROM lower(btrim(entry->>'kind'))
|
|
37
|
+
OR length(entry->>'kind') NOT BETWEEN 1 AND 96
|
|
38
|
+
OR entry->>'kind' !~ '^[a-z0-9](?:[a-z0-9._-]*[a-z0-9])?$'
|
|
39
|
+
OR entry->>'id' IS DISTINCT FROM btrim(entry->>'id')
|
|
40
|
+
OR length(entry->>'id') NOT BETWEEN 1 AND 1024
|
|
41
|
+
OR entry->>'mode' NOT IN ('off', 'suggest', 'automatic')
|
|
42
|
+
THEN
|
|
43
|
+
RETURN false;
|
|
44
|
+
END IF;
|
|
45
|
+
END LOOP;
|
|
46
|
+
|
|
47
|
+
IF (
|
|
48
|
+
SELECT count(*)
|
|
49
|
+
FROM (
|
|
50
|
+
SELECT DISTINCT candidate->>'kind', candidate->>'id'
|
|
51
|
+
FROM jsonb_array_elements(value) AS candidates(candidate)
|
|
52
|
+
) distinct_entries
|
|
53
|
+
) <> jsonb_array_length(value)
|
|
54
|
+
THEN
|
|
55
|
+
RETURN false;
|
|
56
|
+
END IF;
|
|
57
|
+
|
|
58
|
+
SELECT coalesce(
|
|
59
|
+
jsonb_agg(candidate ORDER BY candidate->>'kind' COLLATE "C", candidate->>'id' COLLATE "C"),
|
|
60
|
+
'[]'::jsonb
|
|
61
|
+
) INTO canonical
|
|
62
|
+
FROM jsonb_array_elements(value) AS candidates(candidate);
|
|
63
|
+
|
|
64
|
+
RETURN value = canonical;
|
|
65
|
+
END;
|
|
66
|
+
$$;
|
|
67
|
+
|
|
68
|
+
REVOKE ALL ON FUNCTION workspace_learning_policy_source_overrides_valid(jsonb) FROM PUBLIC;
|
|
69
|
+
|
|
70
|
+
CREATE OR REPLACE FUNCTION workspace_learning_policy_hash(
|
|
71
|
+
p_workspace_mode text,
|
|
72
|
+
p_source_overrides jsonb
|
|
73
|
+
) RETURNS text
|
|
74
|
+
LANGUAGE sql
|
|
75
|
+
IMMUTABLE
|
|
76
|
+
AS $$
|
|
77
|
+
SELECT encode(
|
|
78
|
+
sha256(convert_to(
|
|
79
|
+
jsonb_build_array(
|
|
80
|
+
'workspace_learning_policy',
|
|
81
|
+
1,
|
|
82
|
+
p_workspace_mode,
|
|
83
|
+
p_source_overrides
|
|
84
|
+
)::text,
|
|
85
|
+
'UTF8'
|
|
86
|
+
)),
|
|
87
|
+
'hex'
|
|
88
|
+
);
|
|
89
|
+
$$;
|
|
90
|
+
|
|
91
|
+
REVOKE ALL ON FUNCTION workspace_learning_policy_hash(text, jsonb) FROM PUBLIC;
|
|
92
|
+
|
|
93
|
+
CREATE OR REPLACE FUNCTION workspace_learning_policy_snapshot_hash(
|
|
94
|
+
p_revision_id uuid,
|
|
95
|
+
p_revision bigint,
|
|
96
|
+
p_policy_hash text,
|
|
97
|
+
p_activation_version bigint,
|
|
98
|
+
p_activated_at timestamptz,
|
|
99
|
+
p_workspace_mode text,
|
|
100
|
+
p_source_overrides jsonb
|
|
101
|
+
) RETURNS text
|
|
102
|
+
LANGUAGE sql
|
|
103
|
+
IMMUTABLE
|
|
104
|
+
AS $$
|
|
105
|
+
SELECT encode(
|
|
106
|
+
sha256(convert_to(
|
|
107
|
+
jsonb_build_array(
|
|
108
|
+
'workspace_learning_policy_snapshot',
|
|
109
|
+
1,
|
|
110
|
+
p_revision_id,
|
|
111
|
+
p_revision,
|
|
112
|
+
p_policy_hash,
|
|
113
|
+
p_activation_version,
|
|
114
|
+
CASE WHEN p_activated_at IS NULL THEN NULL ELSE to_char(
|
|
115
|
+
p_activated_at AT TIME ZONE 'UTC',
|
|
116
|
+
'YYYY-MM-DD"T"HH24:MI:SS.US"Z"'
|
|
117
|
+
) END,
|
|
118
|
+
p_workspace_mode,
|
|
119
|
+
p_source_overrides
|
|
120
|
+
)::text,
|
|
121
|
+
'UTF8'
|
|
122
|
+
)),
|
|
123
|
+
'hex'
|
|
124
|
+
);
|
|
125
|
+
$$;
|
|
126
|
+
|
|
127
|
+
REVOKE ALL ON FUNCTION workspace_learning_policy_snapshot_hash(
|
|
128
|
+
uuid, bigint, text, bigint, timestamptz, text, jsonb
|
|
129
|
+
) FROM PUBLIC;
|
|
130
|
+
|
|
131
|
+
CREATE TABLE "workspace_learning_policy_revisions" (
|
|
132
|
+
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
133
|
+
"operation_id" uuid NOT NULL,
|
|
134
|
+
"request_fingerprint" text NOT NULL,
|
|
135
|
+
"account_id" uuid NOT NULL REFERENCES "managed_accounts"("id") ON DELETE CASCADE,
|
|
136
|
+
"workspace_id" uuid NOT NULL REFERENCES "workspaces"("id") ON DELETE CASCADE,
|
|
137
|
+
"revision" bigint NOT NULL DEFAULT nextval('workspace_learning_policy_revision_seq'),
|
|
138
|
+
"workspace_mode" text NOT NULL,
|
|
139
|
+
"source_overrides" jsonb NOT NULL DEFAULT '[]'::jsonb,
|
|
140
|
+
"policy_hash" text NOT NULL,
|
|
141
|
+
"supersedes_revision_id" uuid REFERENCES "workspace_learning_policy_revisions"("id") ON DELETE RESTRICT,
|
|
142
|
+
"created_by_subject_id" text NOT NULL,
|
|
143
|
+
"created_at" timestamptz NOT NULL DEFAULT now(),
|
|
144
|
+
CONSTRAINT "workspace_learning_policy_revisions_revision_chk" CHECK ("revision" > 0),
|
|
145
|
+
CONSTRAINT "workspace_learning_policy_revisions_mode_chk" CHECK (
|
|
146
|
+
"workspace_mode" IN ('off', 'suggest', 'automatic')
|
|
147
|
+
),
|
|
148
|
+
CONSTRAINT "workspace_learning_policy_revisions_overrides_chk" CHECK (
|
|
149
|
+
workspace_learning_policy_source_overrides_valid("source_overrides")
|
|
150
|
+
),
|
|
151
|
+
CONSTRAINT "workspace_learning_policy_revisions_hash_chk" CHECK (
|
|
152
|
+
"policy_hash" ~ '^[0-9a-f]{64}$'
|
|
153
|
+
AND "policy_hash" = workspace_learning_policy_hash("workspace_mode", "source_overrides")
|
|
154
|
+
),
|
|
155
|
+
CONSTRAINT "workspace_learning_policy_revisions_operation_chk" CHECK (
|
|
156
|
+
"request_fingerprint" ~ '^[0-9a-f]{64}$'
|
|
157
|
+
),
|
|
158
|
+
CONSTRAINT "workspace_learning_policy_revisions_actor_chk" CHECK (
|
|
159
|
+
length(btrim("created_by_subject_id")) BETWEEN 1 AND 1024
|
|
160
|
+
),
|
|
161
|
+
CONSTRAINT "workspace_learning_policy_revisions_workspace_operation_uq"
|
|
162
|
+
UNIQUE ("workspace_id", "operation_id"),
|
|
163
|
+
CONSTRAINT "workspace_learning_policy_revisions_workspace_revision_uq"
|
|
164
|
+
UNIQUE ("workspace_id", "revision"),
|
|
165
|
+
CONSTRAINT "workspace_learning_policy_revisions_workspace_identity_uq"
|
|
166
|
+
UNIQUE ("account_id", "workspace_id", "id")
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
CREATE INDEX "workspace_learning_policy_revisions_workspace_history_idx"
|
|
170
|
+
ON "workspace_learning_policy_revisions" ("workspace_id", "revision" DESC);
|
|
171
|
+
|
|
172
|
+
CREATE TABLE "workspace_learning_policy_heads" (
|
|
173
|
+
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
174
|
+
"account_id" uuid NOT NULL REFERENCES "managed_accounts"("id") ON DELETE CASCADE,
|
|
175
|
+
"workspace_id" uuid NOT NULL REFERENCES "workspaces"("id") ON DELETE CASCADE,
|
|
176
|
+
"revision_id" uuid NOT NULL,
|
|
177
|
+
"revision" bigint NOT NULL,
|
|
178
|
+
"policy_hash" text NOT NULL,
|
|
179
|
+
"activation_version" bigint NOT NULL,
|
|
180
|
+
"activated_at" timestamptz NOT NULL DEFAULT now(),
|
|
181
|
+
CONSTRAINT "workspace_learning_policy_heads_revision_fk"
|
|
182
|
+
FOREIGN KEY ("account_id", "workspace_id", "revision_id")
|
|
183
|
+
REFERENCES "workspace_learning_policy_revisions"("account_id", "workspace_id", "id")
|
|
184
|
+
ON DELETE RESTRICT,
|
|
185
|
+
CONSTRAINT "workspace_learning_policy_heads_workspace_uq" UNIQUE ("workspace_id"),
|
|
186
|
+
CONSTRAINT "workspace_learning_policy_heads_version_chk" CHECK (
|
|
187
|
+
"revision" > 0
|
|
188
|
+
AND "activation_version" > 0
|
|
189
|
+
AND "policy_hash" ~ '^[0-9a-f]{64}$'
|
|
190
|
+
)
|
|
191
|
+
);
|
|
192
|
+
|
|
193
|
+
CREATE TABLE "workspace_learning_policy_activation_events" (
|
|
194
|
+
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
195
|
+
"operation_id" uuid NOT NULL,
|
|
196
|
+
"request_fingerprint" text NOT NULL,
|
|
197
|
+
"account_id" uuid NOT NULL REFERENCES "managed_accounts"("id") ON DELETE CASCADE,
|
|
198
|
+
"workspace_id" uuid NOT NULL REFERENCES "workspaces"("id") ON DELETE CASCADE,
|
|
199
|
+
"type" text NOT NULL,
|
|
200
|
+
"activation_version" bigint NOT NULL,
|
|
201
|
+
"old_revision_id" uuid,
|
|
202
|
+
"old_revision" bigint,
|
|
203
|
+
"old_policy_hash" text,
|
|
204
|
+
"new_revision_id" uuid NOT NULL,
|
|
205
|
+
"new_revision" bigint NOT NULL,
|
|
206
|
+
"new_policy_hash" text NOT NULL,
|
|
207
|
+
"actor_subject_id" text NOT NULL,
|
|
208
|
+
"reason" text NOT NULL,
|
|
209
|
+
"created_at" timestamptz NOT NULL DEFAULT now(),
|
|
210
|
+
CONSTRAINT "workspace_learning_policy_events_type_chk" CHECK (
|
|
211
|
+
"type" IN ('activate', 'rollback')
|
|
212
|
+
),
|
|
213
|
+
CONSTRAINT "workspace_learning_policy_events_old_revision_chk" CHECK (
|
|
214
|
+
("old_revision_id" IS NULL AND "old_revision" IS NULL AND "old_policy_hash" IS NULL)
|
|
215
|
+
OR (
|
|
216
|
+
"old_revision_id" IS NOT NULL
|
|
217
|
+
AND "old_revision" > 0
|
|
218
|
+
AND "old_policy_hash" ~ '^[0-9a-f]{64}$'
|
|
219
|
+
)
|
|
220
|
+
),
|
|
221
|
+
CONSTRAINT "workspace_learning_policy_events_new_revision_chk" CHECK (
|
|
222
|
+
"new_revision" > 0
|
|
223
|
+
AND "new_policy_hash" ~ '^[0-9a-f]{64}$'
|
|
224
|
+
AND "activation_version" > 0
|
|
225
|
+
),
|
|
226
|
+
CONSTRAINT "workspace_learning_policy_events_operation_chk" CHECK (
|
|
227
|
+
"request_fingerprint" ~ '^[0-9a-f]{64}$'
|
|
228
|
+
),
|
|
229
|
+
CONSTRAINT "workspace_learning_policy_events_audit_chk" CHECK (
|
|
230
|
+
length(btrim("actor_subject_id")) BETWEEN 1 AND 1024
|
|
231
|
+
AND length(btrim("reason")) BETWEEN 1 AND 4096
|
|
232
|
+
),
|
|
233
|
+
CONSTRAINT "workspace_learning_policy_events_workspace_operation_uq"
|
|
234
|
+
UNIQUE ("workspace_id", "operation_id"),
|
|
235
|
+
CONSTRAINT "workspace_learning_policy_events_workspace_version_uq"
|
|
236
|
+
UNIQUE ("workspace_id", "activation_version")
|
|
237
|
+
);
|
|
238
|
+
|
|
239
|
+
CREATE INDEX "workspace_learning_policy_events_workspace_time_idx"
|
|
240
|
+
ON "workspace_learning_policy_activation_events" ("workspace_id", "created_at" DESC, "id");
|
|
241
|
+
|
|
242
|
+
CREATE TABLE "workspace_learning_policy_snapshots" (
|
|
243
|
+
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
244
|
+
"account_id" uuid NOT NULL REFERENCES "managed_accounts"("id") ON DELETE CASCADE,
|
|
245
|
+
"workspace_id" uuid NOT NULL REFERENCES "workspaces"("id") ON DELETE CASCADE,
|
|
246
|
+
"session_id" uuid NOT NULL REFERENCES "sessions"("id") ON DELETE CASCADE,
|
|
247
|
+
"turn_id" uuid NOT NULL REFERENCES "session_turns"("id") ON DELETE CASCADE,
|
|
248
|
+
"attempt_id" uuid NOT NULL REFERENCES "session_turn_attempts"("id") ON DELETE CASCADE,
|
|
249
|
+
"execution_generation" integer NOT NULL,
|
|
250
|
+
"revision_id" uuid,
|
|
251
|
+
"revision" bigint,
|
|
252
|
+
"policy_hash" text,
|
|
253
|
+
"activation_version" bigint NOT NULL,
|
|
254
|
+
"activated_at" timestamptz,
|
|
255
|
+
"workspace_mode" text NOT NULL,
|
|
256
|
+
"source_overrides" jsonb NOT NULL,
|
|
257
|
+
"snapshot_hash" text NOT NULL,
|
|
258
|
+
"created_at" timestamptz NOT NULL DEFAULT now(),
|
|
259
|
+
CONSTRAINT "workspace_learning_policy_snapshots_generation_chk" CHECK (
|
|
260
|
+
"execution_generation" > 0
|
|
261
|
+
),
|
|
262
|
+
CONSTRAINT "workspace_learning_policy_snapshots_identity_chk" CHECK (
|
|
263
|
+
(
|
|
264
|
+
"revision_id" IS NULL
|
|
265
|
+
AND "revision" IS NULL
|
|
266
|
+
AND "policy_hash" IS NULL
|
|
267
|
+
AND "activation_version" = 0
|
|
268
|
+
AND "activated_at" IS NULL
|
|
269
|
+
AND "workspace_mode" = 'off'
|
|
270
|
+
AND "source_overrides" = '[]'::jsonb
|
|
271
|
+
)
|
|
272
|
+
OR (
|
|
273
|
+
"revision_id" IS NOT NULL
|
|
274
|
+
AND "revision" > 0
|
|
275
|
+
AND "policy_hash" ~ '^[0-9a-f]{64}$'
|
|
276
|
+
AND "activation_version" > 0
|
|
277
|
+
AND "activated_at" IS NOT NULL
|
|
278
|
+
)
|
|
279
|
+
),
|
|
280
|
+
CONSTRAINT "workspace_learning_policy_snapshots_mode_chk" CHECK (
|
|
281
|
+
"workspace_mode" IN ('off', 'suggest', 'automatic')
|
|
282
|
+
),
|
|
283
|
+
CONSTRAINT "workspace_learning_policy_snapshots_overrides_chk" CHECK (
|
|
284
|
+
workspace_learning_policy_source_overrides_valid("source_overrides")
|
|
285
|
+
),
|
|
286
|
+
CONSTRAINT "workspace_learning_policy_snapshots_hash_chk" CHECK (
|
|
287
|
+
"snapshot_hash" ~ '^[0-9a-f]{64}$'
|
|
288
|
+
AND "snapshot_hash" = workspace_learning_policy_snapshot_hash(
|
|
289
|
+
"revision_id",
|
|
290
|
+
"revision",
|
|
291
|
+
"policy_hash",
|
|
292
|
+
"activation_version",
|
|
293
|
+
"activated_at",
|
|
294
|
+
"workspace_mode",
|
|
295
|
+
"source_overrides"
|
|
296
|
+
)
|
|
297
|
+
),
|
|
298
|
+
CONSTRAINT "workspace_learning_policy_snapshots_attempt_uq"
|
|
299
|
+
UNIQUE ("account_id", "workspace_id", "attempt_id")
|
|
300
|
+
);
|
|
301
|
+
|
|
302
|
+
CREATE INDEX "workspace_learning_policy_snapshots_workspace_time_idx"
|
|
303
|
+
ON "workspace_learning_policy_snapshots" ("workspace_id", "created_at" DESC, "id");
|
|
304
|
+
|
|
305
|
+
CREATE OR REPLACE FUNCTION workspace_learning_policy_validate_revision_link()
|
|
306
|
+
RETURNS trigger
|
|
307
|
+
LANGUAGE plpgsql
|
|
308
|
+
AS $$
|
|
309
|
+
BEGIN
|
|
310
|
+
IF NEW."supersedes_revision_id" IS NOT NULL AND NOT EXISTS (
|
|
311
|
+
SELECT 1
|
|
312
|
+
FROM "workspace_learning_policy_revisions" previous
|
|
313
|
+
WHERE previous."id" = NEW."supersedes_revision_id"
|
|
314
|
+
AND previous."account_id" = NEW."account_id"
|
|
315
|
+
AND previous."workspace_id" = NEW."workspace_id"
|
|
316
|
+
) THEN
|
|
317
|
+
RAISE EXCEPTION 'superseded learning-policy revision must belong to the exact workspace'
|
|
318
|
+
USING ERRCODE = '23514';
|
|
319
|
+
END IF;
|
|
320
|
+
RETURN NEW;
|
|
321
|
+
END;
|
|
322
|
+
$$;
|
|
323
|
+
|
|
324
|
+
CREATE TRIGGER workspace_learning_policy_revisions_validate_link
|
|
325
|
+
BEFORE INSERT OR UPDATE ON "workspace_learning_policy_revisions"
|
|
326
|
+
FOR EACH ROW EXECUTE FUNCTION workspace_learning_policy_validate_revision_link();
|
|
327
|
+
|
|
328
|
+
CREATE OR REPLACE FUNCTION workspace_learning_policy_validate_head()
|
|
329
|
+
RETURNS trigger
|
|
330
|
+
LANGUAGE plpgsql
|
|
331
|
+
AS $$
|
|
332
|
+
BEGIN
|
|
333
|
+
IF NOT EXISTS (
|
|
334
|
+
SELECT 1
|
|
335
|
+
FROM "workspace_learning_policy_revisions" revision
|
|
336
|
+
WHERE revision."id" = NEW."revision_id"
|
|
337
|
+
AND revision."account_id" = NEW."account_id"
|
|
338
|
+
AND revision."workspace_id" = NEW."workspace_id"
|
|
339
|
+
AND revision."revision" = NEW."revision"
|
|
340
|
+
AND revision."policy_hash" = NEW."policy_hash"
|
|
341
|
+
) THEN
|
|
342
|
+
RAISE EXCEPTION 'learning-policy head must identify an exact immutable revision'
|
|
343
|
+
USING ERRCODE = '23514';
|
|
344
|
+
END IF;
|
|
345
|
+
RETURN NEW;
|
|
346
|
+
END;
|
|
347
|
+
$$;
|
|
348
|
+
|
|
349
|
+
CREATE TRIGGER workspace_learning_policy_heads_validate_revision
|
|
350
|
+
BEFORE INSERT OR UPDATE ON "workspace_learning_policy_heads"
|
|
351
|
+
FOR EACH ROW EXECUTE FUNCTION workspace_learning_policy_validate_head();
|
|
352
|
+
|
|
353
|
+
CREATE OR REPLACE FUNCTION workspace_learning_policy_guard_head_mutation()
|
|
354
|
+
RETURNS trigger
|
|
355
|
+
LANGUAGE plpgsql
|
|
356
|
+
AS $$
|
|
357
|
+
DECLARE
|
|
358
|
+
lifecycle_workspace_id text;
|
|
359
|
+
BEGIN
|
|
360
|
+
IF TG_OP = 'DELETE'
|
|
361
|
+
AND pg_trigger_depth() > 1
|
|
362
|
+
AND NOT EXISTS (
|
|
363
|
+
SELECT 1 FROM "workspaces" workspace WHERE workspace."id" = OLD."workspace_id"
|
|
364
|
+
)
|
|
365
|
+
THEN
|
|
366
|
+
RETURN OLD;
|
|
367
|
+
END IF;
|
|
368
|
+
lifecycle_workspace_id := current_setting(
|
|
369
|
+
'opengeni.workspace_learning_policy_lifecycle_workspace_id',
|
|
370
|
+
true
|
|
371
|
+
);
|
|
372
|
+
IF lifecycle_workspace_id IS DISTINCT FROM coalesce(NEW."workspace_id", OLD."workspace_id")::text THEN
|
|
373
|
+
RAISE EXCEPTION 'learning-policy heads change only through the lifecycle function'
|
|
374
|
+
USING ERRCODE = '55000';
|
|
375
|
+
END IF;
|
|
376
|
+
IF TG_OP = 'UPDATE' THEN
|
|
377
|
+
IF NEW."id" IS DISTINCT FROM OLD."id"
|
|
378
|
+
OR NEW."account_id" IS DISTINCT FROM OLD."account_id"
|
|
379
|
+
OR NEW."workspace_id" IS DISTINCT FROM OLD."workspace_id"
|
|
380
|
+
OR NEW."activation_version" IS DISTINCT FROM OLD."activation_version" + 1
|
|
381
|
+
THEN
|
|
382
|
+
RAISE EXCEPTION 'invalid learning-policy head transition'
|
|
383
|
+
USING ERRCODE = '23514';
|
|
384
|
+
END IF;
|
|
385
|
+
ELSIF TG_OP = 'DELETE' THEN
|
|
386
|
+
RAISE EXCEPTION 'learning-policy heads cannot be deleted directly'
|
|
387
|
+
USING ERRCODE = '55000';
|
|
388
|
+
END IF;
|
|
389
|
+
RETURN NEW;
|
|
390
|
+
END;
|
|
391
|
+
$$;
|
|
392
|
+
|
|
393
|
+
CREATE TRIGGER workspace_learning_policy_heads_lifecycle_only
|
|
394
|
+
BEFORE INSERT OR UPDATE OR DELETE ON "workspace_learning_policy_heads"
|
|
395
|
+
FOR EACH ROW EXECUTE FUNCTION workspace_learning_policy_guard_head_mutation();
|
|
396
|
+
|
|
397
|
+
CREATE OR REPLACE FUNCTION workspace_learning_policy_validate_event()
|
|
398
|
+
RETURNS trigger
|
|
399
|
+
LANGUAGE plpgsql
|
|
400
|
+
AS $$
|
|
401
|
+
BEGIN
|
|
402
|
+
IF NOT EXISTS (
|
|
403
|
+
SELECT 1
|
|
404
|
+
FROM "workspace_learning_policy_revisions" revision
|
|
405
|
+
WHERE revision."id" = NEW."new_revision_id"
|
|
406
|
+
AND revision."account_id" = NEW."account_id"
|
|
407
|
+
AND revision."workspace_id" = NEW."workspace_id"
|
|
408
|
+
AND revision."revision" = NEW."new_revision"
|
|
409
|
+
AND revision."policy_hash" = NEW."new_policy_hash"
|
|
410
|
+
) THEN
|
|
411
|
+
RAISE EXCEPTION 'learning-policy activation event has an invalid new revision'
|
|
412
|
+
USING ERRCODE = '23514';
|
|
413
|
+
END IF;
|
|
414
|
+
IF NEW."old_revision_id" IS NOT NULL AND NOT EXISTS (
|
|
415
|
+
SELECT 1
|
|
416
|
+
FROM "workspace_learning_policy_revisions" revision
|
|
417
|
+
WHERE revision."id" = NEW."old_revision_id"
|
|
418
|
+
AND revision."account_id" = NEW."account_id"
|
|
419
|
+
AND revision."workspace_id" = NEW."workspace_id"
|
|
420
|
+
AND revision."revision" = NEW."old_revision"
|
|
421
|
+
AND revision."policy_hash" = NEW."old_policy_hash"
|
|
422
|
+
) THEN
|
|
423
|
+
RAISE EXCEPTION 'learning-policy activation event has an invalid old revision'
|
|
424
|
+
USING ERRCODE = '23514';
|
|
425
|
+
END IF;
|
|
426
|
+
RETURN NEW;
|
|
427
|
+
END;
|
|
428
|
+
$$;
|
|
429
|
+
|
|
430
|
+
CREATE TRIGGER workspace_learning_policy_events_validate_revisions
|
|
431
|
+
BEFORE INSERT OR UPDATE ON "workspace_learning_policy_activation_events"
|
|
432
|
+
FOR EACH ROW EXECUTE FUNCTION workspace_learning_policy_validate_event();
|
|
433
|
+
|
|
434
|
+
CREATE OR REPLACE FUNCTION workspace_learning_policy_reject_history_mutation()
|
|
435
|
+
RETURNS trigger
|
|
436
|
+
LANGUAGE plpgsql
|
|
437
|
+
AS $$
|
|
438
|
+
BEGIN
|
|
439
|
+
IF TG_OP = 'DELETE'
|
|
440
|
+
AND pg_trigger_depth() > 1
|
|
441
|
+
AND NOT EXISTS (
|
|
442
|
+
SELECT 1 FROM "workspaces" workspace WHERE workspace."id" = OLD."workspace_id"
|
|
443
|
+
)
|
|
444
|
+
THEN
|
|
445
|
+
RETURN OLD;
|
|
446
|
+
END IF;
|
|
447
|
+
RAISE EXCEPTION 'workspace learning-policy history is immutable'
|
|
448
|
+
USING ERRCODE = '55000';
|
|
449
|
+
END;
|
|
450
|
+
$$;
|
|
451
|
+
|
|
452
|
+
CREATE TRIGGER workspace_learning_policy_revisions_immutable
|
|
453
|
+
BEFORE UPDATE OR DELETE ON "workspace_learning_policy_revisions"
|
|
454
|
+
FOR EACH ROW EXECUTE FUNCTION workspace_learning_policy_reject_history_mutation();
|
|
455
|
+
|
|
456
|
+
CREATE TRIGGER workspace_learning_policy_events_immutable
|
|
457
|
+
BEFORE UPDATE OR DELETE ON "workspace_learning_policy_activation_events"
|
|
458
|
+
FOR EACH ROW EXECUTE FUNCTION workspace_learning_policy_reject_history_mutation();
|
|
459
|
+
|
|
460
|
+
CREATE OR REPLACE FUNCTION workspace_learning_policy_reject_snapshot_mutation()
|
|
461
|
+
RETURNS trigger
|
|
462
|
+
LANGUAGE plpgsql
|
|
463
|
+
AS $$
|
|
464
|
+
BEGIN
|
|
465
|
+
-- Parent lifecycle deletion is the sole mutation exception. PostgreSQL's
|
|
466
|
+
-- cascading constraint trigger runs only after its parent row is absent;
|
|
467
|
+
-- require both nested trigger context and one missing ownership edge so
|
|
468
|
+
-- direct or unrelated-trigger deletes remain fail-closed.
|
|
469
|
+
IF TG_OP = 'DELETE'
|
|
470
|
+
AND pg_trigger_depth() > 1
|
|
471
|
+
AND (
|
|
472
|
+
NOT EXISTS (SELECT 1 FROM "managed_accounts" WHERE "id" = OLD."account_id")
|
|
473
|
+
OR NOT EXISTS (SELECT 1 FROM "workspaces" WHERE "id" = OLD."workspace_id")
|
|
474
|
+
OR NOT EXISTS (SELECT 1 FROM "sessions" WHERE "id" = OLD."session_id")
|
|
475
|
+
OR NOT EXISTS (SELECT 1 FROM "session_turns" WHERE "id" = OLD."turn_id")
|
|
476
|
+
OR NOT EXISTS (SELECT 1 FROM "session_turn_attempts" WHERE "id" = OLD."attempt_id")
|
|
477
|
+
)
|
|
478
|
+
THEN
|
|
479
|
+
RETURN OLD;
|
|
480
|
+
END IF;
|
|
481
|
+
RAISE EXCEPTION 'workspace learning-policy snapshots are immutable'
|
|
482
|
+
USING ERRCODE = '55000';
|
|
483
|
+
END;
|
|
484
|
+
$$;
|
|
485
|
+
|
|
486
|
+
CREATE TRIGGER workspace_learning_policy_snapshots_immutable
|
|
487
|
+
BEFORE UPDATE OR DELETE ON "workspace_learning_policy_snapshots"
|
|
488
|
+
FOR EACH ROW EXECUTE FUNCTION workspace_learning_policy_reject_snapshot_mutation();
|
|
489
|
+
|
|
490
|
+
CREATE OR REPLACE FUNCTION workspace_learning_policy_canonical_at(
|
|
491
|
+
p_account_id uuid,
|
|
492
|
+
p_workspace_id uuid,
|
|
493
|
+
p_accepted_at timestamptz
|
|
494
|
+
) RETURNS jsonb
|
|
495
|
+
LANGUAGE sql
|
|
496
|
+
STABLE
|
|
497
|
+
AS $$
|
|
498
|
+
SELECT CASE WHEN active."id" IS NULL THEN
|
|
499
|
+
jsonb_build_object(
|
|
500
|
+
'revisionId', NULL,
|
|
501
|
+
'revision', NULL,
|
|
502
|
+
'policyHash', NULL,
|
|
503
|
+
'activationVersion', 0,
|
|
504
|
+
'activatedAt', NULL,
|
|
505
|
+
'workspaceMode', 'off',
|
|
506
|
+
'sourceOverrides', '[]'::jsonb
|
|
507
|
+
)
|
|
508
|
+
ELSE
|
|
509
|
+
jsonb_build_object(
|
|
510
|
+
'revisionId', revision."id"::text,
|
|
511
|
+
'revision', revision."revision",
|
|
512
|
+
'policyHash', revision."policy_hash",
|
|
513
|
+
'activationVersion', active."activation_version",
|
|
514
|
+
'activatedAt', to_char(
|
|
515
|
+
active."created_at" AT TIME ZONE 'UTC',
|
|
516
|
+
'YYYY-MM-DD"T"HH24:MI:SS.US"Z"'
|
|
517
|
+
),
|
|
518
|
+
'workspaceMode', revision."workspace_mode",
|
|
519
|
+
'sourceOverrides', revision."source_overrides"
|
|
520
|
+
)
|
|
521
|
+
END
|
|
522
|
+
FROM (SELECT 1) singleton
|
|
523
|
+
LEFT JOIN LATERAL (
|
|
524
|
+
SELECT event.*
|
|
525
|
+
FROM "workspace_learning_policy_activation_events" event
|
|
526
|
+
WHERE event."account_id" = p_account_id
|
|
527
|
+
AND event."workspace_id" = p_workspace_id
|
|
528
|
+
AND event."created_at" <= p_accepted_at
|
|
529
|
+
ORDER BY event."created_at" DESC, event."activation_version" DESC, event."id" DESC
|
|
530
|
+
LIMIT 1
|
|
531
|
+
) active ON true
|
|
532
|
+
LEFT JOIN "workspace_learning_policy_revisions" revision
|
|
533
|
+
ON revision."account_id" = active."account_id"
|
|
534
|
+
AND revision."workspace_id" = active."workspace_id"
|
|
535
|
+
AND revision."id" = active."new_revision_id"
|
|
536
|
+
AND revision."revision" = active."new_revision"
|
|
537
|
+
AND revision."policy_hash" = active."new_policy_hash";
|
|
538
|
+
$$;
|
|
539
|
+
|
|
540
|
+
REVOKE ALL ON FUNCTION workspace_learning_policy_canonical_at(uuid, uuid, timestamptz)
|
|
541
|
+
FROM PUBLIC;
|
|
542
|
+
|
|
543
|
+
CREATE OR REPLACE FUNCTION workspace_learning_policy_validate_snapshot()
|
|
544
|
+
RETURNS trigger
|
|
545
|
+
LANGUAGE plpgsql
|
|
546
|
+
AS $$
|
|
547
|
+
DECLARE
|
|
548
|
+
accepted_at timestamptz;
|
|
549
|
+
canonical jsonb;
|
|
550
|
+
BEGIN
|
|
551
|
+
SELECT turn."created_at" INTO accepted_at
|
|
552
|
+
FROM "session_turn_attempts" attempt
|
|
553
|
+
JOIN "session_turns" turn
|
|
554
|
+
ON turn."account_id" = attempt."account_id"
|
|
555
|
+
AND turn."workspace_id" = attempt."workspace_id"
|
|
556
|
+
AND turn."session_id" = attempt."session_id"
|
|
557
|
+
AND turn."id" = attempt."turn_id"
|
|
558
|
+
JOIN "sessions" session
|
|
559
|
+
ON session."account_id" = attempt."account_id"
|
|
560
|
+
AND session."workspace_id" = attempt."workspace_id"
|
|
561
|
+
AND session."id" = attempt."session_id"
|
|
562
|
+
WHERE attempt."id" = NEW."attempt_id"
|
|
563
|
+
AND attempt."account_id" = NEW."account_id"
|
|
564
|
+
AND attempt."workspace_id" = NEW."workspace_id"
|
|
565
|
+
AND attempt."session_id" = NEW."session_id"
|
|
566
|
+
AND attempt."turn_id" = NEW."turn_id"
|
|
567
|
+
AND attempt."execution_generation" = NEW."execution_generation"
|
|
568
|
+
AND turn."execution_generation" = NEW."execution_generation"
|
|
569
|
+
AND attempt."state" IN ('claimed', 'running')
|
|
570
|
+
AND turn."active_attempt_id" = attempt."id"
|
|
571
|
+
AND session."active_turn_id" = turn."id"
|
|
572
|
+
AND turn."status" IN ('running', 'requires_action', 'recovering', 'waiting_capacity')
|
|
573
|
+
AND NOT EXISTS (
|
|
574
|
+
SELECT 1
|
|
575
|
+
FROM "session_attempt_interruptions" interruption
|
|
576
|
+
WHERE interruption."workspace_id" = NEW."workspace_id"
|
|
577
|
+
AND interruption."attempt_id" = NEW."attempt_id"
|
|
578
|
+
AND interruption."state" IN ('pending', 'delivered', 'acknowledged')
|
|
579
|
+
);
|
|
580
|
+
IF NOT FOUND THEN
|
|
581
|
+
RAISE EXCEPTION 'learning-policy snapshot requires an exact active attempt'
|
|
582
|
+
USING ERRCODE = '23514';
|
|
583
|
+
END IF;
|
|
584
|
+
|
|
585
|
+
canonical := workspace_learning_policy_canonical_at(
|
|
586
|
+
NEW."account_id",
|
|
587
|
+
NEW."workspace_id",
|
|
588
|
+
accepted_at
|
|
589
|
+
);
|
|
590
|
+
IF NEW."revision_id" IS DISTINCT FROM (canonical->>'revisionId')::uuid
|
|
591
|
+
OR NEW."revision" IS DISTINCT FROM (canonical->>'revision')::bigint
|
|
592
|
+
OR NEW."policy_hash" IS DISTINCT FROM canonical->>'policyHash'
|
|
593
|
+
OR NEW."activation_version" IS DISTINCT FROM (canonical->>'activationVersion')::bigint
|
|
594
|
+
OR NEW."activated_at" IS DISTINCT FROM (canonical->>'activatedAt')::timestamptz
|
|
595
|
+
OR NEW."workspace_mode" IS DISTINCT FROM canonical->>'workspaceMode'
|
|
596
|
+
OR NEW."source_overrides" IS DISTINCT FROM canonical->'sourceOverrides'
|
|
597
|
+
THEN
|
|
598
|
+
RAISE EXCEPTION 'learning-policy snapshot is not the canonical accepted policy'
|
|
599
|
+
USING ERRCODE = '23514';
|
|
600
|
+
END IF;
|
|
601
|
+
RETURN NEW;
|
|
602
|
+
END;
|
|
603
|
+
$$;
|
|
604
|
+
|
|
605
|
+
CREATE TRIGGER workspace_learning_policy_snapshots_validate
|
|
606
|
+
BEFORE INSERT ON "workspace_learning_policy_snapshots"
|
|
607
|
+
FOR EACH ROW EXECUTE FUNCTION workspace_learning_policy_validate_snapshot();
|
|
608
|
+
|
|
609
|
+
DO $activation_function$
|
|
610
|
+
DECLARE target_schema text := current_schema();
|
|
611
|
+
BEGIN
|
|
612
|
+
EXECUTE format($ddl$
|
|
613
|
+
CREATE OR REPLACE FUNCTION %I.workspace_learning_policy_apply_activation(
|
|
614
|
+
p_operation_id uuid,
|
|
615
|
+
p_request_fingerprint text,
|
|
616
|
+
p_account_id uuid,
|
|
617
|
+
p_workspace_id uuid,
|
|
618
|
+
p_target_revision_id uuid,
|
|
619
|
+
p_expected_current_revision_id uuid,
|
|
620
|
+
p_expected_activation_version bigint,
|
|
621
|
+
p_type text,
|
|
622
|
+
p_actor_subject_id text,
|
|
623
|
+
p_reason text
|
|
624
|
+
) RETURNS TABLE (event_id uuid)
|
|
625
|
+
LANGUAGE plpgsql SECURITY DEFINER SET search_path = %I, pg_catalog
|
|
626
|
+
AS $body$
|
|
627
|
+
DECLARE
|
|
628
|
+
target_revision record;
|
|
629
|
+
current_head record;
|
|
630
|
+
existing_event record;
|
|
631
|
+
next_activation_version bigint;
|
|
632
|
+
event_created_at timestamptz;
|
|
633
|
+
context_account_id uuid;
|
|
634
|
+
context_workspace_id uuid;
|
|
635
|
+
context_subject_id text;
|
|
636
|
+
context_principal_kind text;
|
|
637
|
+
BEGIN
|
|
638
|
+
context_account_id := NULLIF(current_setting('opengeni.account_id', true), '')::uuid;
|
|
639
|
+
context_workspace_id := NULLIF(current_setting('opengeni.workspace_id', true), '')::uuid;
|
|
640
|
+
context_subject_id := NULLIF(current_setting('opengeni.subject_id', true), '');
|
|
641
|
+
context_principal_kind := NULLIF(current_setting('opengeni.principal_kind', true), '');
|
|
642
|
+
IF context_account_id IS DISTINCT FROM p_account_id
|
|
643
|
+
OR context_workspace_id IS DISTINCT FROM p_workspace_id
|
|
644
|
+
OR context_subject_id IS DISTINCT FROM p_actor_subject_id
|
|
645
|
+
OR context_principal_kind IS DISTINCT FROM 'human_session'
|
|
646
|
+
THEN
|
|
647
|
+
RAISE EXCEPTION 'learning-policy activation requires exact human workspace authority'
|
|
648
|
+
USING ERRCODE = '42501';
|
|
649
|
+
END IF;
|
|
650
|
+
IF p_request_fingerprint !~ '^[0-9a-f]{64}$'
|
|
651
|
+
OR p_expected_activation_version < 0
|
|
652
|
+
OR p_type NOT IN ('activate', 'rollback')
|
|
653
|
+
OR length(btrim(p_actor_subject_id)) NOT BETWEEN 1 AND 1024
|
|
654
|
+
OR length(btrim(p_reason)) NOT BETWEEN 1 AND 4096
|
|
655
|
+
THEN
|
|
656
|
+
RAISE EXCEPTION 'learning-policy activation input is invalid'
|
|
657
|
+
USING ERRCODE = '22023';
|
|
658
|
+
END IF;
|
|
659
|
+
|
|
660
|
+
PERFORM 1
|
|
661
|
+
FROM "workspaces" workspace
|
|
662
|
+
WHERE workspace."id" = p_workspace_id AND workspace."account_id" = p_account_id
|
|
663
|
+
FOR UPDATE;
|
|
664
|
+
IF NOT FOUND THEN
|
|
665
|
+
RAISE EXCEPTION 'workspace was not found' USING ERRCODE = '42501';
|
|
666
|
+
END IF;
|
|
667
|
+
|
|
668
|
+
SELECT * INTO existing_event
|
|
669
|
+
FROM "workspace_learning_policy_activation_events" event
|
|
670
|
+
WHERE event."workspace_id" = p_workspace_id
|
|
671
|
+
AND event."operation_id" = p_operation_id;
|
|
672
|
+
IF FOUND THEN
|
|
673
|
+
IF existing_event."request_fingerprint" IS DISTINCT FROM p_request_fingerprint THEN
|
|
674
|
+
RAISE EXCEPTION 'learning-policy operation id was reused'
|
|
675
|
+
USING ERRCODE = 'P1471';
|
|
676
|
+
END IF;
|
|
677
|
+
event_id := existing_event."id";
|
|
678
|
+
RETURN NEXT;
|
|
679
|
+
RETURN;
|
|
680
|
+
END IF;
|
|
681
|
+
IF EXISTS (
|
|
682
|
+
SELECT 1 FROM "workspace_learning_policy_revisions" revision
|
|
683
|
+
WHERE revision."workspace_id" = p_workspace_id
|
|
684
|
+
AND revision."operation_id" = p_operation_id
|
|
685
|
+
) THEN
|
|
686
|
+
RAISE EXCEPTION 'learning-policy operation id was reused'
|
|
687
|
+
USING ERRCODE = 'P1471';
|
|
688
|
+
END IF;
|
|
689
|
+
|
|
690
|
+
SELECT * INTO target_revision
|
|
691
|
+
FROM "workspace_learning_policy_revisions" revision
|
|
692
|
+
WHERE revision."id" = p_target_revision_id
|
|
693
|
+
AND revision."account_id" = p_account_id
|
|
694
|
+
AND revision."workspace_id" = p_workspace_id;
|
|
695
|
+
IF NOT FOUND THEN
|
|
696
|
+
RAISE EXCEPTION 'learning-policy revision was not found' USING ERRCODE = '23503';
|
|
697
|
+
END IF;
|
|
698
|
+
|
|
699
|
+
SELECT * INTO current_head
|
|
700
|
+
FROM "workspace_learning_policy_heads" head
|
|
701
|
+
WHERE head."account_id" = p_account_id
|
|
702
|
+
AND head."workspace_id" = p_workspace_id
|
|
703
|
+
FOR UPDATE;
|
|
704
|
+
IF coalesce(current_head."activation_version", 0) IS DISTINCT FROM p_expected_activation_version
|
|
705
|
+
OR current_head."revision_id" IS DISTINCT FROM p_expected_current_revision_id
|
|
706
|
+
THEN
|
|
707
|
+
RAISE EXCEPTION 'learning-policy active revision changed'
|
|
708
|
+
USING ERRCODE = '40001';
|
|
709
|
+
END IF;
|
|
710
|
+
IF current_head."revision_id" IS NOT NULL
|
|
711
|
+
AND current_head."revision_id" = target_revision."id"
|
|
712
|
+
THEN
|
|
713
|
+
RAISE EXCEPTION 'learning-policy revision is already active'
|
|
714
|
+
USING ERRCODE = '23514';
|
|
715
|
+
END IF;
|
|
716
|
+
IF p_type = 'rollback' THEN
|
|
717
|
+
IF current_head."revision_id" IS NULL OR NOT EXISTS (
|
|
718
|
+
SELECT 1
|
|
719
|
+
FROM "workspace_learning_policy_activation_events" event
|
|
720
|
+
WHERE event."account_id" = p_account_id
|
|
721
|
+
AND event."workspace_id" = p_workspace_id
|
|
722
|
+
AND event."new_revision_id" = target_revision."id"
|
|
723
|
+
) THEN
|
|
724
|
+
RAISE EXCEPTION 'learning-policy rollback target was not previously active'
|
|
725
|
+
USING ERRCODE = '23514';
|
|
726
|
+
END IF;
|
|
727
|
+
END IF;
|
|
728
|
+
|
|
729
|
+
-- The event timestamp is accepted-order evidence. Stamp it only after
|
|
730
|
+
-- workspace/head serialization and successful CAS so a dependent
|
|
731
|
+
-- activation that began earlier cannot sort before its predecessor.
|
|
732
|
+
event_created_at := clock_timestamp();
|
|
733
|
+
next_activation_version := coalesce(current_head."activation_version", 0) + 1;
|
|
734
|
+
PERFORM set_config(
|
|
735
|
+
'opengeni.workspace_learning_policy_lifecycle_workspace_id',
|
|
736
|
+
p_workspace_id::text,
|
|
737
|
+
true
|
|
738
|
+
);
|
|
739
|
+
IF current_head."id" IS NULL THEN
|
|
740
|
+
INSERT INTO "workspace_learning_policy_heads" (
|
|
741
|
+
"account_id", "workspace_id", "revision_id", "revision",
|
|
742
|
+
"policy_hash", "activation_version", "activated_at"
|
|
743
|
+
) VALUES (
|
|
744
|
+
p_account_id, p_workspace_id, target_revision."id", target_revision."revision",
|
|
745
|
+
target_revision."policy_hash", next_activation_version, event_created_at
|
|
746
|
+
);
|
|
747
|
+
ELSE
|
|
748
|
+
UPDATE "workspace_learning_policy_heads"
|
|
749
|
+
SET "revision_id" = target_revision."id",
|
|
750
|
+
"revision" = target_revision."revision",
|
|
751
|
+
"policy_hash" = target_revision."policy_hash",
|
|
752
|
+
"activation_version" = next_activation_version,
|
|
753
|
+
"activated_at" = event_created_at
|
|
754
|
+
WHERE "id" = current_head."id";
|
|
755
|
+
END IF;
|
|
756
|
+
PERFORM set_config('opengeni.workspace_learning_policy_lifecycle_workspace_id', '', true);
|
|
757
|
+
|
|
758
|
+
INSERT INTO "workspace_learning_policy_activation_events" (
|
|
759
|
+
"operation_id", "request_fingerprint", "account_id", "workspace_id",
|
|
760
|
+
"type", "activation_version",
|
|
761
|
+
"old_revision_id", "old_revision", "old_policy_hash",
|
|
762
|
+
"new_revision_id", "new_revision", "new_policy_hash",
|
|
763
|
+
"actor_subject_id", "reason", "created_at"
|
|
764
|
+
) VALUES (
|
|
765
|
+
p_operation_id, p_request_fingerprint, p_account_id, p_workspace_id,
|
|
766
|
+
p_type, next_activation_version,
|
|
767
|
+
current_head."revision_id", current_head."revision", current_head."policy_hash",
|
|
768
|
+
target_revision."id", target_revision."revision", target_revision."policy_hash",
|
|
769
|
+
p_actor_subject_id, p_reason, event_created_at
|
|
770
|
+
) RETURNING "id" INTO event_id;
|
|
771
|
+
RETURN NEXT;
|
|
772
|
+
END
|
|
773
|
+
$body$
|
|
774
|
+
$ddl$, target_schema, target_schema);
|
|
775
|
+
EXECUTE format(
|
|
776
|
+
'REVOKE ALL ON FUNCTION %I.workspace_learning_policy_apply_activation(uuid,text,uuid,uuid,uuid,uuid,bigint,text,text,text) FROM PUBLIC',
|
|
777
|
+
target_schema
|
|
778
|
+
);
|
|
779
|
+
IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'opengeni_app') THEN
|
|
780
|
+
EXECUTE format(
|
|
781
|
+
'GRANT EXECUTE ON FUNCTION %I.workspace_learning_policy_apply_activation(uuid, text, uuid, uuid, uuid, uuid, bigint, text, text, text) TO opengeni_app',
|
|
782
|
+
target_schema
|
|
783
|
+
);
|
|
784
|
+
END IF;
|
|
785
|
+
END $activation_function$;
|
|
786
|
+
|
|
787
|
+
DO $snapshot_function$
|
|
788
|
+
DECLARE target_schema text := current_schema();
|
|
789
|
+
BEGIN
|
|
790
|
+
EXECUTE format($ddl$
|
|
791
|
+
CREATE OR REPLACE FUNCTION %I.workspace_learning_policy_get_or_create_snapshot(
|
|
792
|
+
p_account_id uuid,
|
|
793
|
+
p_workspace_id uuid,
|
|
794
|
+
p_session_id uuid,
|
|
795
|
+
p_turn_id uuid,
|
|
796
|
+
p_attempt_id uuid,
|
|
797
|
+
p_execution_generation integer
|
|
798
|
+
) RETURNS TABLE (snapshot_id uuid)
|
|
799
|
+
LANGUAGE plpgsql SECURITY DEFINER SET search_path = %I, pg_catalog
|
|
800
|
+
AS $body$
|
|
801
|
+
DECLARE
|
|
802
|
+
accepted_at timestamptz;
|
|
803
|
+
canonical jsonb;
|
|
804
|
+
existing_snapshot record;
|
|
805
|
+
snapshot_revision_id uuid;
|
|
806
|
+
snapshot_revision bigint;
|
|
807
|
+
snapshot_policy_hash text;
|
|
808
|
+
snapshot_activation_version bigint;
|
|
809
|
+
snapshot_activated_at timestamptz;
|
|
810
|
+
snapshot_workspace_mode text;
|
|
811
|
+
snapshot_source_overrides jsonb;
|
|
812
|
+
BEGIN
|
|
813
|
+
IF NULLIF(current_setting('opengeni.account_id', true), '')::uuid IS DISTINCT FROM p_account_id
|
|
814
|
+
OR NULLIF(current_setting('opengeni.workspace_id', true), '')::uuid IS DISTINCT FROM p_workspace_id
|
|
815
|
+
THEN
|
|
816
|
+
RAISE EXCEPTION 'learning-policy snapshot requires exact workspace authority'
|
|
817
|
+
USING ERRCODE = '42501';
|
|
818
|
+
END IF;
|
|
819
|
+
|
|
820
|
+
SELECT * INTO existing_snapshot
|
|
821
|
+
FROM "workspace_learning_policy_snapshots" snapshot
|
|
822
|
+
WHERE snapshot."account_id" = p_account_id
|
|
823
|
+
AND snapshot."workspace_id" = p_workspace_id
|
|
824
|
+
AND snapshot."attempt_id" = p_attempt_id;
|
|
825
|
+
IF FOUND THEN
|
|
826
|
+
IF existing_snapshot."session_id" IS DISTINCT FROM p_session_id
|
|
827
|
+
OR existing_snapshot."turn_id" IS DISTINCT FROM p_turn_id
|
|
828
|
+
OR existing_snapshot."execution_generation" IS DISTINCT FROM p_execution_generation
|
|
829
|
+
THEN
|
|
830
|
+
RAISE EXCEPTION 'learning-policy snapshot attempt identity conflicted'
|
|
831
|
+
USING ERRCODE = '23514';
|
|
832
|
+
END IF;
|
|
833
|
+
snapshot_id := existing_snapshot."id";
|
|
834
|
+
RETURN NEXT;
|
|
835
|
+
RETURN;
|
|
836
|
+
END IF;
|
|
837
|
+
|
|
838
|
+
SELECT turn."created_at" INTO accepted_at
|
|
839
|
+
FROM "session_turn_attempts" attempt
|
|
840
|
+
JOIN "session_turns" turn
|
|
841
|
+
ON turn."account_id" = attempt."account_id"
|
|
842
|
+
AND turn."workspace_id" = attempt."workspace_id"
|
|
843
|
+
AND turn."session_id" = attempt."session_id"
|
|
844
|
+
AND turn."id" = attempt."turn_id"
|
|
845
|
+
JOIN "sessions" session
|
|
846
|
+
ON session."account_id" = attempt."account_id"
|
|
847
|
+
AND session."workspace_id" = attempt."workspace_id"
|
|
848
|
+
AND session."id" = attempt."session_id"
|
|
849
|
+
WHERE attempt."id" = p_attempt_id
|
|
850
|
+
AND attempt."account_id" = p_account_id
|
|
851
|
+
AND attempt."workspace_id" = p_workspace_id
|
|
852
|
+
AND attempt."session_id" = p_session_id
|
|
853
|
+
AND attempt."turn_id" = p_turn_id
|
|
854
|
+
AND attempt."execution_generation" = p_execution_generation
|
|
855
|
+
AND turn."execution_generation" = p_execution_generation
|
|
856
|
+
AND attempt."state" IN ('claimed', 'running')
|
|
857
|
+
AND turn."active_attempt_id" = attempt."id"
|
|
858
|
+
AND session."active_turn_id" = turn."id"
|
|
859
|
+
AND turn."status" IN ('running', 'requires_action', 'recovering', 'waiting_capacity')
|
|
860
|
+
AND NOT EXISTS (
|
|
861
|
+
SELECT 1 FROM "session_attempt_interruptions" interruption
|
|
862
|
+
WHERE interruption."workspace_id" = p_workspace_id
|
|
863
|
+
AND interruption."attempt_id" = p_attempt_id
|
|
864
|
+
AND interruption."state" IN ('pending', 'delivered', 'acknowledged')
|
|
865
|
+
)
|
|
866
|
+
FOR SHARE OF attempt, turn, session;
|
|
867
|
+
IF NOT FOUND THEN
|
|
868
|
+
RAISE EXCEPTION 'learning-policy snapshot requires an exact active attempt'
|
|
869
|
+
USING ERRCODE = '23514';
|
|
870
|
+
END IF;
|
|
871
|
+
|
|
872
|
+
canonical := workspace_learning_policy_canonical_at(
|
|
873
|
+
p_account_id,
|
|
874
|
+
p_workspace_id,
|
|
875
|
+
accepted_at
|
|
876
|
+
);
|
|
877
|
+
snapshot_revision_id := (canonical->>'revisionId')::uuid;
|
|
878
|
+
snapshot_revision := (canonical->>'revision')::bigint;
|
|
879
|
+
snapshot_policy_hash := canonical->>'policyHash';
|
|
880
|
+
snapshot_activation_version := (canonical->>'activationVersion')::bigint;
|
|
881
|
+
snapshot_activated_at := (canonical->>'activatedAt')::timestamptz;
|
|
882
|
+
snapshot_workspace_mode := canonical->>'workspaceMode';
|
|
883
|
+
snapshot_source_overrides := canonical->'sourceOverrides';
|
|
884
|
+
|
|
885
|
+
INSERT INTO "workspace_learning_policy_snapshots" (
|
|
886
|
+
"account_id", "workspace_id", "session_id", "turn_id", "attempt_id",
|
|
887
|
+
"execution_generation", "revision_id", "revision", "policy_hash",
|
|
888
|
+
"activation_version", "activated_at", "workspace_mode", "source_overrides",
|
|
889
|
+
"snapshot_hash"
|
|
890
|
+
) VALUES (
|
|
891
|
+
p_account_id, p_workspace_id, p_session_id, p_turn_id, p_attempt_id,
|
|
892
|
+
p_execution_generation, snapshot_revision_id, snapshot_revision, snapshot_policy_hash,
|
|
893
|
+
snapshot_activation_version, snapshot_activated_at, snapshot_workspace_mode,
|
|
894
|
+
snapshot_source_overrides,
|
|
895
|
+
workspace_learning_policy_snapshot_hash(
|
|
896
|
+
snapshot_revision_id,
|
|
897
|
+
snapshot_revision,
|
|
898
|
+
snapshot_policy_hash,
|
|
899
|
+
snapshot_activation_version,
|
|
900
|
+
snapshot_activated_at,
|
|
901
|
+
snapshot_workspace_mode,
|
|
902
|
+
snapshot_source_overrides
|
|
903
|
+
)
|
|
904
|
+
)
|
|
905
|
+
ON CONFLICT ("account_id", "workspace_id", "attempt_id") DO NOTHING
|
|
906
|
+
RETURNING "id" INTO snapshot_id;
|
|
907
|
+
|
|
908
|
+
IF snapshot_id IS NULL THEN
|
|
909
|
+
SELECT snapshot."id" INTO snapshot_id
|
|
910
|
+
FROM "workspace_learning_policy_snapshots" snapshot
|
|
911
|
+
WHERE snapshot."account_id" = p_account_id
|
|
912
|
+
AND snapshot."workspace_id" = p_workspace_id
|
|
913
|
+
AND snapshot."attempt_id" = p_attempt_id
|
|
914
|
+
AND snapshot."session_id" = p_session_id
|
|
915
|
+
AND snapshot."turn_id" = p_turn_id
|
|
916
|
+
AND snapshot."execution_generation" = p_execution_generation;
|
|
917
|
+
IF NOT FOUND THEN
|
|
918
|
+
RAISE EXCEPTION 'learning-policy snapshot concurrent identity conflicted'
|
|
919
|
+
USING ERRCODE = '23514';
|
|
920
|
+
END IF;
|
|
921
|
+
END IF;
|
|
922
|
+
RETURN NEXT;
|
|
923
|
+
END
|
|
924
|
+
$body$
|
|
925
|
+
$ddl$, target_schema, target_schema);
|
|
926
|
+
EXECUTE format(
|
|
927
|
+
'REVOKE ALL ON FUNCTION %I.workspace_learning_policy_get_or_create_snapshot(uuid,uuid,uuid,uuid,uuid,integer) FROM PUBLIC',
|
|
928
|
+
target_schema
|
|
929
|
+
);
|
|
930
|
+
IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'opengeni_app') THEN
|
|
931
|
+
EXECUTE format(
|
|
932
|
+
'GRANT EXECUTE ON FUNCTION %I.workspace_learning_policy_get_or_create_snapshot(uuid, uuid, uuid, uuid, uuid, integer) TO opengeni_app',
|
|
933
|
+
target_schema
|
|
934
|
+
);
|
|
935
|
+
END IF;
|
|
936
|
+
END $snapshot_function$;
|
|
937
|
+
|
|
938
|
+
ALTER TABLE "workspace_learning_policy_revisions" ENABLE ROW LEVEL SECURITY;
|
|
939
|
+
ALTER TABLE "workspace_learning_policy_revisions" FORCE ROW LEVEL SECURITY;
|
|
940
|
+
ALTER TABLE "workspace_learning_policy_heads" ENABLE ROW LEVEL SECURITY;
|
|
941
|
+
ALTER TABLE "workspace_learning_policy_heads" FORCE ROW LEVEL SECURITY;
|
|
942
|
+
ALTER TABLE "workspace_learning_policy_activation_events" ENABLE ROW LEVEL SECURITY;
|
|
943
|
+
ALTER TABLE "workspace_learning_policy_activation_events" FORCE ROW LEVEL SECURITY;
|
|
944
|
+
ALTER TABLE "workspace_learning_policy_snapshots" ENABLE ROW LEVEL SECURITY;
|
|
945
|
+
ALTER TABLE "workspace_learning_policy_snapshots" FORCE ROW LEVEL SECURITY;
|
|
946
|
+
|
|
947
|
+
CREATE POLICY workspace_isolation ON "workspace_learning_policy_revisions"
|
|
948
|
+
USING (opengeni_private.workspace_rls_visible("account_id", "workspace_id"))
|
|
949
|
+
WITH CHECK (opengeni_private.workspace_rls_visible("account_id", "workspace_id"));
|
|
950
|
+
|
|
951
|
+
CREATE POLICY workspace_isolation ON "workspace_learning_policy_heads"
|
|
952
|
+
USING (opengeni_private.workspace_rls_visible("account_id", "workspace_id"))
|
|
953
|
+
WITH CHECK (opengeni_private.workspace_rls_visible("account_id", "workspace_id"));
|
|
954
|
+
|
|
955
|
+
CREATE POLICY workspace_isolation ON "workspace_learning_policy_activation_events"
|
|
956
|
+
USING (opengeni_private.workspace_rls_visible("account_id", "workspace_id"))
|
|
957
|
+
WITH CHECK (opengeni_private.workspace_rls_visible("account_id", "workspace_id"));
|
|
958
|
+
|
|
959
|
+
CREATE POLICY workspace_isolation ON "workspace_learning_policy_snapshots"
|
|
960
|
+
USING (opengeni_private.workspace_rls_visible("account_id", "workspace_id"))
|
|
961
|
+
WITH CHECK (opengeni_private.workspace_rls_visible("account_id", "workspace_id"));
|
|
962
|
+
|
|
963
|
+
REVOKE ALL ON TABLE "workspace_learning_policy_revisions" FROM PUBLIC;
|
|
964
|
+
REVOKE ALL ON TABLE "workspace_learning_policy_heads" FROM PUBLIC;
|
|
965
|
+
REVOKE ALL ON TABLE "workspace_learning_policy_activation_events" FROM PUBLIC;
|
|
966
|
+
REVOKE ALL ON TABLE "workspace_learning_policy_snapshots" FROM PUBLIC;
|
|
967
|
+
|
|
968
|
+
DO $grants$
|
|
969
|
+
BEGIN
|
|
970
|
+
IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'opengeni_app') THEN
|
|
971
|
+
GRANT SELECT, INSERT ON TABLE "workspace_learning_policy_revisions" TO opengeni_app;
|
|
972
|
+
GRANT SELECT ON TABLE "workspace_learning_policy_heads" TO opengeni_app;
|
|
973
|
+
GRANT SELECT ON TABLE "workspace_learning_policy_activation_events" TO opengeni_app;
|
|
974
|
+
GRANT SELECT ON TABLE "workspace_learning_policy_snapshots" TO opengeni_app;
|
|
975
|
+
GRANT EXECUTE ON FUNCTION workspace_learning_policy_source_overrides_valid(jsonb)
|
|
976
|
+
TO opengeni_app;
|
|
977
|
+
GRANT EXECUTE ON FUNCTION workspace_learning_policy_hash(text, jsonb)
|
|
978
|
+
TO opengeni_app;
|
|
979
|
+
END IF;
|
|
980
|
+
END $grants$;
|