@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.
Files changed (52) hide show
  1. package/dist/{chunk-HT5T62CC.js → chunk-P6CUHXQZ.js} +651 -206
  2. package/dist/chunk-P6CUHXQZ.js.map +1 -0
  3. package/dist/{chunk-DBS5HPEW.js → chunk-VHBFHMPC.js} +7 -1
  4. package/dist/chunk-VHBFHMPC.js.map +1 -0
  5. package/dist/environment-crypto.d.ts +8 -4
  6. package/dist/index.d.ts +265 -20
  7. package/dist/index.js +3966 -2185
  8. package/dist/index.js.map +1 -1
  9. package/dist/lossless-columns.d.ts +58 -0
  10. package/dist/lossless-json.d.ts +39 -0
  11. package/dist/memory-domain.d.ts +3 -6
  12. package/dist/persistence-errors.d.ts +7 -14
  13. package/dist/provision-roles.js +1 -1
  14. package/dist/runtime-posture.d.ts +2 -2
  15. package/dist/schema.d.ts +1419 -271
  16. package/dist/schema.js +9 -1
  17. package/dist/session-realtime-terminal.d.ts +7 -0
  18. package/dist/transcription-recordings-schema.d.ts +44 -6
  19. package/dist/transcription-recordings.d.ts +1 -1
  20. package/drizzle/0065_enrollment_credential_generation.sql +10 -0
  21. package/drizzle/0140_retained_screenshot_artifacts.sql +192 -0
  22. package/drizzle/0176_lossless_canonical_json.sql +975 -0
  23. package/drizzle/0177_session_events_workspace_turn_type_index.sql +5 -0
  24. package/drizzle/0178_permissioned_secret_reads.sql +14 -0
  25. package/drizzle/0179_slack_private_shortcut_delivery_gate.sql +85 -0
  26. package/drizzle/0180_retained_screenshot_lifecycle_fences.sql +273 -0
  27. package/drizzle/0181_connected_machine_removal.sql +52 -0
  28. package/drizzle/0182_connected_machine_remove_session_default.sql +77 -0
  29. package/package.json +4 -4
  30. package/src/database.ts +7 -1
  31. package/src/environment-crypto.ts +22 -9
  32. package/src/index.ts +4253 -1601
  33. package/src/lossless-columns.ts +35 -0
  34. package/src/lossless-json.ts +322 -0
  35. package/src/memory-domain.ts +5 -44
  36. package/src/persistence-errors.ts +29 -34
  37. package/src/runtime-posture.ts +6 -0
  38. package/src/schema.ts +260 -38
  39. package/src/session-control.ts +125 -76
  40. package/src/session-queue-commands.ts +325 -234
  41. package/src/session-realtime-context.ts +18 -5
  42. package/src/session-realtime-ledger.ts +29 -7
  43. package/src/session-realtime-mirror.ts +4 -2
  44. package/src/session-realtime-terminal.ts +89 -21
  45. package/src/session-realtime.ts +3 -2
  46. package/src/session-tool-call-settlement.ts +29 -15
  47. package/src/transcription-recordings-schema.ts +5 -2
  48. package/src/transcription-recordings.ts +70 -40
  49. package/dist/chunk-DBS5HPEW.js.map +0 -1
  50. package/dist/chunk-HT5T62CC.js.map +0 -1
  51. package/dist/event-payload-sanitizer.d.ts +0 -32
  52. 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-HT5T62CC.js";
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: "string";
217
- columnType: "PgText";
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: [string, ...string[]];
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: "string";
1107
- columnType: "PgText";
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: [string, ...string[]];
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 $$;