@opengeni/db 0.7.3 → 0.10.7
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-YFQ7SGE4.js → chunk-BMFDXFPA.js} +23 -1
- package/dist/chunk-BMFDXFPA.js.map +1 -0
- package/dist/chunk-KW526IJA.js +127 -0
- package/dist/chunk-KW526IJA.js.map +1 -0
- package/dist/{chunk-B22X3IEZ.js → chunk-P6PKXY5W.js} +604 -32
- package/dist/chunk-P6PKXY5W.js.map +1 -0
- package/dist/index.d.ts +4 -3
- package/dist/index.js +7408 -2276
- package/dist/index.js.map +1 -1
- package/dist/migrate.d.ts +29 -4
- package/dist/migrate.js +3 -1
- package/dist/provision-roles.d.ts +1122 -73
- package/dist/provision-roles.js +1 -1
- package/dist/{schema-BN5mB9xZ.d.ts → schema-CqkzrBRS.d.ts} +6967 -4457
- package/dist/schema.d.ts +1 -1
- package/dist/schema.js +19 -1
- package/drizzle/0053_codex_credential_leases.sql +2 -2
- package/drizzle/0057_durable_queue_control.sql +1 -1
- package/drizzle/0061_session_workflow_wake_outbox.sql +1 -1
- package/drizzle/0062_session_list_snapshot_reaper.sql +1 -1
- package/drizzle/0063_session_control_mega_foundation.sql +1 -1
- package/drizzle/0064_rotation_strategy_sharded_backfill.sql +15 -0
- package/drizzle/0065_codex_subscription_overview.sql +168 -0
- package/drizzle/0065_session_attempt_quiescence.sql +26 -0
- package/drizzle/0065_session_tool_policy.sql +38 -0
- package/drizzle/0066_session_interruption_attempt_lookup.sql +4 -0
- package/drizzle/0067_session_event_payload_bounds.sql +209 -0
- package/drizzle/0068_workspace_control_event_bounds.sql +134 -0
- package/drizzle/0069_session_event_history_backfill.sql +32 -0
- package/drizzle/0070_session_event_type_sequence_lookup.sql +4 -0
- package/drizzle/0071_session_event_monitoring_tail.sql +10 -0
- package/drizzle/0072_sessions_workspace_created_id_idx.sql +4 -0
- package/drizzle/0073_sessions_workspace_updated_id_idx.sql +4 -0
- package/drizzle/0074_session_activity_revisions.sql +72 -0
- package/drizzle/0075_sessions_workspace_activity_revision_idx.sql +4 -0
- package/drizzle/0076_session_workflow_wake_acl.sql +13 -0
- package/drizzle/0077_session_attempt_latest_lookup.sql +4 -0
- package/drizzle/0094_quarantine_credential_bearing_catalog_urls.sql +51 -0
- package/drizzle/0095_github_existing_installations.sql +84 -0
- package/drizzle/0096_session_turn_initiators.sql +97 -0
- package/drizzle/0097_host_export_outbox.sql +1220 -0
- package/drizzle/0098_usage_events_workspace_session_idx.sql +4 -0
- package/drizzle/0099_session_human_input_attempt_owner_index.sql +6 -0
- package/drizzle/0100_session_human_input_requests.sql +89 -0
- package/drizzle/0101_session_mcp_connection_refs.sql +30 -0
- package/drizzle/0102_session_command_receipt_service_actor.sql +16 -0
- package/drizzle/0103_host_export_root_session.sql +166 -0
- package/drizzle/0104_host_export_root_session_backfill.sql +27 -0
- package/drizzle/0105_session_turn_instructions.sql +9 -0
- package/drizzle/0106_session_attempt_mcp_approval_policies.sql +29 -0
- package/drizzle/0107_host_export_lineage_contract.sql +381 -0
- package/drizzle/0108_fence_invalidated_warming_epochs.sql +76 -0
- package/package.json +5 -4
- package/src/codex-token-resolver.ts +175 -14
- package/src/connection-token-resolver.ts +428 -119
- package/src/event-payload-sanitizer.ts +88 -20
- package/src/index.ts +7208 -1273
- package/src/memory-domain.ts +1 -1
- package/src/migrate.ts +86 -23
- package/src/persistence-errors.ts +252 -0
- package/src/provision-roles.ts +42 -0
- package/src/schema.ts +658 -34
- package/src/session-control.ts +520 -38
- package/src/session-queue-commands.ts +385 -61
- package/src/session-tool-call-settlement.ts +58 -7
- package/src/turn-initiator.ts +155 -0
- package/dist/chunk-7LDU7F5P.js +0 -80
- package/dist/chunk-7LDU7F5P.js.map +0 -1
- package/dist/chunk-B22X3IEZ.js.map +0 -1
- package/dist/chunk-YFQ7SGE4.js.map +0 -1
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { boundSessionEventPayload } from "@opengeni/contracts";
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Last line of defense against a session event crashing a whole turn.
|
|
3
5
|
*
|
|
@@ -8,12 +10,10 @@
|
|
|
8
10
|
* such a payload reaches `INSERT INTO session_events`, the driver rejects it
|
|
9
11
|
* ("Failed query: insert into session_events") and the turn dies.
|
|
10
12
|
*
|
|
11
|
-
* `sanitizeEventPayload` deep-walks any payload value (objects, arrays, nested)
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* the two disallowed classes of code unit -- no meaningful text is lost, no
|
|
16
|
-
* truncation (truncation is handled elsewhere).
|
|
13
|
+
* `sanitizeEventPayload` deep-walks any payload value (objects, arrays, nested),
|
|
14
|
+
* repairs every string, redacts sensitive fields, then applies the canonical
|
|
15
|
+
* byte-bounded human/audit preview. Conversation truth uses
|
|
16
|
+
* `sanitizeModelPayload` below and remains a separate representation.
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
19
|
const REPLACEMENT = "�";
|
|
@@ -88,12 +88,53 @@ export function sanitizeEventString(value: string): string {
|
|
|
88
88
|
* combinations are traversed; non-string leaves pass through untouched. Object
|
|
89
89
|
* keys are sanitized too -- they are jsonb-constrained the same as values.
|
|
90
90
|
*/
|
|
91
|
-
export
|
|
91
|
+
export type SanitizeEventPayloadOptions = {
|
|
92
|
+
/**
|
|
93
|
+
* Separately trusted, server-created retained-output evidence. Never populate
|
|
94
|
+
* this from a producer-controlled payload field.
|
|
95
|
+
*/
|
|
96
|
+
fullEvidence?: unknown;
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
export function sanitizeEventPayload<T>(payload: T, options: SanitizeEventPayloadOptions = {}): T {
|
|
100
|
+
// Bound first. The preview walker caps depth/container fan-out and replaces
|
|
101
|
+
// inline media before this sanitizer allocates a deep clone. Reversing this
|
|
102
|
+
// order lets a cyclic, deeply nested, or multi-megabyte tool result exhaust
|
|
103
|
+
// the stack/heap before the durable 64 KiB event boundary can protect it.
|
|
104
|
+
const bounded = boundSessionEventPayload(payload, {
|
|
105
|
+
fullEvidence: options.fullEvidence,
|
|
106
|
+
});
|
|
107
|
+
return sanitizeEventPayloadDeep(
|
|
108
|
+
bounded === payload ? removeProducerTruncationMetadata(bounded) : bounded,
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* `truncation` is reserved durable-boundary metadata. An ordinary payload that
|
|
114
|
+
* already fits the envelope otherwise returns by reference, so remove a
|
|
115
|
+
* producer-supplied value before persistence rather than allowing it to forge
|
|
116
|
+
* byte accounting or an available retained-artifact receipt. A payload changed
|
|
117
|
+
* by `boundSessionEventPayload` already carries freshly computed metadata and
|
|
118
|
+
* never reaches this helper.
|
|
119
|
+
*/
|
|
120
|
+
function removeProducerTruncationMetadata<T>(payload: T): T {
|
|
121
|
+
if (!isPlainObject(payload)) return payload;
|
|
122
|
+
const descriptor = Object.getOwnPropertyDescriptor(payload, "truncation");
|
|
123
|
+
if (!descriptor?.enumerable) return payload;
|
|
124
|
+
const cleaned = { ...payload };
|
|
125
|
+
delete cleaned.truncation;
|
|
126
|
+
return cleaned as T;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function sanitizeEventPayloadDeep<T>(payload: T): T {
|
|
92
130
|
if (typeof payload === "string") {
|
|
93
131
|
return sanitizeEventString(payload) as unknown as T;
|
|
94
132
|
}
|
|
95
133
|
if (Array.isArray(payload)) {
|
|
96
|
-
return payload.map((item) =>
|
|
134
|
+
return payload.map((item) => sanitizeEventPayloadDeep(item)) as unknown as T;
|
|
135
|
+
}
|
|
136
|
+
if (payload instanceof Date) {
|
|
137
|
+
return safeDateIso(payload) as unknown as T;
|
|
97
138
|
}
|
|
98
139
|
if (payload && typeof payload === "object") {
|
|
99
140
|
const entries = Object.entries(payload as Record<string, unknown>).map(
|
|
@@ -115,21 +156,48 @@ export function sanitizeEventPayload<T>(payload: T): T {
|
|
|
115
156
|
* performs only the database-safety repair (NUL removal and UTF-16 repair).
|
|
116
157
|
*/
|
|
117
158
|
export function sanitizeModelPayload<T>(payload: T): T {
|
|
159
|
+
return sanitizeModelPayloadDeep(payload, new WeakSet<object>(), 0);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const MODEL_PAYLOAD_SANITIZE_MAX_DEPTH = 64;
|
|
163
|
+
const MODEL_PAYLOAD_CYCLE_MARKER = "[OpenGeni omitted cyclic model payload]";
|
|
164
|
+
const MODEL_PAYLOAD_DEPTH_MARKER = "[OpenGeni omitted model payload beyond database-safety depth]";
|
|
165
|
+
|
|
166
|
+
function sanitizeModelPayloadDeep<T>(payload: T, seen: WeakSet<object>, depth: number): T {
|
|
118
167
|
if (typeof payload === "string") {
|
|
119
168
|
return sanitizeEventString(payload) as unknown as T;
|
|
120
169
|
}
|
|
121
|
-
if (
|
|
122
|
-
|
|
170
|
+
if (!payload || typeof payload !== "object") return payload;
|
|
171
|
+
if (payload instanceof Date) {
|
|
172
|
+
return safeDateIso(payload) as unknown as T;
|
|
123
173
|
}
|
|
124
|
-
if (
|
|
174
|
+
if (depth >= MODEL_PAYLOAD_SANITIZE_MAX_DEPTH) {
|
|
175
|
+
return MODEL_PAYLOAD_DEPTH_MARKER as unknown as T;
|
|
176
|
+
}
|
|
177
|
+
if (seen.has(payload)) return MODEL_PAYLOAD_CYCLE_MARKER as unknown as T;
|
|
178
|
+
seen.add(payload);
|
|
179
|
+
try {
|
|
180
|
+
if (Array.isArray(payload)) {
|
|
181
|
+
return payload.map((item) => sanitizeModelPayloadDeep(item, seen, depth + 1)) as unknown as T;
|
|
182
|
+
}
|
|
125
183
|
return Object.fromEntries(
|
|
126
184
|
Object.entries(payload as Record<string, unknown>).map(([key, value]) => [
|
|
127
185
|
sanitizeEventString(key),
|
|
128
|
-
|
|
186
|
+
sanitizeModelPayloadDeep(value, seen, depth + 1),
|
|
129
187
|
]),
|
|
130
188
|
) as unknown as T;
|
|
189
|
+
} finally {
|
|
190
|
+
seen.delete(payload);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function safeDateIso(value: Date): string | null {
|
|
195
|
+
try {
|
|
196
|
+
const epoch = Date.prototype.getTime.call(value);
|
|
197
|
+
return Number.isFinite(epoch) ? Date.prototype.toISOString.call(value) : null;
|
|
198
|
+
} catch {
|
|
199
|
+
return null;
|
|
131
200
|
}
|
|
132
|
-
return payload;
|
|
133
201
|
}
|
|
134
202
|
|
|
135
203
|
function sanitizeSensitiveEventField(key: string, value: unknown): unknown {
|
|
@@ -142,19 +210,19 @@ function sanitizeSensitiveEventField(key: string, value: unknown): unknown {
|
|
|
142
210
|
if (SENSITIVE_FIELD_NAMES.has(normalizeFieldName(key))) {
|
|
143
211
|
return REDACTED;
|
|
144
212
|
}
|
|
145
|
-
return
|
|
213
|
+
return sanitizeEventPayloadDeep(value);
|
|
146
214
|
}
|
|
147
215
|
|
|
148
216
|
function sanitizeSessionMcpServerList(value: unknown): unknown {
|
|
149
217
|
if (!Array.isArray(value)) {
|
|
150
|
-
return
|
|
218
|
+
return sanitizeEventPayloadDeep(value);
|
|
151
219
|
}
|
|
152
220
|
return value.map((item) => {
|
|
153
221
|
if (!isPlainObject(item)) {
|
|
154
|
-
return
|
|
222
|
+
return sanitizeEventPayloadDeep(item);
|
|
155
223
|
}
|
|
156
224
|
const { headers, headersEncrypted, ...rest } = item;
|
|
157
|
-
const cleaned =
|
|
225
|
+
const cleaned = sanitizeEventPayloadDeep(rest) as Record<string, unknown>;
|
|
158
226
|
const headerNames = safeHeaderNames(headers) ?? safeHeaderNames(headersEncrypted);
|
|
159
227
|
if (headerNames) {
|
|
160
228
|
cleaned.headerNames = headerNames;
|
|
@@ -165,14 +233,14 @@ function sanitizeSessionMcpServerList(value: unknown): unknown {
|
|
|
165
233
|
|
|
166
234
|
function sanitizeMcpCredentialUpdateList(value: unknown): unknown {
|
|
167
235
|
if (!Array.isArray(value)) {
|
|
168
|
-
return
|
|
236
|
+
return sanitizeEventPayloadDeep(value);
|
|
169
237
|
}
|
|
170
238
|
return value.map((item) => {
|
|
171
239
|
if (!isPlainObject(item)) {
|
|
172
|
-
return
|
|
240
|
+
return sanitizeEventPayloadDeep(item);
|
|
173
241
|
}
|
|
174
242
|
const { headers, headersEncrypted, ...rest } = item;
|
|
175
|
-
const cleaned =
|
|
243
|
+
const cleaned = sanitizeEventPayloadDeep(rest) as Record<string, unknown>;
|
|
176
244
|
const headerNames = safeHeaderNames(headers) ?? safeHeaderNames(headersEncrypted);
|
|
177
245
|
if (headerNames) {
|
|
178
246
|
cleaned.headerNames = headerNames;
|