@opengeni/db 0.28.1 → 0.28.9
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/{chunk-HT5T62CC.js → chunk-P6CUHXQZ.js} +651 -206
- package/dist/chunk-P6CUHXQZ.js.map +1 -0
- package/dist/{chunk-DBS5HPEW.js → chunk-VHBFHMPC.js} +7 -1
- package/dist/chunk-VHBFHMPC.js.map +1 -0
- package/dist/environment-crypto.d.ts +8 -4
- package/dist/index.d.ts +265 -20
- package/dist/index.js +3966 -2185
- package/dist/index.js.map +1 -1
- 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/persistence-errors.d.ts +7 -14
- package/dist/provision-roles.js +1 -1
- package/dist/runtime-posture.d.ts +2 -2
- package/dist/schema.d.ts +1419 -271
- package/dist/schema.js +9 -1
- package/dist/session-realtime-terminal.d.ts +7 -0
- package/dist/transcription-recordings-schema.d.ts +44 -6
- package/dist/transcription-recordings.d.ts +1 -1
- 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/package.json +4 -4
- package/src/database.ts +7 -1
- package/src/environment-crypto.ts +22 -9
- package/src/index.ts +4253 -1601
- package/src/lossless-columns.ts +35 -0
- package/src/lossless-json.ts +322 -0
- package/src/memory-domain.ts +5 -44
- package/src/persistence-errors.ts +29 -34
- package/src/runtime-posture.ts +6 -0
- package/src/schema.ts +260 -38
- package/src/session-control.ts +125 -76
- package/src/session-queue-commands.ts +325 -234
- package/src/session-realtime-context.ts +18 -5
- package/src/session-realtime-ledger.ts +29 -7
- package/src/session-realtime-mirror.ts +4 -2
- package/src/session-realtime-terminal.ts +89 -21
- package/src/session-realtime.ts +3 -2
- package/src/session-tool-call-settlement.ts +29 -15
- package/src/transcription-recordings-schema.ts +5 -2
- package/src/transcription-recordings.ts +70 -40
- package/dist/chunk-DBS5HPEW.js.map +0 -1
- 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
package/dist/schema.js
CHANGED
|
@@ -59,6 +59,8 @@ import {
|
|
|
59
59
|
knowledgeSyncRuns,
|
|
60
60
|
machineMetricsLatest,
|
|
61
61
|
machineMetricsSeries,
|
|
62
|
+
machineRemovalOperationOutcomeValues,
|
|
63
|
+
machineRemovalOperations,
|
|
62
64
|
managedAccounts,
|
|
63
65
|
modelCallFacts,
|
|
64
66
|
nestedAgentDepthConfiguration,
|
|
@@ -68,6 +70,7 @@ import {
|
|
|
68
70
|
preferenceRegistryPreferences,
|
|
69
71
|
preferenceRegistryRevisions,
|
|
70
72
|
preferenceRegistrySnapshots,
|
|
73
|
+
retainedScreenshotArtifacts,
|
|
71
74
|
rigChanges,
|
|
72
75
|
rigVersions,
|
|
73
76
|
rigs,
|
|
@@ -144,11 +147,12 @@ import {
|
|
|
144
147
|
workspaceMemberships,
|
|
145
148
|
workspaceModelPolicies,
|
|
146
149
|
workspacePacks,
|
|
150
|
+
workspaceScreenshotQuotas,
|
|
147
151
|
workspaceSessionActivityRevisions,
|
|
148
152
|
workspaceVariableSetVariables,
|
|
149
153
|
workspaceVariableSets,
|
|
150
154
|
workspaces
|
|
151
|
-
} from "./chunk-
|
|
155
|
+
} from "./chunk-P6CUHXQZ.js";
|
|
152
156
|
import "./chunk-PZ5AY32C.js";
|
|
153
157
|
export {
|
|
154
158
|
agentRunStates,
|
|
@@ -211,6 +215,8 @@ export {
|
|
|
211
215
|
knowledgeSyncRuns,
|
|
212
216
|
machineMetricsLatest,
|
|
213
217
|
machineMetricsSeries,
|
|
218
|
+
machineRemovalOperationOutcomeValues,
|
|
219
|
+
machineRemovalOperations,
|
|
214
220
|
managedAccounts,
|
|
215
221
|
modelCallFacts,
|
|
216
222
|
nestedAgentDepthConfiguration,
|
|
@@ -220,6 +226,7 @@ export {
|
|
|
220
226
|
preferenceRegistryPreferences,
|
|
221
227
|
preferenceRegistryRevisions,
|
|
222
228
|
preferenceRegistrySnapshots,
|
|
229
|
+
retainedScreenshotArtifacts,
|
|
223
230
|
rigChanges,
|
|
224
231
|
rigVersions,
|
|
225
232
|
rigs,
|
|
@@ -296,6 +303,7 @@ export {
|
|
|
296
303
|
workspaceMemberships,
|
|
297
304
|
workspaceModelPolicies,
|
|
298
305
|
workspacePacks,
|
|
306
|
+
workspaceScreenshotQuotas,
|
|
299
307
|
workspaceSessionActivityRevisions,
|
|
300
308
|
workspaceVariableSetVariables,
|
|
301
309
|
workspaceVariableSets,
|
|
@@ -6,9 +6,11 @@ export type ProjectSessionRealtimeDelegationTerminalInput = {
|
|
|
6
6
|
turnId: string;
|
|
7
7
|
turnStatus: "completed" | "failed" | "cancelled" | "superseded";
|
|
8
8
|
terminalEvent: {
|
|
9
|
+
id: string | null;
|
|
9
10
|
type: "turn.completed" | "turn.failed" | "turn.cancelled" | "turn.superseded";
|
|
10
11
|
payload: Record<string, unknown>;
|
|
11
12
|
};
|
|
13
|
+
retainedOutputEvidence?: unknown;
|
|
12
14
|
now?: Date;
|
|
13
15
|
};
|
|
14
16
|
export type SessionRealtimeTerminalEntry = {
|
|
@@ -36,5 +38,10 @@ export type ProjectSessionRealtimeDelegationTerminalResult = {
|
|
|
36
38
|
entry: SessionRealtimeTerminalEntry;
|
|
37
39
|
replay: boolean;
|
|
38
40
|
} | null;
|
|
41
|
+
export declare function buildSessionRealtimeDelegationTerminalProjection(input: ProjectSessionRealtimeDelegationTerminalInput): {
|
|
42
|
+
kind: "delegation_result" | "error";
|
|
43
|
+
text: string;
|
|
44
|
+
payload: Record<string, unknown>;
|
|
45
|
+
};
|
|
39
46
|
/** One terminal projection for every realtime-delegated durable turn. */
|
|
40
47
|
export declare function projectSessionRealtimeDelegationTerminalInTransaction(db: Database, input: ProjectSessionRealtimeDelegationTerminalInput): Promise<ProjectSessionRealtimeDelegationTerminalResult>;
|
|
@@ -213,8 +213,8 @@ export declare const transcriptionRecordings: import("drizzle-orm/pg-core").PgTa
|
|
|
213
213
|
transcriptText: import("drizzle-orm/pg-core").PgColumn<{
|
|
214
214
|
name: "transcript_text";
|
|
215
215
|
tableName: "transcription_recordings";
|
|
216
|
-
dataType: "
|
|
217
|
-
columnType: "
|
|
216
|
+
dataType: "custom";
|
|
217
|
+
columnType: "PgCustomColumn";
|
|
218
218
|
data: string;
|
|
219
219
|
driverParam: string;
|
|
220
220
|
notNull: false;
|
|
@@ -222,7 +222,26 @@ export declare const transcriptionRecordings: import("drizzle-orm/pg-core").PgTa
|
|
|
222
222
|
isPrimaryKey: false;
|
|
223
223
|
isAutoincrement: false;
|
|
224
224
|
hasRuntimeDefault: false;
|
|
225
|
-
enumValues:
|
|
225
|
+
enumValues: undefined;
|
|
226
|
+
baseColumn: never;
|
|
227
|
+
identity: undefined;
|
|
228
|
+
generated: undefined;
|
|
229
|
+
}, {}, {
|
|
230
|
+
pgColumnBuilderBrand: 'PgCustomColumnBuilderBrand';
|
|
231
|
+
}>;
|
|
232
|
+
transcriptTextCodecVersion: import("drizzle-orm/pg-core").PgColumn<{
|
|
233
|
+
name: "transcript_text_codec_version";
|
|
234
|
+
tableName: "transcription_recordings";
|
|
235
|
+
dataType: "number";
|
|
236
|
+
columnType: "PgInteger";
|
|
237
|
+
data: number;
|
|
238
|
+
driverParam: string | number;
|
|
239
|
+
notNull: false;
|
|
240
|
+
hasDefault: false;
|
|
241
|
+
isPrimaryKey: false;
|
|
242
|
+
isAutoincrement: false;
|
|
243
|
+
hasRuntimeDefault: false;
|
|
244
|
+
enumValues: undefined;
|
|
226
245
|
baseColumn: never;
|
|
227
246
|
identity: undefined;
|
|
228
247
|
generated: undefined;
|
|
@@ -1103,8 +1122,8 @@ export declare const transcriptionRecordingSegments: import("drizzle-orm/pg-core
|
|
|
1103
1122
|
transcriptText: import("drizzle-orm/pg-core").PgColumn<{
|
|
1104
1123
|
name: "transcript_text";
|
|
1105
1124
|
tableName: "transcription_recording_segments";
|
|
1106
|
-
dataType: "
|
|
1107
|
-
columnType: "
|
|
1125
|
+
dataType: "custom";
|
|
1126
|
+
columnType: "PgCustomColumn";
|
|
1108
1127
|
data: string;
|
|
1109
1128
|
driverParam: string;
|
|
1110
1129
|
notNull: false;
|
|
@@ -1112,7 +1131,26 @@ export declare const transcriptionRecordingSegments: import("drizzle-orm/pg-core
|
|
|
1112
1131
|
isPrimaryKey: false;
|
|
1113
1132
|
isAutoincrement: false;
|
|
1114
1133
|
hasRuntimeDefault: false;
|
|
1115
|
-
enumValues:
|
|
1134
|
+
enumValues: undefined;
|
|
1135
|
+
baseColumn: never;
|
|
1136
|
+
identity: undefined;
|
|
1137
|
+
generated: undefined;
|
|
1138
|
+
}, {}, {
|
|
1139
|
+
pgColumnBuilderBrand: 'PgCustomColumnBuilderBrand';
|
|
1140
|
+
}>;
|
|
1141
|
+
transcriptTextCodecVersion: import("drizzle-orm/pg-core").PgColumn<{
|
|
1142
|
+
name: "transcript_text_codec_version";
|
|
1143
|
+
tableName: "transcription_recording_segments";
|
|
1144
|
+
dataType: "number";
|
|
1145
|
+
columnType: "PgInteger";
|
|
1146
|
+
data: number;
|
|
1147
|
+
driverParam: string | number;
|
|
1148
|
+
notNull: false;
|
|
1149
|
+
hasDefault: false;
|
|
1150
|
+
isPrimaryKey: false;
|
|
1151
|
+
isAutoincrement: false;
|
|
1152
|
+
hasRuntimeDefault: false;
|
|
1153
|
+
enumValues: undefined;
|
|
1116
1154
|
baseColumn: never;
|
|
1117
1155
|
identity: undefined;
|
|
1118
1156
|
generated: undefined;
|
|
@@ -171,7 +171,7 @@ export declare function startTranscriptionRecordingSegmentProviderCall(db: Datab
|
|
|
171
171
|
providerStartedAt: Date;
|
|
172
172
|
providerDeadlineAt: Date;
|
|
173
173
|
}): Promise<void>;
|
|
174
|
-
export declare function assembleTranscriptionSegments(segments: readonly Pick<SegmentRow, "segmentNumber" | "transcriptText" | "languages">[]): {
|
|
174
|
+
export declare function assembleTranscriptionSegments(segments: readonly (Pick<SegmentRow, "segmentNumber" | "transcriptText" | "languages"> & Partial<Pick<SegmentRow, "transcriptTextCodecVersion">>)[]): {
|
|
175
175
|
text: string;
|
|
176
176
|
languages: string[];
|
|
177
177
|
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
-- deployment-mode: rolling
|
|
2
|
+
-- Enrollment credential-generation fence.
|
|
3
|
+
--
|
|
4
|
+
-- Schema-first/backward-compatible rollout: every pre-existing enrollment is
|
|
5
|
+
-- generation 1, matching legacy signed bearers that did not carry an explicit
|
|
6
|
+
-- generation claim. New binaries atomically increment this column whenever the
|
|
7
|
+
-- same machine identity is enrolled again and require the signed claim to match.
|
|
8
|
+
|
|
9
|
+
ALTER TABLE "enrollments"
|
|
10
|
+
ADD COLUMN IF NOT EXISTS "credential_generation" integer NOT NULL DEFAULT 1;
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
-- deployment-mode: rolling
|
|
2
|
+
-- Retain computer screenshots as deterministic, tenant-owned files while
|
|
3
|
+
-- keeping provider object locations server-private. Pending/ready bytes are
|
|
4
|
+
-- quota-accounted, and one bounded SECURITY DEFINER claim seam drives stale
|
|
5
|
+
-- settlement reconciliation plus expiry/orphan cleanup across FORCE-RLS rows.
|
|
6
|
+
|
|
7
|
+
CREATE UNIQUE INDEX IF NOT EXISTS "files_workspace_id_uq"
|
|
8
|
+
ON "files" ("workspace_id", "id");
|
|
9
|
+
|
|
10
|
+
CREATE TABLE "workspace_screenshot_quotas" (
|
|
11
|
+
"workspace_id" uuid PRIMARY KEY,
|
|
12
|
+
"account_id" uuid NOT NULL,
|
|
13
|
+
"reserved_bytes" bigint NOT NULL DEFAULT 0,
|
|
14
|
+
"ready_bytes" bigint NOT NULL DEFAULT 0,
|
|
15
|
+
"updated_at" timestamptz NOT NULL DEFAULT now(),
|
|
16
|
+
CONSTRAINT "workspace_screenshot_quotas_workspace_account_fk"
|
|
17
|
+
FOREIGN KEY ("workspace_id", "account_id")
|
|
18
|
+
REFERENCES "workspaces"("id", "account_id") ON DELETE CASCADE,
|
|
19
|
+
CONSTRAINT "workspace_screenshot_quotas_nonnegative_chk"
|
|
20
|
+
CHECK ("reserved_bytes" >= 0 AND "ready_bytes" >= 0)
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
CREATE TABLE "retained_screenshot_artifacts" (
|
|
24
|
+
"artifact_id" uuid PRIMARY KEY,
|
|
25
|
+
"account_id" uuid NOT NULL,
|
|
26
|
+
"workspace_id" uuid NOT NULL,
|
|
27
|
+
"session_id" uuid NOT NULL,
|
|
28
|
+
"turn_id" uuid NOT NULL,
|
|
29
|
+
"attempt_id" uuid NOT NULL,
|
|
30
|
+
"settlement_key" text NOT NULL,
|
|
31
|
+
"tool_call_id" text NOT NULL,
|
|
32
|
+
"tool_output_id" text NOT NULL,
|
|
33
|
+
"status" text NOT NULL DEFAULT 'pending',
|
|
34
|
+
"media_type" text NOT NULL,
|
|
35
|
+
"size_bytes" bigint NOT NULL,
|
|
36
|
+
"sha256" text NOT NULL,
|
|
37
|
+
"width" integer NOT NULL,
|
|
38
|
+
"height" integer NOT NULL,
|
|
39
|
+
"retention_expires_at" timestamptz NOT NULL,
|
|
40
|
+
"ready_at" timestamptz,
|
|
41
|
+
"cleanup_reason" text,
|
|
42
|
+
"last_error" text,
|
|
43
|
+
"created_at" timestamptz NOT NULL DEFAULT now(),
|
|
44
|
+
"updated_at" timestamptz NOT NULL DEFAULT now(),
|
|
45
|
+
CONSTRAINT "retained_screenshot_artifacts_workspace_account_fk"
|
|
46
|
+
FOREIGN KEY ("workspace_id", "account_id")
|
|
47
|
+
REFERENCES "workspaces"("id", "account_id") ON DELETE CASCADE,
|
|
48
|
+
CONSTRAINT "retained_screenshot_artifacts_workspace_session_fk"
|
|
49
|
+
FOREIGN KEY ("workspace_id", "session_id")
|
|
50
|
+
REFERENCES "sessions"("workspace_id", "id") ON DELETE CASCADE,
|
|
51
|
+
CONSTRAINT "retained_screenshot_artifacts_workspace_turn_fk"
|
|
52
|
+
FOREIGN KEY ("workspace_id", "turn_id")
|
|
53
|
+
REFERENCES "session_turns"("workspace_id", "id") ON DELETE CASCADE,
|
|
54
|
+
CONSTRAINT "retained_screenshot_artifacts_workspace_attempt_fk"
|
|
55
|
+
FOREIGN KEY ("workspace_id", "attempt_id")
|
|
56
|
+
REFERENCES "session_turn_attempts"("workspace_id", "id") ON DELETE RESTRICT,
|
|
57
|
+
CONSTRAINT "retained_screenshot_artifacts_workspace_file_fk"
|
|
58
|
+
FOREIGN KEY ("workspace_id", "artifact_id")
|
|
59
|
+
REFERENCES "files"("workspace_id", "id") ON DELETE CASCADE,
|
|
60
|
+
CONSTRAINT "retained_screenshot_artifacts_settlement_key_uq"
|
|
61
|
+
UNIQUE ("settlement_key"),
|
|
62
|
+
CONSTRAINT "retained_screenshot_artifacts_status_chk"
|
|
63
|
+
CHECK ("status" IN ('pending', 'reconciling', 'ready', 'cleanup_pending', 'failed', 'expired', 'deleted')),
|
|
64
|
+
CONSTRAINT "retained_screenshot_artifacts_media_type_chk"
|
|
65
|
+
CHECK ("media_type" = 'image/png'),
|
|
66
|
+
CONSTRAINT "retained_screenshot_artifacts_size_chk"
|
|
67
|
+
CHECK ("size_bytes" > 0 AND "size_bytes" <= 33554432),
|
|
68
|
+
CONSTRAINT "retained_screenshot_artifacts_sha256_chk"
|
|
69
|
+
CHECK ("sha256" ~ '^[0-9a-f]{64}$'),
|
|
70
|
+
CONSTRAINT "retained_screenshot_artifacts_dimensions_chk"
|
|
71
|
+
CHECK (
|
|
72
|
+
"width" BETWEEN 1 AND 16384
|
|
73
|
+
AND "height" BETWEEN 1 AND 16384
|
|
74
|
+
AND ("width"::bigint * "height"::bigint) <= 67108864
|
|
75
|
+
),
|
|
76
|
+
CONSTRAINT "retained_screenshot_artifacts_ready_shape_chk"
|
|
77
|
+
CHECK (
|
|
78
|
+
("status" = 'ready' AND "ready_at" IS NOT NULL)
|
|
79
|
+
OR ("status" IN ('pending', 'reconciling') AND "ready_at" IS NULL)
|
|
80
|
+
OR "status" IN ('cleanup_pending', 'failed', 'expired', 'deleted')
|
|
81
|
+
),
|
|
82
|
+
CONSTRAINT "retained_screenshot_artifacts_terminal_cleanup_chk"
|
|
83
|
+
CHECK (
|
|
84
|
+
("status" IN ('cleanup_pending', 'failed', 'expired', 'deleted'))
|
|
85
|
+
OR "cleanup_reason" IS NULL
|
|
86
|
+
)
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
CREATE INDEX "retained_screenshot_artifacts_session_created_idx"
|
|
90
|
+
ON "retained_screenshot_artifacts" ("workspace_id", "session_id", "created_at", "artifact_id");
|
|
91
|
+
CREATE INDEX "retained_screenshot_artifacts_ready_expiry_idx"
|
|
92
|
+
ON "retained_screenshot_artifacts" ("retention_expires_at", "artifact_id")
|
|
93
|
+
WHERE "status" = 'ready';
|
|
94
|
+
CREATE INDEX "retained_screenshot_artifacts_pending_reconcile_idx"
|
|
95
|
+
ON "retained_screenshot_artifacts" ("updated_at", "artifact_id")
|
|
96
|
+
WHERE "status" IN ('pending', 'reconciling', 'cleanup_pending');
|
|
97
|
+
|
|
98
|
+
ALTER TABLE "workspace_screenshot_quotas" ENABLE ROW LEVEL SECURITY;
|
|
99
|
+
ALTER TABLE "workspace_screenshot_quotas" FORCE ROW LEVEL SECURITY;
|
|
100
|
+
CREATE POLICY "workspace_isolation" ON "workspace_screenshot_quotas"
|
|
101
|
+
USING (opengeni_private.workspace_rls_visible(account_id, workspace_id))
|
|
102
|
+
WITH CHECK (opengeni_private.workspace_rls_visible(account_id, workspace_id));
|
|
103
|
+
|
|
104
|
+
ALTER TABLE "retained_screenshot_artifacts" ENABLE ROW LEVEL SECURITY;
|
|
105
|
+
ALTER TABLE "retained_screenshot_artifacts" FORCE ROW LEVEL SECURITY;
|
|
106
|
+
CREATE POLICY "workspace_isolation" ON "retained_screenshot_artifacts"
|
|
107
|
+
USING (opengeni_private.workspace_rls_visible(account_id, workspace_id))
|
|
108
|
+
WITH CHECK (opengeni_private.workspace_rls_visible(account_id, workspace_id));
|
|
109
|
+
|
|
110
|
+
CREATE OR REPLACE FUNCTION opengeni_private.claim_retained_screenshot_maintenance(
|
|
111
|
+
p_pending_grace_ms bigint,
|
|
112
|
+
p_claim_timeout_ms bigint,
|
|
113
|
+
p_limit integer
|
|
114
|
+
)
|
|
115
|
+
RETURNS TABLE (
|
|
116
|
+
action text,
|
|
117
|
+
artifact_id uuid,
|
|
118
|
+
account_id uuid,
|
|
119
|
+
workspace_id uuid,
|
|
120
|
+
session_id uuid,
|
|
121
|
+
object_key text,
|
|
122
|
+
media_type text,
|
|
123
|
+
size_bytes bigint,
|
|
124
|
+
sha256 text,
|
|
125
|
+
width integer,
|
|
126
|
+
height integer,
|
|
127
|
+
retention_expires_at timestamptz,
|
|
128
|
+
cleanup_reason text
|
|
129
|
+
)
|
|
130
|
+
LANGUAGE sql
|
|
131
|
+
SECURITY DEFINER
|
|
132
|
+
AS $$
|
|
133
|
+
WITH candidates AS (
|
|
134
|
+
SELECT A.artifact_id,
|
|
135
|
+
CASE
|
|
136
|
+
WHEN A.status IN ('pending', 'reconciling') THEN 'reconcile'
|
|
137
|
+
ELSE 'delete'
|
|
138
|
+
END AS action,
|
|
139
|
+
CASE
|
|
140
|
+
WHEN A.status = 'ready' THEN 'expired'
|
|
141
|
+
WHEN A.status IN ('pending', 'reconciling') THEN A.cleanup_reason
|
|
142
|
+
ELSE coalesce(A.cleanup_reason, 'orphaned')
|
|
143
|
+
END AS cleanup_reason
|
|
144
|
+
FROM retained_screenshot_artifacts A
|
|
145
|
+
WHERE
|
|
146
|
+
(A.status = 'ready' AND A.retention_expires_at <= clock_timestamp())
|
|
147
|
+
OR (
|
|
148
|
+
A.status = 'pending'
|
|
149
|
+
AND A.updated_at <= clock_timestamp() - (
|
|
150
|
+
greatest(p_pending_grace_ms, 0)::double precision * interval '1 millisecond'
|
|
151
|
+
)
|
|
152
|
+
)
|
|
153
|
+
OR (
|
|
154
|
+
A.status IN ('reconciling', 'cleanup_pending')
|
|
155
|
+
AND A.updated_at <= clock_timestamp() - (
|
|
156
|
+
greatest(p_claim_timeout_ms, 0)::double precision * interval '1 millisecond'
|
|
157
|
+
)
|
|
158
|
+
)
|
|
159
|
+
ORDER BY A.retention_expires_at, A.artifact_id
|
|
160
|
+
LIMIT least(greatest(p_limit, 0), 1000)
|
|
161
|
+
FOR UPDATE SKIP LOCKED
|
|
162
|
+
), claimed AS (
|
|
163
|
+
UPDATE retained_screenshot_artifacts A
|
|
164
|
+
SET
|
|
165
|
+
status = CASE WHEN C.action = 'reconcile' THEN 'reconciling' ELSE 'cleanup_pending' END,
|
|
166
|
+
cleanup_reason = C.cleanup_reason,
|
|
167
|
+
updated_at = clock_timestamp()
|
|
168
|
+
FROM candidates C
|
|
169
|
+
WHERE A.artifact_id = C.artifact_id
|
|
170
|
+
RETURNING A.*, C.action
|
|
171
|
+
)
|
|
172
|
+
SELECT C.action, C.artifact_id, C.account_id, C.workspace_id, C.session_id,
|
|
173
|
+
F.object_key, C.media_type, C.size_bytes, C.sha256, C.width, C.height,
|
|
174
|
+
C.retention_expires_at, C.cleanup_reason
|
|
175
|
+
FROM claimed C
|
|
176
|
+
JOIN files F
|
|
177
|
+
ON F.workspace_id = C.workspace_id
|
|
178
|
+
AND F.id = C.artifact_id;
|
|
179
|
+
$$;
|
|
180
|
+
|
|
181
|
+
REVOKE ALL ON FUNCTION opengeni_private.claim_retained_screenshot_maintenance(bigint, bigint, integer)
|
|
182
|
+
FROM PUBLIC;
|
|
183
|
+
|
|
184
|
+
DO $$
|
|
185
|
+
BEGIN
|
|
186
|
+
IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'opengeni_app') THEN
|
|
187
|
+
GRANT SELECT, INSERT, UPDATE, DELETE ON "workspace_screenshot_quotas" TO opengeni_app;
|
|
188
|
+
GRANT SELECT, INSERT, UPDATE, DELETE ON "retained_screenshot_artifacts" TO opengeni_app;
|
|
189
|
+
GRANT EXECUTE ON FUNCTION opengeni_private.claim_retained_screenshot_maintenance(bigint, bigint, integer)
|
|
190
|
+
TO opengeni_app;
|
|
191
|
+
END IF;
|
|
192
|
+
END $$;
|