@opengeni/db 0.28.1 → 0.31.1
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 +91 -0
- package/dist/browser-identities.d.ts +128 -0
- package/dist/browser-sessions.d.ts +272 -0
- package/dist/browser-state-artifacts.d.ts +17 -0
- package/dist/capability-components.d.ts +37 -0
- package/dist/capability-integrations.d.ts +192 -0
- package/dist/chunk-F5FT7BEZ.js +3535 -0
- package/dist/chunk-F5FT7BEZ.js.map +1 -0
- package/dist/chunk-ISI2TIUG.js +639 -0
- package/dist/chunk-ISI2TIUG.js.map +1 -0
- package/dist/chunk-MWDVXQOL.js +11639 -0
- package/dist/chunk-MWDVXQOL.js.map +1 -0
- package/dist/chunk-NBE6CHRI.js +955 -0
- package/dist/chunk-NBE6CHRI.js.map +1 -0
- package/dist/{chunk-DBS5HPEW.js → chunk-YHZXQ7HP.js} +760 -11
- package/dist/chunk-YHZXQ7HP.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 +52 -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/environment-crypto.d.ts +8 -4
- package/dist/generated-images.d.ts +139 -0
- package/dist/index.d.ts +958 -126
- package/dist/index.js +31204 -12172
- package/dist/index.js.map +1 -1
- package/dist/insights.d.ts +51 -4
- package/dist/integration-bindings.d.ts +70 -0
- package/dist/integration-features.d.ts +99 -0
- package/dist/interaction-revisions.d.ts +3 -0
- package/dist/interaction-schema.d.ts +5372 -0
- package/dist/knowledge-source-sync-schema.d.ts +1679 -0
- package/dist/knowledge-source-sync.d.ts +274 -0
- package/dist/lossless-columns.d.ts +58 -0
- package/dist/lossless-json.d.ts +39 -0
- package/dist/memory-domain.d.ts +3 -6
- 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 +7 -14
- 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 +18 -6
- package/dist/schema.d.ts +19122 -8731
- package/dist/schema.js +173 -1
- package/dist/scoped-knowledge.d.ts +97 -1
- package/dist/session-control.d.ts +4 -4
- 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 +8 -1
- package/dist/session-realtime.d.ts +7 -7
- package/dist/session-tool-call-settlement.d.ts +1 -1
- package/dist/slack-user-link-access.d.ts +54 -0
- package/dist/transcription-recordings-schema.d.ts +44 -6
- package/dist/transcription-recordings.d.ts +3 -3
- package/dist/turn-initiator.d.ts +2 -2
- package/dist/video-generation.d.ts +216 -0
- package/dist/video-generation.js +66 -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/drizzle/0065_enrollment_credential_generation.sql +10 -0
- package/drizzle/0140_retained_screenshot_artifacts.sql +192 -0
- package/drizzle/0176_lossless_canonical_json.sql +975 -0
- package/drizzle/0177_session_events_workspace_turn_type_index.sql +5 -0
- package/drizzle/0178_permissioned_secret_reads.sql +14 -0
- package/drizzle/0179_slack_private_shortcut_delivery_gate.sql +85 -0
- package/drizzle/0180_retained_screenshot_lifecycle_fences.sql +273 -0
- package/drizzle/0181_connected_machine_removal.sql +52 -0
- package/drizzle/0182_connected_machine_remove_session_default.sql +77 -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_slack_installation_bindings.sql +348 -0
- package/drizzle/0213_slack_user_link_access_requests.sql +177 -0
- package/drizzle/0214_session_activity_commit_gate.sql +262 -0
- package/drizzle/0215_capabilities_platform.sql +980 -0
- package/drizzle/0216_pack_component_ownership.sql +235 -0
- package/drizzle/0217_capability_definition_delete_authority.sql +32 -0
- package/package.json +18 -5
- package/src/attached-browser-devices.ts +371 -0
- package/src/attempt-tool-catalogs.ts +131 -0
- package/src/browser-auth.ts +1896 -0
- package/src/browser-identities.ts +1168 -0
- package/src/browser-sessions.ts +2005 -0
- package/src/browser-state-artifacts.ts +59 -0
- package/src/capability-components.ts +166 -0
- package/src/capability-integrations.ts +1663 -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 +434 -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/environment-crypto.ts +22 -9
- package/src/generated-images.ts +740 -0
- package/src/index.ts +10117 -2730
- package/src/insights.ts +160 -13
- package/src/integration-bindings.ts +455 -0
- package/src/integration-features.ts +859 -0
- package/src/interaction-revisions.ts +40 -0
- package/src/interaction-schema.ts +1303 -0
- package/src/knowledge-source-sync-schema.ts +192 -0
- package/src/knowledge-source-sync.ts +1922 -0
- package/src/lossless-columns.ts +35 -0
- package/src/lossless-json.ts +322 -0
- package/src/memory-domain.ts +5 -44
- package/src/memory-slack-delivery.ts +801 -0
- package/src/pack-components.ts +954 -0
- package/src/pack-installations.ts +929 -0
- package/src/persistence-errors.ts +26 -34
- package/src/plugin-packages.ts +1186 -0
- package/src/provision-roles.ts +302 -1
- package/src/runtime-posture-cli.ts +9 -0
- package/src/runtime-posture.ts +514 -5
- package/src/schema.ts +5177 -2957
- package/src/scoped-knowledge-schema.ts +1 -1
- package/src/scoped-knowledge.ts +655 -3
- package/src/session-control.ts +133 -81
- package/src/session-queue-commands.ts +511 -247
- package/src/session-realtime-context.ts +20 -7
- package/src/session-realtime-ledger.ts +32 -10
- package/src/session-realtime-mirror.ts +4 -2
- package/src/session-realtime-terminal.ts +89 -21
- package/src/session-realtime.ts +10 -9
- package/src/session-tool-call-settlement.ts +38 -15
- package/src/slack-user-link-access.ts +702 -0
- package/src/transcription-recordings-schema.ts +5 -2
- package/src/transcription-recordings.ts +70 -40
- package/src/video-generation.ts +1452 -0
- package/src/workspace-learning-policy-schema.ts +139 -0
- package/src/workspace-learning-policy.ts +595 -0
- package/dist/chunk-DBS5HPEW.js.map +0 -1
- package/dist/chunk-HT5T62CC.js +0 -6803
- package/dist/chunk-HT5T62CC.js.map +0 -1
- package/dist/event-payload-sanitizer.d.ts +0 -32
- package/src/event-payload-sanitizer.ts +0 -377
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
-- deployment-mode: rolling
|
|
2
|
+
-- Treat artifact creation and Office import as scope-level origin operations.
|
|
3
|
+
|
|
4
|
+
SET LOCAL lock_timeout = '5s';
|
|
5
|
+
SET LOCAL statement_timeout = '5min';
|
|
6
|
+
|
|
7
|
+
CREATE UNIQUE INDEX "files_scope_id_uq"
|
|
8
|
+
ON "files" ("account_id", "workspace_id", "id");
|
|
9
|
+
|
|
10
|
+
ALTER TABLE "editable_artifact_blob_refs"
|
|
11
|
+
ADD COLUMN "source_file_id" uuid,
|
|
12
|
+
ADD CONSTRAINT "editable_artifact_blob_refs_source_kind_chk" CHECK (
|
|
13
|
+
("kind" = 'original_import') = ("source_file_id" IS NOT NULL)
|
|
14
|
+
) NOT VALID,
|
|
15
|
+
ADD CONSTRAINT "editable_artifact_blob_refs_source_file_fk"
|
|
16
|
+
FOREIGN KEY ("account_id", "workspace_id", "source_file_id")
|
|
17
|
+
REFERENCES "files" ("account_id", "workspace_id", "id")
|
|
18
|
+
ON DELETE RESTRICT NOT VALID;
|
|
19
|
+
|
|
20
|
+
ALTER TABLE "editable_artifact_blob_refs"
|
|
21
|
+
VALIDATE CONSTRAINT "editable_artifact_blob_refs_source_kind_chk";
|
|
22
|
+
ALTER TABLE "editable_artifact_blob_refs"
|
|
23
|
+
VALIDATE CONSTRAINT "editable_artifact_blob_refs_source_file_fk";
|
|
24
|
+
|
|
25
|
+
CREATE OR REPLACE FUNCTION opengeni_private.authorize_editable_artifact_actor(
|
|
26
|
+
p_account_id uuid,
|
|
27
|
+
p_workspace_id uuid,
|
|
28
|
+
p_artifact_id text,
|
|
29
|
+
p_actor_kind text,
|
|
30
|
+
p_actor_subject_id text,
|
|
31
|
+
p_agent_session_id text,
|
|
32
|
+
p_agent_turn_id text,
|
|
33
|
+
p_agent_attempt_id text,
|
|
34
|
+
p_agent_generation integer,
|
|
35
|
+
p_service_name text,
|
|
36
|
+
p_permission text,
|
|
37
|
+
p_data_schema name DEFAULT pg_catalog.current_schema()
|
|
38
|
+
) RETURNS TABLE (allowed boolean, authorization_revision bigint)
|
|
39
|
+
LANGUAGE plpgsql
|
|
40
|
+
SECURITY DEFINER
|
|
41
|
+
SET search_path = pg_catalog, pg_temp
|
|
42
|
+
AS $body$
|
|
43
|
+
DECLARE data_schema name;
|
|
44
|
+
DECLARE required_permission text;
|
|
45
|
+
DECLARE current_revision bigint;
|
|
46
|
+
DECLARE principal_allowed boolean := false;
|
|
47
|
+
BEGIN
|
|
48
|
+
IF p_account_id IS NULL OR p_workspace_id IS NULL
|
|
49
|
+
OR p_artifact_id IS NULL
|
|
50
|
+
OR p_artifact_id !~ '^[0-9a-f]{32}$' OR p_artifact_id ~ '^0+$'
|
|
51
|
+
OR p_actor_kind IS NULL OR p_actor_kind NOT IN ('human', 'agent', 'service')
|
|
52
|
+
OR p_actor_subject_id IS NULL
|
|
53
|
+
OR octet_length(p_actor_subject_id) NOT BETWEEN 1 AND 1024
|
|
54
|
+
OR p_actor_subject_id <> btrim(p_actor_subject_id)
|
|
55
|
+
OR p_permission IS NULL
|
|
56
|
+
OR p_permission NOT IN ('create', 'read', 'edit', 'import', 'export', 'manage')
|
|
57
|
+
OR NOT opengeni_private.editable_artifact_scope_matches_context(
|
|
58
|
+
p_account_id, p_workspace_id
|
|
59
|
+
)
|
|
60
|
+
THEN
|
|
61
|
+
RAISE EXCEPTION 'editable artifact authorization request is invalid'
|
|
62
|
+
USING ERRCODE = '22023';
|
|
63
|
+
END IF;
|
|
64
|
+
IF (p_actor_kind = 'human' AND (
|
|
65
|
+
p_agent_session_id IS NOT NULL OR p_agent_turn_id IS NOT NULL
|
|
66
|
+
OR p_agent_attempt_id IS NOT NULL OR p_agent_generation IS NOT NULL
|
|
67
|
+
OR p_service_name IS NOT NULL
|
|
68
|
+
)) OR (p_actor_kind = 'agent' AND (
|
|
69
|
+
p_agent_session_id IS NULL OR p_agent_turn_id IS NULL
|
|
70
|
+
OR p_agent_attempt_id IS NULL OR p_agent_generation IS NULL
|
|
71
|
+
OR p_agent_generation < 0 OR p_service_name IS NOT NULL
|
|
72
|
+
)) OR (p_actor_kind = 'service' AND (
|
|
73
|
+
p_agent_session_id IS NOT NULL OR p_agent_turn_id IS NOT NULL
|
|
74
|
+
OR p_agent_attempt_id IS NOT NULL OR p_agent_generation IS NOT NULL
|
|
75
|
+
OR p_service_name IS NULL
|
|
76
|
+
))
|
|
77
|
+
THEN
|
|
78
|
+
RAISE EXCEPTION 'editable artifact authorization actor is invalid'
|
|
79
|
+
USING ERRCODE = '22023';
|
|
80
|
+
END IF;
|
|
81
|
+
|
|
82
|
+
data_schema := opengeni_private.resolve_editable_artifact_data_schema(p_data_schema);
|
|
83
|
+
required_permission := CASE
|
|
84
|
+
WHEN p_permission IN ('read', 'export') THEN 'artifacts:read'
|
|
85
|
+
ELSE 'artifacts:publish'
|
|
86
|
+
END;
|
|
87
|
+
|
|
88
|
+
IF p_permission IN ('create', 'import') THEN
|
|
89
|
+
current_revision := opengeni_private.ensure_editable_artifact_scope_authorization_head(
|
|
90
|
+
p_account_id, p_workspace_id, data_schema
|
|
91
|
+
);
|
|
92
|
+
ELSE
|
|
93
|
+
EXECUTE pg_catalog.format($query$
|
|
94
|
+
SELECT artifact.authorization_revision
|
|
95
|
+
FROM %I.editable_artifacts artifact
|
|
96
|
+
WHERE artifact.account_id = $1 AND artifact.workspace_id = $2
|
|
97
|
+
AND artifact.id = $3
|
|
98
|
+
$query$, data_schema)
|
|
99
|
+
INTO current_revision
|
|
100
|
+
USING p_account_id, p_workspace_id, p_artifact_id;
|
|
101
|
+
current_revision := coalesce(current_revision, 1);
|
|
102
|
+
END IF;
|
|
103
|
+
|
|
104
|
+
IF p_actor_kind = 'agent' THEN
|
|
105
|
+
EXECUTE pg_catalog.format($query$
|
|
106
|
+
SELECT true
|
|
107
|
+
FROM %I.sessions session
|
|
108
|
+
JOIN %I.session_turns turn
|
|
109
|
+
ON turn.account_id = session.account_id
|
|
110
|
+
AND turn.workspace_id = session.workspace_id
|
|
111
|
+
AND turn.session_id = session.id
|
|
112
|
+
JOIN %I.session_turn_attempts attempt
|
|
113
|
+
ON attempt.account_id = turn.account_id
|
|
114
|
+
AND attempt.workspace_id = turn.workspace_id
|
|
115
|
+
AND attempt.session_id = turn.session_id
|
|
116
|
+
AND attempt.turn_id = turn.id
|
|
117
|
+
WHERE session.account_id = $1 AND session.workspace_id = $2
|
|
118
|
+
AND session.id::text = $3
|
|
119
|
+
AND turn.id::text = $4
|
|
120
|
+
AND attempt.id::text = $5
|
|
121
|
+
AND session.active_turn_id = turn.id
|
|
122
|
+
AND turn.active_attempt_id = attempt.id
|
|
123
|
+
AND turn.execution_generation = $6
|
|
124
|
+
AND attempt.execution_generation = $6
|
|
125
|
+
AND turn.status IN ('running', 'requires_action', 'recovering', 'waiting_capacity')
|
|
126
|
+
AND attempt.state IN ('claimed', 'running')
|
|
127
|
+
AND attempt.closed_at IS NULL AND attempt.quiesced_at IS NULL
|
|
128
|
+
AND NOT EXISTS (
|
|
129
|
+
SELECT 1
|
|
130
|
+
FROM %I.session_attempt_interruptions interruption
|
|
131
|
+
WHERE interruption.account_id = session.account_id
|
|
132
|
+
AND interruption.workspace_id = session.workspace_id
|
|
133
|
+
AND interruption.session_id = session.id
|
|
134
|
+
AND interruption.attempt_id = attempt.id
|
|
135
|
+
AND interruption.state IN ('pending', 'delivered', 'acknowledged')
|
|
136
|
+
)
|
|
137
|
+
AND (
|
|
138
|
+
session.first_party_mcp_permissions IS NULL
|
|
139
|
+
OR session.first_party_mcp_permissions ? $7
|
|
140
|
+
OR session.first_party_mcp_permissions ? 'workspace:admin'
|
|
141
|
+
)
|
|
142
|
+
LIMIT 1
|
|
143
|
+
FOR SHARE OF session, turn, attempt
|
|
144
|
+
$query$, data_schema, data_schema, data_schema, data_schema)
|
|
145
|
+
INTO principal_allowed
|
|
146
|
+
USING p_account_id, p_workspace_id, p_agent_session_id,
|
|
147
|
+
p_agent_turn_id, p_agent_attempt_id, p_agent_generation,
|
|
148
|
+
required_permission;
|
|
149
|
+
ELSIF p_actor_kind = 'service'
|
|
150
|
+
AND p_service_name = 'api_key'
|
|
151
|
+
AND p_actor_subject_id ~ '^api_key:[0-9a-fA-F-]{36}$'
|
|
152
|
+
THEN
|
|
153
|
+
EXECUTE pg_catalog.format($query$
|
|
154
|
+
SELECT true
|
|
155
|
+
FROM %I.api_keys api_key
|
|
156
|
+
WHERE api_key.account_id = $1 AND api_key.workspace_id = $2
|
|
157
|
+
AND api_key.id::text = substring($3 from 9)
|
|
158
|
+
AND api_key.revoked_at IS NULL
|
|
159
|
+
AND (api_key.expires_at IS NULL OR api_key.expires_at > pg_catalog.clock_timestamp())
|
|
160
|
+
AND (api_key.permissions ? $4 OR api_key.permissions ? 'workspace:admin')
|
|
161
|
+
LIMIT 1
|
|
162
|
+
FOR SHARE OF api_key
|
|
163
|
+
$query$, data_schema)
|
|
164
|
+
INTO principal_allowed
|
|
165
|
+
USING p_account_id, p_workspace_id, p_actor_subject_id, required_permission;
|
|
166
|
+
ELSIF p_actor_kind = 'human'
|
|
167
|
+
OR (p_actor_kind = 'service' AND p_service_name = 'configured_key')
|
|
168
|
+
THEN
|
|
169
|
+
EXECUTE pg_catalog.format($query$
|
|
170
|
+
SELECT true
|
|
171
|
+
FROM %I.workspace_memberships membership
|
|
172
|
+
WHERE membership.account_id = $1 AND membership.workspace_id = $2
|
|
173
|
+
AND membership.subject_id = $3
|
|
174
|
+
AND (membership.permissions ? $4 OR membership.permissions ? 'workspace:admin')
|
|
175
|
+
LIMIT 1
|
|
176
|
+
FOR SHARE OF membership
|
|
177
|
+
$query$, data_schema)
|
|
178
|
+
INTO principal_allowed
|
|
179
|
+
USING p_account_id, p_workspace_id, p_actor_subject_id, required_permission;
|
|
180
|
+
ELSE
|
|
181
|
+
principal_allowed := false;
|
|
182
|
+
END IF;
|
|
183
|
+
|
|
184
|
+
RETURN QUERY SELECT coalesce(principal_allowed, false), current_revision;
|
|
185
|
+
END;
|
|
186
|
+
$body$;
|
|
187
|
+
|
|
188
|
+
REVOKE ALL ON FUNCTION opengeni_private.authorize_editable_artifact_actor(
|
|
189
|
+
uuid, uuid, text, text, text, text, text, text, integer, text, text, name
|
|
190
|
+
) FROM PUBLIC;
|
|
191
|
+
|
|
192
|
+
DO $runtime_authorization_grant$
|
|
193
|
+
BEGIN
|
|
194
|
+
IF EXISTS (SELECT 1 FROM pg_catalog.pg_roles WHERE rolname = 'opengeni_app') THEN
|
|
195
|
+
GRANT EXECUTE ON FUNCTION opengeni_private.authorize_editable_artifact_actor(
|
|
196
|
+
uuid, uuid, text, text, text, text, text, text, integer, text, text, name
|
|
197
|
+
) TO opengeni_app;
|
|
198
|
+
END IF;
|
|
199
|
+
END;
|
|
200
|
+
$runtime_authorization_grant$;
|
|
201
|
+
|
|
202
|
+
RESET statement_timeout;
|
|
203
|
+
RESET lock_timeout;
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
-- deployment-mode: rolling
|
|
2
|
+
-- Exact rig-version definitions remain immutable. This additive operational
|
|
3
|
+
-- metadata records build-once provider image status and immutable identities.
|
|
4
|
+
|
|
5
|
+
ALTER TABLE rig_versions
|
|
6
|
+
ADD COLUMN provider_images jsonb NOT NULL DEFAULT '{}'::jsonb;
|
|
7
|
+
|
|
8
|
+
ALTER TABLE rig_versions
|
|
9
|
+
ADD CONSTRAINT rig_versions_provider_images_object_chk
|
|
10
|
+
CHECK (jsonb_typeof(provider_images) = 'object');
|
|
11
|
+
|
|
12
|
+
-- Reuse the existing provider-artifact ledger and global GC. A rig-version
|
|
13
|
+
-- reference protects the exact image for that immutable version. A verified
|
|
14
|
+
-- change protects it only while its base remains active/promotable; rejected,
|
|
15
|
+
-- failed, abandoned-after-supersession, and deleted targets fall back to the
|
|
16
|
+
-- ordinary candidate/current collection path.
|
|
17
|
+
DO $rig_provider_image_checkpoint_gc$
|
|
18
|
+
DECLARE data_schema text := current_schema();
|
|
19
|
+
BEGIN
|
|
20
|
+
EXECUTE format($create$
|
|
21
|
+
CREATE OR REPLACE FUNCTION opengeni_private.claim_sandbox_checkpoint_artifacts(
|
|
22
|
+
p_claim_id uuid,
|
|
23
|
+
p_limit integer,
|
|
24
|
+
p_claim_ttl_ms bigint
|
|
25
|
+
)
|
|
26
|
+
RETURNS TABLE (
|
|
27
|
+
id uuid,
|
|
28
|
+
provider_backend text,
|
|
29
|
+
provider_binding_key text,
|
|
30
|
+
provider_binding jsonb,
|
|
31
|
+
object_kind text,
|
|
32
|
+
object_id text,
|
|
33
|
+
delete_attempts integer
|
|
34
|
+
)
|
|
35
|
+
LANGUAGE plpgsql
|
|
36
|
+
SECURITY DEFINER
|
|
37
|
+
SET search_path = pg_catalog
|
|
38
|
+
AS $function$
|
|
39
|
+
BEGIN
|
|
40
|
+
IF p_claim_id IS NULL THEN
|
|
41
|
+
RAISE EXCEPTION 'checkpoint artifact claim id is required'
|
|
42
|
+
USING ERRCODE = '22023';
|
|
43
|
+
END IF;
|
|
44
|
+
IF p_limit IS NULL OR p_limit < 1 OR p_limit > 500 THEN
|
|
45
|
+
RAISE EXCEPTION 'checkpoint artifact claim limit must be between 1 and 500'
|
|
46
|
+
USING ERRCODE = '22023';
|
|
47
|
+
END IF;
|
|
48
|
+
IF p_claim_ttl_ms IS NULL
|
|
49
|
+
OR p_claim_ttl_ms < 1000
|
|
50
|
+
OR p_claim_ttl_ms > 3600000
|
|
51
|
+
THEN
|
|
52
|
+
RAISE EXCEPTION 'checkpoint artifact claim TTL must be between 1s and 1h'
|
|
53
|
+
USING ERRCODE = '22023';
|
|
54
|
+
END IF;
|
|
55
|
+
|
|
56
|
+
PERFORM pg_catalog.set_config('opengeni.sandbox_recovery_protocol_v2', '1', true);
|
|
57
|
+
|
|
58
|
+
WITH stale_claims AS MATERIALIZED (
|
|
59
|
+
SELECT artifact.id
|
|
60
|
+
FROM %1$I.sandbox_checkpoint_artifacts artifact
|
|
61
|
+
WHERE artifact.state = 'deleting'
|
|
62
|
+
AND artifact.delete_claimed_at
|
|
63
|
+
< pg_catalog.now()
|
|
64
|
+
- pg_catalog.make_interval(secs => p_claim_ttl_ms / 1000.0)
|
|
65
|
+
ORDER BY artifact.delete_claimed_at, artifact.id
|
|
66
|
+
FOR UPDATE SKIP LOCKED
|
|
67
|
+
LIMIT p_limit
|
|
68
|
+
)
|
|
69
|
+
UPDATE %1$I.sandbox_checkpoint_artifacts artifact SET
|
|
70
|
+
state = 'delete_failed',
|
|
71
|
+
delete_after = pg_catalog.now(),
|
|
72
|
+
delete_claim_id = null,
|
|
73
|
+
delete_claimed_at = null,
|
|
74
|
+
last_delete_error = coalesce(
|
|
75
|
+
last_delete_error, 'stale delete claim recovered'
|
|
76
|
+
),
|
|
77
|
+
updated_at = pg_catalog.now()
|
|
78
|
+
FROM stale_claims
|
|
79
|
+
WHERE artifact.id = stale_claims.id;
|
|
80
|
+
|
|
81
|
+
RETURN QUERY
|
|
82
|
+
WITH candidates AS (
|
|
83
|
+
SELECT artifact.id
|
|
84
|
+
FROM %1$I.sandbox_checkpoint_artifacts artifact
|
|
85
|
+
WHERE (
|
|
86
|
+
(
|
|
87
|
+
artifact.state = 'candidate'
|
|
88
|
+
AND artifact.created_at < pg_catalog.now() - interval '15 minutes'
|
|
89
|
+
)
|
|
90
|
+
OR (
|
|
91
|
+
artifact.state IN ('current', 'previous')
|
|
92
|
+
AND artifact.created_at < pg_catalog.now() - interval '15 minutes'
|
|
93
|
+
)
|
|
94
|
+
OR (
|
|
95
|
+
artifact.state IN ('delete_pending', 'delete_failed')
|
|
96
|
+
AND coalesce(artifact.delete_after, artifact.created_at)
|
|
97
|
+
<= pg_catalog.now()
|
|
98
|
+
)
|
|
99
|
+
)
|
|
100
|
+
AND NOT EXISTS (
|
|
101
|
+
SELECT 1 FROM %1$I.sandbox_leases lease
|
|
102
|
+
WHERE lease.current_checkpoint_artifact_id = artifact.id
|
|
103
|
+
OR lease.previous_checkpoint_artifact_id = artifact.id
|
|
104
|
+
OR (
|
|
105
|
+
artifact.provenance = 'native_capture'
|
|
106
|
+
AND lease.id = artifact.source_lease_id
|
|
107
|
+
AND lease.lease_epoch = artifact.source_lease_epoch
|
|
108
|
+
AND lease.instance_id = artifact.source_instance_id
|
|
109
|
+
AND lease.backend = artifact.provider_backend
|
|
110
|
+
AND lease.archive_capture_id IS NOT NULL
|
|
111
|
+
AND lease.archive_capture_generation
|
|
112
|
+
= artifact.source_workspace_generation
|
|
113
|
+
)
|
|
114
|
+
)
|
|
115
|
+
AND NOT EXISTS (
|
|
116
|
+
SELECT 1
|
|
117
|
+
FROM %1$I.rig_versions version
|
|
118
|
+
CROSS JOIN LATERAL pg_catalog.jsonb_each(version.provider_images) provider_image
|
|
119
|
+
WHERE provider_image.value ->> 'artifactId' = artifact.id::text
|
|
120
|
+
AND provider_image.value ->> 'status' = 'ready'
|
|
121
|
+
)
|
|
122
|
+
AND NOT EXISTS (
|
|
123
|
+
SELECT 1
|
|
124
|
+
FROM %1$I.rig_changes change
|
|
125
|
+
JOIN %1$I.rig_versions base
|
|
126
|
+
ON base.id = change.base_version_id
|
|
127
|
+
AND base.workspace_id = change.workspace_id
|
|
128
|
+
AND base.active = true
|
|
129
|
+
WHERE change.status IN ('verifying', 'proposed')
|
|
130
|
+
AND change.verification #>> '{providerImage,artifactId}' = artifact.id::text
|
|
131
|
+
AND change.verification #>> '{providerImage,status}' = 'ready'
|
|
132
|
+
)
|
|
133
|
+
ORDER BY coalesce(artifact.delete_after, artifact.created_at), artifact.id
|
|
134
|
+
FOR UPDATE SKIP LOCKED
|
|
135
|
+
LIMIT p_limit
|
|
136
|
+
)
|
|
137
|
+
UPDATE %1$I.sandbox_checkpoint_artifacts artifact SET
|
|
138
|
+
state = 'deleting',
|
|
139
|
+
delete_attempts = artifact.delete_attempts + 1,
|
|
140
|
+
delete_claim_id = p_claim_id,
|
|
141
|
+
delete_claimed_at = pg_catalog.now(),
|
|
142
|
+
updated_at = pg_catalog.now()
|
|
143
|
+
FROM candidates
|
|
144
|
+
WHERE artifact.id = candidates.id
|
|
145
|
+
RETURNING artifact.id, artifact.provider_backend, artifact.provider_binding_key,
|
|
146
|
+
artifact.provider_binding, artifact.object_kind, artifact.object_id,
|
|
147
|
+
artifact.delete_attempts;
|
|
148
|
+
END;
|
|
149
|
+
$function$;
|
|
150
|
+
$create$, data_schema);
|
|
151
|
+
END
|
|
152
|
+
$rig_provider_image_checkpoint_gc$;
|