@opengeni/db 0.27.11 → 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 (54) hide show
  1. package/dist/{chunk-JYQPJ6Y5.js → chunk-P6CUHXQZ.js} +2967 -2272
  2. package/dist/chunk-P6CUHXQZ.js.map +1 -0
  3. package/dist/{chunk-RPHPNVWW.js → chunk-VHBFHMPC.js} +15 -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 +272 -26
  7. package/dist/index.js +7798 -5008
  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 +1420 -271
  16. package/dist/schema.js +25 -1
  17. package/dist/session-realtime-terminal.d.ts +7 -0
  18. package/dist/transcription-recordings-schema.d.ts +1264 -0
  19. package/dist/transcription-recordings.d.ts +228 -0
  20. package/drizzle/0065_enrollment_credential_generation.sql +10 -0
  21. package/drizzle/0140_retained_screenshot_artifacts.sql +192 -0
  22. package/drizzle/0170_resumable_transcription_recordings.sql +440 -0
  23. package/drizzle/0175_resumable_transcription_provider_deadline.sql +24 -0
  24. package/drizzle/0176_lossless_canonical_json.sql +975 -0
  25. package/drizzle/0177_session_events_workspace_turn_type_index.sql +5 -0
  26. package/drizzle/0178_permissioned_secret_reads.sql +14 -0
  27. package/drizzle/0179_slack_private_shortcut_delivery_gate.sql +85 -0
  28. package/drizzle/0180_retained_screenshot_lifecycle_fences.sql +273 -0
  29. package/drizzle/0181_connected_machine_removal.sql +52 -0
  30. package/drizzle/0182_connected_machine_remove_session_default.sql +77 -0
  31. package/package.json +4 -4
  32. package/src/database.ts +7 -1
  33. package/src/environment-crypto.ts +22 -9
  34. package/src/index.ts +4368 -1678
  35. package/src/lossless-columns.ts +35 -0
  36. package/src/lossless-json.ts +322 -0
  37. package/src/memory-domain.ts +5 -44
  38. package/src/persistence-errors.ts +29 -34
  39. package/src/runtime-posture.ts +14 -0
  40. package/src/schema.ts +264 -42
  41. package/src/session-control.ts +125 -76
  42. package/src/session-queue-commands.ts +325 -234
  43. package/src/session-realtime-context.ts +18 -5
  44. package/src/session-realtime-ledger.ts +29 -7
  45. package/src/session-realtime-mirror.ts +4 -2
  46. package/src/session-realtime-terminal.ts +89 -21
  47. package/src/session-realtime.ts +3 -2
  48. package/src/session-tool-call-settlement.ts +29 -15
  49. package/src/transcription-recordings-schema.ts +253 -0
  50. package/src/transcription-recordings.ts +1538 -0
  51. package/dist/chunk-JYQPJ6Y5.js.map +0 -1
  52. package/dist/chunk-RPHPNVWW.js.map +0 -1
  53. package/dist/event-payload-sanitizer.d.ts +0 -32
  54. package/src/event-payload-sanitizer.ts +0 -377
package/src/schema.ts CHANGED
@@ -11,6 +11,7 @@ import {
11
11
  bigint,
12
12
  boolean,
13
13
  check,
14
+ customType,
14
15
  foreignKey,
15
16
  index,
16
17
  integer,
@@ -21,8 +22,8 @@ import {
21
22
  timestamp,
22
23
  uniqueIndex,
23
24
  uuid,
24
- customType,
25
25
  } from "drizzle-orm/pg-core";
26
+ import { losslessCodecVersion, losslessJsonb, losslessText } from "./lossless-columns";
26
27
 
27
28
  const vector = customType<{ data: number[]; driverData: string }>({
28
29
  dataType() {
@@ -1371,7 +1372,8 @@ export const sessions = pgTable(
1371
1372
  .notNull()
1372
1373
  .references(() => workspaces.id, { onDelete: "cascade" }),
1373
1374
  status: text("status").notNull().default("queued"),
1374
- initialMessage: text("initial_message").notNull(),
1375
+ initialMessage: losslessText("initial_message").notNull(),
1376
+ initialMessageCodecVersion: losslessCodecVersion("initial_message_codec_version"),
1375
1377
  // Invisible host context frozen with the winning session create. The
1376
1378
  // initial turn copies this value so an idempotent repair can never adopt a
1377
1379
  // retrying caller's different instructions.
@@ -1499,10 +1501,9 @@ export const sessions = pgTable(
1499
1501
  nestedAgentDepthPolicySessionId: uuid("nested_agent_depth_policy_session_id"),
1500
1502
  temporalWorkflowId: text("temporal_workflow_id"),
1501
1503
  activeTurnId: uuid("active_turn_id"),
1502
- // Actual input tokens reported for the last model call of the most recent
1503
- // turn. The pre-turn portable compaction trigger reads this as its budget
1504
- // signal (char/4 estimate is the same-turn fallback). Null until a turn with
1505
- // usage has completed.
1504
+ // Actual input tokens reported for the latest authoritative ordinary model
1505
+ // call. Compaction/context clearing invalidates it to null; local history
1506
+ // estimates must never be stored here.
1506
1507
  lastInputTokens: integer("last_input_tokens"),
1507
1508
  // Operator /compact request flag. The API sets
1508
1509
  // it true; the worker honors it BEFORE the next turn's model call by forcing
@@ -1826,8 +1827,10 @@ export const sessionRealtimeEntries = pgTable(
1826
1827
  // result/error to the same ordinary turn. It never denotes a child/fork
1827
1828
  // session.
1828
1829
  turnId: uuid("turn_id"),
1829
- text: text("text"),
1830
- payload: jsonb("payload").$type<Record<string, unknown>>().notNull().default({}),
1830
+ text: losslessText("text"),
1831
+ textCodecVersion: losslessCodecVersion("text_codec_version"),
1832
+ payload: losslessJsonb("payload").$type<Record<string, unknown>>().notNull().default({}),
1833
+ payloadCodecVersion: losslessCodecVersion("payload_codec_version"),
1831
1834
  clientAckedAt: timestamp("client_acked_at", { withTimezone: true }),
1832
1835
  providerAckedAt: timestamp("provider_acked_at", { withTimezone: true }),
1833
1836
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
@@ -1891,14 +1894,6 @@ export const sessionRealtimeEntries = pgTable(
1891
1894
  "session_realtime_entries_delegation_item_check",
1892
1895
  sql`${table.delegationItemId} is null or octet_length(${table.delegationItemId}) between 1 and 1024`,
1893
1896
  ),
1894
- textValid: check(
1895
- "session_realtime_entries_text_check",
1896
- sql`${table.text} is null or octet_length(${table.text}) <= 131072`,
1897
- ),
1898
- payloadValid: check(
1899
- "session_realtime_entries_payload_check",
1900
- sql`octet_length(${table.payload}::text) <= 131072`,
1901
- ),
1902
1897
  turnValid: check(
1903
1898
  "session_realtime_entries_turn_check",
1904
1899
  sql`${table.turnId} is null
@@ -2172,6 +2167,145 @@ export const fileUploads = pgTable(
2172
2167
  }),
2173
2168
  );
2174
2169
 
2170
+ /** Exact pending/ready byte accounting for retained computer screenshots. */
2171
+ export const workspaceScreenshotQuotas = pgTable(
2172
+ "workspace_screenshot_quotas",
2173
+ {
2174
+ workspaceId: uuid("workspace_id")
2175
+ .primaryKey()
2176
+ .references(() => workspaces.id, { onDelete: "cascade" }),
2177
+ accountId: uuid("account_id")
2178
+ .notNull()
2179
+ .references(() => managedAccounts.id, { onDelete: "cascade" }),
2180
+ reservedBytes: bigint("reserved_bytes", { mode: "number" }).notNull().default(0),
2181
+ readyBytes: bigint("ready_bytes", { mode: "number" }).notNull().default(0),
2182
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
2183
+ },
2184
+ (table) => ({
2185
+ workspaceAccount: foreignKey({
2186
+ columns: [table.workspaceId, table.accountId],
2187
+ foreignColumns: [workspaces.id, workspaces.accountId],
2188
+ name: "workspace_screenshot_quotas_workspace_account_fk",
2189
+ }).onDelete("cascade"),
2190
+ nonnegative: check(
2191
+ "workspace_screenshot_quotas_nonnegative_chk",
2192
+ sql`${table.reservedBytes} >= 0 and ${table.readyBytes} >= 0`,
2193
+ ),
2194
+ }),
2195
+ );
2196
+
2197
+ /** Provider-neutral screenshot lifecycle; canonical bytes stay in `files` storage. */
2198
+ export const retainedScreenshotArtifacts = pgTable(
2199
+ "retained_screenshot_artifacts",
2200
+ {
2201
+ // The composite file FK is RESTRICT in migration 0176: only the retained
2202
+ // screenshot lifecycle may remove its backing file after provider cleanup.
2203
+ artifactId: uuid("artifact_id").primaryKey(),
2204
+ accountId: uuid("account_id")
2205
+ .notNull()
2206
+ .references(() => managedAccounts.id, { onDelete: "cascade" }),
2207
+ workspaceId: uuid("workspace_id")
2208
+ .notNull()
2209
+ .references(() => workspaces.id, { onDelete: "cascade" }),
2210
+ sessionId: uuid("session_id").references(() => sessions.id, { onDelete: "set null" }),
2211
+ // Turn/attempt foreign keys are installed by migrations 0140/0176.
2212
+ // Those tables are declared later in this monolithic schema module, so
2213
+ // referencing them here would create an eager initialization cycle.
2214
+ turnId: uuid("turn_id"),
2215
+ attemptId: uuid("attempt_id"),
2216
+ settlementKey: text("settlement_key").notNull(),
2217
+ toolCallId: text("tool_call_id").notNull(),
2218
+ toolOutputId: text("tool_output_id").notNull(),
2219
+ status: text("status")
2220
+ .$type<
2221
+ | "pending"
2222
+ | "reconciling"
2223
+ | "ready"
2224
+ | "cleanup_queued"
2225
+ | "cleanup_pending"
2226
+ | "failed"
2227
+ | "expired"
2228
+ | "deleted"
2229
+ >()
2230
+ .notNull()
2231
+ .default("pending"),
2232
+ quotaState: text("quota_state")
2233
+ .$type<"reserved" | "ready" | "released">()
2234
+ .notNull()
2235
+ .default("reserved"),
2236
+ mediaType: text("media_type").notNull(),
2237
+ sizeBytes: bigint("size_bytes", { mode: "number" }).notNull(),
2238
+ sha256: text("sha256").notNull(),
2239
+ width: integer("width").notNull(),
2240
+ height: integer("height").notNull(),
2241
+ retentionExpiresAt: timestamp("retention_expires_at", { withTimezone: true }).notNull(),
2242
+ readyAt: timestamp("ready_at", { withTimezone: true }),
2243
+ cleanupReason: text("cleanup_reason"),
2244
+ lastError: text("last_error"),
2245
+ maintenanceClaimId: uuid("maintenance_claim_id"),
2246
+ maintenanceClaimedAt: timestamp("maintenance_claimed_at", { withTimezone: true }),
2247
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
2248
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
2249
+ },
2250
+ (table) => ({
2251
+ settlementKey: uniqueIndex("retained_screenshot_artifacts_settlement_key_uq").on(
2252
+ table.settlementKey,
2253
+ ),
2254
+ sessionCreated: index("retained_screenshot_artifacts_session_created_idx").on(
2255
+ table.workspaceId,
2256
+ table.sessionId,
2257
+ table.createdAt,
2258
+ table.artifactId,
2259
+ ),
2260
+ readyExpiry: index("retained_screenshot_artifacts_ready_expiry_idx")
2261
+ .on(table.retentionExpiresAt, table.artifactId)
2262
+ .where(sql`${table.status} = 'ready'`),
2263
+ pendingReconcile: index("retained_screenshot_artifacts_pending_reconcile_idx")
2264
+ .on(table.updatedAt, table.artifactId)
2265
+ .where(
2266
+ sql`${table.status} in ('pending', 'reconciling', 'cleanup_queued', 'cleanup_pending')`,
2267
+ ),
2268
+ workspaceAccount: foreignKey({
2269
+ columns: [table.workspaceId, table.accountId],
2270
+ foreignColumns: [workspaces.id, workspaces.accountId],
2271
+ name: "retained_screenshot_artifacts_workspace_account_fk",
2272
+ }).onDelete("cascade"),
2273
+ workspaceFile: foreignKey({
2274
+ columns: [table.workspaceId, table.artifactId],
2275
+ foreignColumns: [files.workspaceId, files.id],
2276
+ name: "retained_screenshot_artifacts_workspace_file_fk",
2277
+ }).onDelete("restrict"),
2278
+ statusValid: check(
2279
+ "retained_screenshot_artifacts_status_chk",
2280
+ sql`${table.status} in ('pending', 'reconciling', 'ready', 'cleanup_queued', 'cleanup_pending', 'failed', 'expired', 'deleted')`,
2281
+ ),
2282
+ quotaStateValid: check(
2283
+ "retained_screenshot_artifacts_quota_state_chk",
2284
+ sql`${table.quotaState} in ('reserved', 'ready', 'released')`,
2285
+ ),
2286
+ statusQuotaValid: check(
2287
+ "retained_screenshot_artifacts_status_quota_chk",
2288
+ sql`(${table.status} in ('pending', 'reconciling') and ${table.quotaState} = 'reserved')
2289
+ or (${table.status} = 'ready' and ${table.quotaState} = 'ready')
2290
+ or (${table.status} in ('cleanup_queued', 'cleanup_pending') and ${table.quotaState} in ('reserved', 'ready'))
2291
+ or (${table.status} in ('failed', 'expired', 'deleted') and ${table.quotaState} = 'released')`,
2292
+ ),
2293
+ claimShapeValid: check(
2294
+ "retained_screenshot_artifacts_claim_shape_chk",
2295
+ sql`(${table.status} in ('reconciling', 'cleanup_pending')
2296
+ and ${table.maintenanceClaimId} is not null
2297
+ and ${table.maintenanceClaimedAt} is not null)
2298
+ or (${table.status} not in ('reconciling', 'cleanup_pending')
2299
+ and ${table.maintenanceClaimId} is null
2300
+ and ${table.maintenanceClaimedAt} is null)`,
2301
+ ),
2302
+ dimensionsValid: check(
2303
+ "retained_screenshot_artifacts_dimensions_chk",
2304
+ sql`${table.width} between 1 and 16384 and ${table.height} between 1 and 16384 and (${table.width}::bigint * ${table.height}::bigint) <= 67108864`,
2305
+ ),
2306
+ }),
2307
+ );
2308
+
2175
2309
  export const documentBases = pgTable(
2176
2310
  "document_bases",
2177
2311
  {
@@ -2381,7 +2515,8 @@ export const knowledgeMemories = pgTable(
2381
2515
  status: text("status").notNull().default("proposed"),
2382
2516
  kind: text("kind").notNull().default("semantic"),
2383
2517
  scope: text("scope").notNull().default("workspace"),
2384
- text: text("text").notNull(),
2518
+ text: losslessText("text").notNull(),
2519
+ textCodecVersion: losslessCodecVersion("text_codec_version"),
2385
2520
  sourceRefs: jsonb("source_refs").$type<unknown[]>().notNull().default([]),
2386
2521
  confidence: integer("confidence").notNull().default(50),
2387
2522
  metadata: jsonb("metadata").$type<Record<string, unknown>>().notNull().default({}),
@@ -2492,7 +2627,8 @@ export const sessionTurns = pgTable(
2492
2627
  status: text("status").notNull(),
2493
2628
  source: text("source").notNull().default("user"),
2494
2629
  position: bigint("position", { mode: "number" }).notNull(),
2495
- prompt: text("prompt").notNull(),
2630
+ prompt: losslessText("prompt").notNull(),
2631
+ promptCodecVersion: losslessCodecVersion("prompt_codec_version"),
2496
2632
  // Host context for this exact turn. System-level at runtime and deliberately
2497
2633
  // separate from the visible prompt/event payload.
2498
2634
  turnInstructions: text("turn_instructions"),
@@ -3151,8 +3287,10 @@ export const sessionSystemUpdates = pgTable(
3151
3287
  classification: text("classification").notNull().default("info"),
3152
3288
  sourceId: text("source_id").notNull(),
3153
3289
  dedupeKey: text("dedupe_key").notNull(),
3154
- summary: text("summary").notNull(),
3155
- payload: jsonb("payload").$type<Record<string, unknown>>().notNull().default({}),
3290
+ summary: losslessText("summary").notNull(),
3291
+ summaryCodecVersion: losslessCodecVersion("summary_codec_version"),
3292
+ payload: losslessJsonb("payload").$type<Record<string, unknown>>().notNull().default({}),
3293
+ payloadCodecVersion: losslessCodecVersion("payload_codec_version"),
3156
3294
  lineage: jsonb("lineage").$type<Record<string, unknown>>().notNull().default({}),
3157
3295
  // Private immutable authority frozen when this machine input is accepted.
3158
3296
  // Public projections intentionally omit connection ids and owner subjects.
@@ -3236,8 +3374,10 @@ export const sessionSystemUpdateOutbox = pgTable(
3236
3374
  kind: text("kind").notNull(),
3237
3375
  classification: text("classification").notNull(),
3238
3376
  sourceId: text("source_id").notNull(),
3239
- summary: text("summary").notNull(),
3240
- payload: jsonb("payload").$type<Record<string, unknown>>().notNull().default({}),
3377
+ summary: losslessText("summary").notNull(),
3378
+ summaryCodecVersion: losslessCodecVersion("summary_codec_version"),
3379
+ payload: losslessJsonb("payload").$type<Record<string, unknown>>().notNull().default({}),
3380
+ payloadCodecVersion: losslessCodecVersion("payload_codec_version"),
3241
3381
  lineage: jsonb("lineage").$type<Record<string, unknown>>().notNull().default({}),
3242
3382
  // Exact private authority copied from the causal parent turn in the source
3243
3383
  // terminal transaction. Delivery retries cannot replace this snapshot.
@@ -3473,7 +3613,8 @@ export const sessionEvents = pgTable(
3473
3613
  duplicateReason: text("duplicate_reason"),
3474
3614
  sequence: integer("sequence").notNull(),
3475
3615
  type: text("type").notNull(),
3476
- payload: jsonb("payload").$type<unknown>().notNull().default({}),
3616
+ payload: losslessJsonb("payload").$type<unknown>().notNull().default({}),
3617
+ payloadCodecVersion: losslessCodecVersion("payload_codec_version"),
3477
3618
  clientEventId: text("client_event_id"),
3478
3619
  producerId: text("producer_id"),
3479
3620
  producerSeq: integer("producer_seq"),
@@ -3508,16 +3649,15 @@ export const sessionEvents = pgTable(
3508
3649
  table.type,
3509
3650
  table.sequence,
3510
3651
  ),
3652
+ workspaceTurnType: index("session_events_workspace_turn_type_idx")
3653
+ .on(table.workspaceId, table.turnId, table.type)
3654
+ .where(sql`${table.turnId} is not null`),
3511
3655
  monitoringTail: index("session_events_workspace_session_monitoring_tail_idx")
3512
3656
  .on(table.workspaceId, table.sessionId, table.sequence)
3513
3657
  .where(
3514
3658
  sql`${table.type} not in ('agent.message.delta', 'agent.reasoning.delta', 'sandbox.command.output.delta', 'terminal.pty.output.delta')`,
3515
3659
  ),
3516
3660
  duplicateOfEvent: index("session_events_duplicate_of_event_idx").on(table.duplicateOfEventId),
3517
- payloadBytes: check(
3518
- "session_events_payload_bytes_check",
3519
- sql`octet_length(${table.payload}::text) <= 65536`,
3520
- ),
3521
3661
  typeBytes: check(
3522
3662
  "session_events_type_bytes_check",
3523
3663
  sql`octet_length(${table.type}) <= 256 and position(E'\n' in ${table.type}) = 0 and position(E'\r' in ${table.type}) = 0`,
@@ -3556,8 +3696,10 @@ export const agentRunStates = pgTable("agent_run_states", {
3556
3696
  onDelete: "set null",
3557
3697
  }),
3558
3698
  stateVersion: integer("state_version").notNull(),
3559
- serializedRunState: text("serialized_run_state").notNull(),
3560
- pendingApprovals: jsonb("pending_approvals").$type<unknown[]>().notNull().default([]),
3699
+ serializedRunState: losslessText("serialized_run_state").notNull(),
3700
+ serializedRunStateCodecVersion: losslessCodecVersion("serialized_run_state_codec_version"),
3701
+ pendingApprovals: losslessJsonb("pending_approvals").$type<unknown[]>().notNull().default([]),
3702
+ pendingApprovalsCodecVersion: losslessCodecVersion("pending_approvals_codec_version"),
3561
3703
  // Exact provider rejection marks the latest current-turn receipt only when it
3562
3704
  // was part of the rejected request. The serialized receipt remains durable;
3563
3705
  // recovery builds a temporary view without unusable opaque artifacts.
@@ -3652,8 +3794,8 @@ export const sessionHumanInputRequests = pgTable(
3652
3794
  );
3653
3795
 
3654
3796
  // Conversation truth: ordered, verbatim SDK input items (issue #35). The
3655
- // model-facing memory store — unredacted and replay-ready. session_events
3656
- // remains the redacted human/audit timeline.
3797
+ // model-facing memory store — exact and replay-ready. session_events is also
3798
+ // exact canonical OpenGeni data; transport projections must not rewrite it.
3657
3799
  export const sessionHistoryItems = pgTable(
3658
3800
  "session_history_items",
3659
3801
  {
@@ -3677,7 +3819,8 @@ export const sessionHistoryItems = pgTable(
3677
3819
  // positions; only the summary uses the half-step. `mode: "number"` maps the
3678
3820
  // postgres.js string back to a JS number so every reader stays numeric.
3679
3821
  position: numeric("position", { mode: "number" }).notNull(),
3680
- item: jsonb("item").$type<Record<string, unknown>>().notNull(),
3822
+ item: losslessJsonb("item").$type<Record<string, unknown>>().notNull(),
3823
+ itemCodecVersion: losslessCodecVersion("item_codec_version"),
3681
3824
  // Live-row flag for client-side context compaction. The read path selects
3682
3825
  // only active rows; a compaction supersedes the summarized prefix (sets this
3683
3826
  // false — never deletes, so the full transcript stays as an audit trail) and
@@ -3707,7 +3850,7 @@ export const sessionHistoryItems = pgTable(
3707
3850
 
3708
3851
  // Turn-lineage ledger for a tool call that the SDK emitted but has not yet
3709
3852
  // produced a durably reconciled result. The raw call item is model-facing truth
3710
- // (not the redacted session-event projection). The attempt/generation identify
3853
+ // (not a transport projection). The attempt/generation identify
3711
3854
  // where the call originated, but the receipt survives an approval resume into a
3712
3855
  // newer attempt of the same logical turn. Turn-ending transactions
3713
3856
  // consume these rows atomically and append a valid interrupted result so a
@@ -3733,9 +3876,11 @@ export const sessionPendingToolCalls = pgTable(
3733
3876
  attemptId: uuid("attempt_id").notNull(),
3734
3877
  callId: text("call_id").notNull(),
3735
3878
  callType: text("call_type").notNull(),
3736
- callItem: jsonb("call_item").$type<Record<string, unknown>>().notNull(),
3879
+ callItem: losslessJsonb("call_item").$type<Record<string, unknown>>().notNull(),
3880
+ callItemCodecVersion: losslessCodecVersion("call_item_codec_version"),
3737
3881
  modelToolOutputTruncationTokens: integer("model_tool_output_truncation_tokens"),
3738
- resultItem: jsonb("result_item").$type<Record<string, unknown>>(),
3882
+ resultItem: losslessJsonb("result_item").$type<Record<string, unknown>>(),
3883
+ resultItemCodecVersion: losslessCodecVersion("result_item_codec_version"),
3739
3884
  resultRecordedAt: timestamp("result_recorded_at", { withTimezone: true }),
3740
3885
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
3741
3886
  },
@@ -3774,7 +3919,8 @@ export const sandboxSessionEnvelopes = pgTable(
3774
3919
  sessionId: uuid("session_id")
3775
3920
  .notNull()
3776
3921
  .references(() => sessions.id, { onDelete: "cascade" }),
3777
- envelope: jsonb("envelope").$type<Record<string, unknown>>().notNull(),
3922
+ envelope: losslessJsonb("envelope").$type<Record<string, unknown>>().notNull(),
3923
+ envelopeCodecVersion: losslessCodecVersion("envelope_codec_version"),
3778
3924
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
3779
3925
  updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
3780
3926
  },
@@ -4550,7 +4696,8 @@ export const sessionRecordings = pgTable(
4550
4696
  width: integer("width").notNull(),
4551
4697
  height: integer("height").notNull(),
4552
4698
 
4553
- reason: text("reason"),
4699
+ reason: losslessText("reason"),
4700
+ reasonCodecVersion: losslessCodecVersion("reason_codec_version"),
4554
4701
 
4555
4702
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
4556
4703
  finalizedAt: timestamp("finalized_at", { withTimezone: true }),
@@ -4760,6 +4907,10 @@ export const enrollments = pgTable(
4760
4907
  desktopUnavailableReason: text("desktop_unavailable_reason"),
4761
4908
  allowScreenControl: boolean("allow_screen_control").notNull().default(false),
4762
4909
  status: text("status", { enum: enrollmentStatusValues }).notNull().default("active"),
4910
+ // Credential-family fence. Existing rows/migration-era bearers are generation
4911
+ // 1; every successful re-enrollment increments this atomically before a new
4912
+ // bearer is signed. Auth and self-revoke require an exact row/claim match.
4913
+ credentialGeneration: integer("credential_generation").notNull().default(1),
4763
4914
  os: text("os", { enum: enrollmentOsValues }).notNull().default("linux"),
4764
4915
  arch: text("arch").notNull().default("x86_64"),
4765
4916
  // Heartbeat liveness cursor. Null until the first connect.
@@ -4787,6 +4938,68 @@ export const enrollments = pgTable(
4787
4938
  }),
4788
4939
  );
4789
4940
 
4941
+ // One durable receipt per workspace-authorized connected-machine removal
4942
+ // request. The enrollment row remains the lifecycle truth; this table preserves
4943
+ // the exact idempotency key, request fingerprint, and terminal result so a lost
4944
+ // response can be replayed without re-running dependency checks or mutating a
4945
+ // different enrollment that happens to share the same display name.
4946
+ export const machineRemovalOperationOutcomeValues = [
4947
+ "removed",
4948
+ "already_removed",
4949
+ "blocked",
4950
+ ] as const;
4951
+
4952
+ export const machineRemovalOperations = pgTable(
4953
+ "machine_removal_operations",
4954
+ {
4955
+ id: uuid("id").primaryKey().defaultRandom(),
4956
+ accountId: uuid("account_id")
4957
+ .notNull()
4958
+ .references(() => managedAccounts.id, { onDelete: "cascade" }),
4959
+ workspaceId: uuid("workspace_id")
4960
+ .notNull()
4961
+ .references(() => workspaces.id, { onDelete: "cascade" }),
4962
+ enrollmentId: uuid("enrollment_id")
4963
+ .notNull()
4964
+ .references(() => enrollments.id, { onDelete: "restrict" }),
4965
+ operationKey: text("operation_key").notNull(),
4966
+ requestFingerprint: text("request_fingerprint").notNull(),
4967
+ outcome: text("outcome", { enum: machineRemovalOperationOutcomeValues }).notNull(),
4968
+ result: jsonb("result").$type<Record<string, unknown>>().notNull().default({}),
4969
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
4970
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
4971
+ },
4972
+ (table) => ({
4973
+ workspaceAccount: foreignKey({
4974
+ name: "machine_removal_operations_workspace_account_fk",
4975
+ columns: [table.workspaceId, table.accountId],
4976
+ foreignColumns: [workspaces.id, workspaces.accountId],
4977
+ }).onDelete("cascade"),
4978
+ workspaceOperation: uniqueIndex("machine_removal_operations_workspace_operation_uq").on(
4979
+ table.workspaceId,
4980
+ table.operationKey,
4981
+ ),
4982
+ workspaceIdentity: uniqueIndex("machine_removal_operations_workspace_id_uq").on(
4983
+ table.workspaceId,
4984
+ table.id,
4985
+ ),
4986
+ enrollmentTimeline: index("machine_removal_operations_enrollment_created_idx").on(
4987
+ table.workspaceId,
4988
+ table.enrollmentId,
4989
+ table.createdAt,
4990
+ ),
4991
+ requestFingerprintValid: check(
4992
+ "machine_removal_operations_request_fingerprint_chk",
4993
+ sql`${table.requestFingerprint} ~ '^[0-9a-f]{64}$'`,
4994
+ ),
4995
+ operationKeyValid: check(
4996
+ "machine_removal_operations_operation_key_chk",
4997
+ sql`length(btrim(${table.operationKey})) between 1 and 200
4998
+ and ${table.operationKey} = btrim(${table.operationKey})`,
4999
+ ),
5000
+ }),
5001
+ );
5002
+
4790
5003
  // The OAuth 2.0 device-authorization (RFC 8628) PENDING request (M5, migration
4791
5004
  // 0025 / enrollment + §18 LOUD consent). An agent's `enroll` starts
4792
5005
  // a flow (POST /enrollments/device/start) → one short-TTL, single-use row keyed by
@@ -5405,7 +5618,8 @@ export const hostExportConfig = pgTable(
5405
5618
  /**
5406
5619
  * Transactional delivery buffer. It intentionally has no tenant/source FKs:
5407
5620
  * a workspace deletion must not erase an already-committed, unacknowledged
5408
- * host fact. Payloads are sanitized/bounded before they reach this table.
5621
+ * host fact. Session-event payloads retain their exact storage bytes plus
5622
+ * explicit codec truth; usage payloads remain ordinary JSON.
5409
5623
  */
5410
5624
  export const hostExportOutbox = pgTable(
5411
5625
  "host_export_outbox",
@@ -5435,6 +5649,7 @@ export const hostExportOutbox = pgTable(
5435
5649
  .default({}),
5436
5650
  origin: text("origin"),
5437
5651
  payload: jsonb("payload").$type<unknown>().notNull(),
5652
+ payloadCodecVersion: losslessCodecVersion("payload_codec_version"),
5438
5653
  envelopeBytes: integer("envelope_bytes").notNull(),
5439
5654
  occurredAt: timestamp("occurred_at", { withTimezone: true }).notNull(),
5440
5655
  sourceRecordedAt: timestamp("source_recorded_at", { withTimezone: true }).notNull(),
@@ -5510,6 +5725,7 @@ export const hostExportConsumers = pgTable(
5510
5725
  consecutiveFailures: integer("consecutive_failures").notNull().default(0),
5511
5726
  nextAttemptAt: timestamp("next_attempt_at", { withTimezone: true }).notNull().defaultNow(),
5512
5727
  lastError: text("last_error"),
5728
+ lastErrorCodecVersion: losslessCodecVersion("last_error_codec_version"),
5513
5729
  lastErrorAt: timestamp("last_error_at", { withTimezone: true }),
5514
5730
  blockedAt: timestamp("blocked_at", { withTimezone: true }),
5515
5731
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
@@ -5543,7 +5759,9 @@ export const hostExportDeadLetters = pgTable(
5543
5759
  exportCursor: bigint("export_cursor", { mode: "bigint" }).notNull(),
5544
5760
  sourceId: uuid("source_id").notNull(),
5545
5761
  reason: text("reason").notNull(),
5546
- envelope: jsonb("envelope").$type<Record<string, unknown>>().notNull(),
5762
+ envelope: losslessJsonb("envelope").$type<Record<string, unknown>>().notNull(),
5763
+ envelopeCodecVersion: losslessCodecVersion("envelope_codec_version"),
5764
+ eventPayloadCodecVersion: losslessCodecVersion("event_payload_codec_version"),
5547
5765
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
5548
5766
  },
5549
5767
  (table) => ({
@@ -5644,7 +5862,8 @@ export const auditEvents = pgTable(
5644
5862
  action: text("action").notNull(),
5645
5863
  targetType: text("target_type"),
5646
5864
  targetId: text("target_id"),
5647
- metadata: jsonb("metadata").$type<Record<string, unknown>>().notNull().default({}),
5865
+ metadata: losslessJsonb("metadata").$type<Record<string, unknown>>().notNull().default({}),
5866
+ metadataCodecVersion: losslessCodecVersion("metadata_codec_version"),
5648
5867
  occurredAt: timestamp("occurred_at", { withTimezone: true }).notNull().defaultNow(),
5649
5868
  },
5650
5869
  (table) => ({
@@ -6012,11 +6231,13 @@ export const rigChanges = pgTable(
6012
6231
  }),
6013
6232
  // 'setup_append' | 'definition_edit' (CHECK in migration 0047).
6014
6233
  kind: text("kind").notNull(),
6015
- payload: jsonb("payload").$type<Record<string, unknown>>().notNull(),
6234
+ payload: losslessJsonb("payload").$type<Record<string, unknown>>().notNull(),
6235
+ payloadCodecVersion: losslessCodecVersion("payload_codec_version"),
6016
6236
  // 'proposed' | 'verifying' | 'merged' | 'rejected' | 'failed' (CHECK in 0047).
6017
6237
  status: text("status").notNull().default("proposed"),
6018
6238
  proposedBy: text("proposed_by"),
6019
- verification: jsonb("verification").$type<Record<string, unknown>>(),
6239
+ verification: losslessJsonb("verification").$type<Record<string, unknown>>(),
6240
+ verificationCodecVersion: losslessCodecVersion("verification_codec_version"),
6020
6241
  resultVersionId: uuid("result_version_id").references(() => rigVersions.id, {
6021
6242
  onDelete: "set null",
6022
6243
  }),
@@ -6037,3 +6258,4 @@ export * from "./workspace-instruction-policies-schema";
6037
6258
  export * from "./preference-registry-schema";
6038
6259
  export * from "./memory-governance-schema";
6039
6260
  export * from "./scoped-knowledge-schema";
6261
+ export * from "./transcription-recordings-schema";