@opengeni/db 0.6.1 → 0.7.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.
Files changed (53) hide show
  1. package/dist/{chunk-OGCE6O2X.js → chunk-7LDU7F5P.js} +31 -3
  2. package/dist/chunk-7LDU7F5P.js.map +1 -0
  3. package/dist/chunk-B22X3IEZ.js +2634 -0
  4. package/dist/chunk-B22X3IEZ.js.map +1 -0
  5. package/dist/{chunk-57MLICFR.js → chunk-YFQ7SGE4.js} +18 -6
  6. package/dist/chunk-YFQ7SGE4.js.map +1 -0
  7. package/dist/index.d.ts +2 -2
  8. package/dist/index.js +16571 -5018
  9. package/dist/index.js.map +1 -1
  10. package/dist/migrate.js +1 -1
  11. package/dist/provision-roles.d.ts +2121 -248
  12. package/dist/provision-roles.js +1 -1
  13. package/dist/{schema-BUbuMteO.d.ts → schema-BN5mB9xZ.d.ts} +8716 -3432
  14. package/dist/schema.d.ts +1 -1
  15. package/dist/schema.js +43 -5
  16. package/drizzle/0044_reap_dead_turn_holders.sql +104 -0
  17. package/drizzle/0045_workspace_captures.sql +83 -0
  18. package/drizzle/0045_workspace_memory_v1.sql +71 -0
  19. package/drizzle/0046_variable_sets_rename.sql +56 -0
  20. package/drizzle/0047_rigs.sql +151 -0
  21. package/drizzle/0048_rig_runtime.sql +9 -0
  22. package/drizzle/0049_enrollment_went_offline.sql +28 -0
  23. package/drizzle/0050_enrollment_op_stream.sql +1 -0
  24. package/drizzle/0051_codex_pin_source.sql +48 -0
  25. package/drizzle/0052_file_upload_cleanup.sql +91 -0
  26. package/drizzle/0053_codex_credential_leases.sql +230 -0
  27. package/drizzle/0054_session_pins.sql +85 -0
  28. package/drizzle/0055_session_list_snapshots.sql +73 -0
  29. package/drizzle/0056_workspace_model_policies.sql +48 -0
  30. package/drizzle/0057_durable_queue_control.sql +536 -0
  31. package/drizzle/0058_turn_admission_usage_enrollment.sql +158 -0
  32. package/drizzle/0059_workspace_pause_control_kind.sql +12 -0
  33. package/drizzle/0060_session_system_update_deferral.sql +10 -0
  34. package/drizzle/0061_session_workflow_wake_outbox.sql +157 -0
  35. package/drizzle/0062_session_list_snapshot_reaper.sql +48 -0
  36. package/drizzle/0063_session_control_mega_foundation.sql +1324 -0
  37. package/package.json +13 -13
  38. package/src/codex-token-resolver.ts +58 -23
  39. package/src/connection-token-resolver.ts +146 -57
  40. package/src/environment-crypto.ts +5 -1
  41. package/src/event-payload-sanitizer.ts +29 -1
  42. package/src/index.ts +20990 -6465
  43. package/src/memory-domain.ts +218 -0
  44. package/src/migrate.ts +58 -3
  45. package/src/provision-roles.ts +46 -17
  46. package/src/schema.ts +2888 -1121
  47. package/src/session-control.ts +1759 -0
  48. package/src/session-queue-commands.ts +1753 -0
  49. package/src/session-tool-call-settlement.ts +269 -0
  50. package/dist/chunk-57MLICFR.js.map +0 -1
  51. package/dist/chunk-OGCE6O2X.js.map +0 -1
  52. package/dist/chunk-ZIUCA2IO.js +0 -1268
  53. package/dist/chunk-ZIUCA2IO.js.map +0 -1
@@ -0,0 +1,2634 @@
1
+ import {
2
+ __export
3
+ } from "./chunk-PZ5AY32C.js";
4
+
5
+ // src/schema.ts
6
+ var schema_exports = {};
7
+ __export(schema_exports, {
8
+ agentRunStates: () => agentRunStates,
9
+ apiKeys: () => apiKeys,
10
+ auditEvents: () => auditEvents,
11
+ billingCustomers: () => billingCustomers,
12
+ capabilityCatalogItems: () => capabilityCatalogItems,
13
+ capabilityInstallations: () => capabilityInstallations,
14
+ codexCapacityWaiters: () => codexCapacityWaiters,
15
+ codexCredentialLeases: () => codexCredentialLeases,
16
+ codexRotationSettings: () => codexRotationSettings,
17
+ codexSubscriptionCredentials: () => codexSubscriptionCredentials,
18
+ composerDrafts: () => composerDrafts,
19
+ connections: () => connections,
20
+ creditLedgerEntries: () => creditLedgerEntries,
21
+ deviceEnrollmentRequests: () => deviceEnrollmentRequests,
22
+ deviceEnrollmentStatusValues: () => deviceEnrollmentStatusValues,
23
+ documentBases: () => documentBases,
24
+ documentChunks: () => documentChunks,
25
+ documents: () => documents,
26
+ enrollmentExposureValues: () => enrollmentExposureValues,
27
+ enrollmentOsValues: () => enrollmentOsValues,
28
+ enrollmentStatusValues: () => enrollmentStatusValues,
29
+ enrollments: () => enrollments,
30
+ fileUploads: () => fileUploads,
31
+ files: () => files,
32
+ githubInstallations: () => githubInstallations,
33
+ importBatches: () => importBatches,
34
+ integrationOauthClients: () => integrationOauthClients,
35
+ integrationOauthStateNonces: () => integrationOauthStateNonces,
36
+ knowledgeMemories: () => knowledgeMemories,
37
+ machineMetricsLatest: () => machineMetricsLatest,
38
+ machineMetricsSeries: () => machineMetricsSeries,
39
+ managedAccounts: () => managedAccounts,
40
+ packInstallations: () => packInstallations,
41
+ rigChanges: () => rigChanges,
42
+ rigVersions: () => rigVersions,
43
+ rigs: () => rigs,
44
+ sandboxKindValues: () => sandboxKindValues,
45
+ sandboxLeaseHolders: () => sandboxLeaseHolders,
46
+ sandboxLeaseLivenessValues: () => sandboxLeaseLivenessValues,
47
+ sandboxLeases: () => sandboxLeases,
48
+ sandboxPtySessions: () => sandboxPtySessions,
49
+ sandboxSessionEnvelopes: () => sandboxSessionEnvelopes,
50
+ sandboxes: () => sandboxes,
51
+ scheduledTaskRuns: () => scheduledTaskRuns,
52
+ scheduledTasks: () => scheduledTasks,
53
+ sessionAttemptInterruptions: () => sessionAttemptInterruptions,
54
+ sessionCommandReceipts: () => sessionCommandReceipts,
55
+ sessionEvents: () => sessionEvents,
56
+ sessionGoals: () => sessionGoals,
57
+ sessionHistoryItems: () => sessionHistoryItems,
58
+ sessionListSnapshots: () => sessionListSnapshots,
59
+ sessionMcpServers: () => sessionMcpServers,
60
+ sessionPendingToolCalls: () => sessionPendingToolCalls,
61
+ sessionPins: () => sessionPins,
62
+ sessionRecordingCodecValues: () => sessionRecordingCodecValues,
63
+ sessionRecordingModeValues: () => sessionRecordingModeValues,
64
+ sessionRecordingStateValues: () => sessionRecordingStateValues,
65
+ sessionRecordings: () => sessionRecordings,
66
+ sessionSystemUpdateOutbox: () => sessionSystemUpdateOutbox,
67
+ sessionSystemUpdates: () => sessionSystemUpdates,
68
+ sessionTurnAttempts: () => sessionTurnAttempts,
69
+ sessionTurns: () => sessionTurns,
70
+ sessionWorkflowWakeOutbox: () => sessionWorkflowWakeOutbox,
71
+ sessions: () => sessions,
72
+ socialConnections: () => socialConnections,
73
+ socialPosts: () => socialPosts,
74
+ stripeWebhookEvents: () => stripeWebhookEvents,
75
+ usageEvents: () => usageEvents,
76
+ workspaceCaptures: () => workspaceCaptures,
77
+ workspaceControlEvents: () => workspaceControlEvents,
78
+ workspaceInferenceControls: () => workspaceInferenceControls,
79
+ workspaceMemberships: () => workspaceMemberships,
80
+ workspaceModelPolicies: () => workspaceModelPolicies,
81
+ workspacePacks: () => workspacePacks,
82
+ workspaceVariableSetVariables: () => workspaceVariableSetVariables,
83
+ workspaceVariableSets: () => workspaceVariableSets,
84
+ workspaces: () => workspaces
85
+ });
86
+ import { sql } from "drizzle-orm";
87
+ import {
88
+ bigint,
89
+ boolean,
90
+ check,
91
+ foreignKey,
92
+ index,
93
+ integer,
94
+ jsonb,
95
+ numeric,
96
+ pgTable,
97
+ text,
98
+ timestamp,
99
+ uniqueIndex,
100
+ uuid,
101
+ customType
102
+ } from "drizzle-orm/pg-core";
103
+ var vector = customType({
104
+ dataType() {
105
+ return "vector(3072)";
106
+ },
107
+ toDriver(value) {
108
+ return `[${value.join(",")}]`;
109
+ }
110
+ });
111
+ var managedAccounts = pgTable(
112
+ "managed_accounts",
113
+ {
114
+ id: uuid("id").primaryKey().defaultRandom(),
115
+ name: text("name").notNull(),
116
+ externalSource: text("external_source"),
117
+ externalId: text("external_id"),
118
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
119
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
120
+ },
121
+ (table) => ({
122
+ external: uniqueIndex("managed_accounts_external_idx").on(
123
+ table.externalSource,
124
+ table.externalId
125
+ )
126
+ })
127
+ );
128
+ var workspaces = pgTable(
129
+ "workspaces",
130
+ {
131
+ id: uuid("id").primaryKey().defaultRandom(),
132
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
133
+ name: text("name").notNull(),
134
+ slug: text("slug"),
135
+ externalSource: text("external_source"),
136
+ externalId: text("external_id"),
137
+ // White-label agent persona template override. NULL means the deployment
138
+ // default (OPENGENI_AGENT_INSTRUCTIONS_TEMPLATE / DEFAULT_AGENT_INSTRUCTIONS).
139
+ agentInstructions: text("agent_instructions"),
140
+ // Growth-ready per-workspace settings bag (migration 0045). Holds memoryEnabled
141
+ // and future workspace-level toggles; validated/merged via WorkspaceSettingsSchema.
142
+ settings: jsonb("settings").$type().notNull().default({}),
143
+ // The workspace's default rig (migration 0047). NULL ⇒ no default; sessions
144
+ // created without an explicit rig ride no rig (today's behavior exactly). FK
145
+ // (-> rigs(id) ON DELETE SET NULL) lives in migration 0047, not a Drizzle
146
+ // .references(), because `rigs` is declared later in this file (same
147
+ // forward-reference pattern as sessions.activeSandboxId). Consumed in M3.
148
+ defaultRigId: uuid("default_rig_id"),
149
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
150
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
151
+ },
152
+ (table) => ({
153
+ account: index("workspaces_account_idx").on(table.accountId),
154
+ accountSlug: uniqueIndex("workspaces_account_slug_idx").on(table.accountId, table.slug).where(sql`${table.slug} is not null`),
155
+ external: uniqueIndex("workspaces_external_idx").on(table.externalSource, table.externalId)
156
+ })
157
+ );
158
+ var workspaceInferenceControls = pgTable(
159
+ "workspace_inference_controls",
160
+ {
161
+ workspaceId: uuid("workspace_id").primaryKey(),
162
+ accountId: uuid("account_id").notNull(),
163
+ revision: bigint("revision", { mode: "number" }).notNull().default(0),
164
+ workspaceState: text("workspace_state").notNull().default("active"),
165
+ workspacePauseRevision: bigint("workspace_pause_revision", { mode: "number" }),
166
+ reason: text("reason"),
167
+ changedBy: text("changed_by"),
168
+ changedAt: timestamp("changed_at", { withTimezone: true }),
169
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
170
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
171
+ },
172
+ (table) => ({
173
+ workspaceAccount: foreignKey({
174
+ name: "workspace_inference_controls_workspace_account_fk",
175
+ columns: [table.workspaceId, table.accountId],
176
+ foreignColumns: [workspaces.id, workspaces.accountId]
177
+ }).onDelete("cascade"),
178
+ workspaceAccountIdentity: uniqueIndex("workspace_inference_controls_workspace_account_uq").on(
179
+ table.workspaceId,
180
+ table.accountId
181
+ ),
182
+ stateValid: check(
183
+ "workspace_inference_controls_state_check",
184
+ sql`${table.workspaceState} in ('active', 'paused')`
185
+ ),
186
+ pauseRevisionConsistent: check(
187
+ "workspace_inference_controls_pause_revision_check",
188
+ sql`(${table.workspaceState} = 'active' and ${table.workspacePauseRevision} is null)
189
+ or (${table.workspaceState} = 'paused' and ${table.workspacePauseRevision} is not null)`
190
+ ),
191
+ revisionValid: check(
192
+ "workspace_inference_controls_revision_check",
193
+ sql`${table.revision} >= 0 and (${table.workspacePauseRevision} is null or ${table.workspacePauseRevision} <= ${table.revision})`
194
+ )
195
+ })
196
+ );
197
+ var workspaceMemberships = pgTable(
198
+ "workspace_memberships",
199
+ {
200
+ id: uuid("id").primaryKey().defaultRandom(),
201
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
202
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
203
+ subjectId: text("subject_id").notNull(),
204
+ subjectLabel: text("subject_label"),
205
+ role: text("role").notNull().default("member"),
206
+ permissions: jsonb("permissions").$type().notNull().default([]),
207
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
208
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
209
+ },
210
+ (table) => ({
211
+ subjectWorkspace: uniqueIndex("workspace_memberships_subject_workspace_idx").on(
212
+ table.subjectId,
213
+ table.workspaceId
214
+ ),
215
+ subject: index("workspace_memberships_subject_idx").on(table.subjectId),
216
+ account: index("workspace_memberships_account_idx").on(table.accountId)
217
+ })
218
+ );
219
+ var apiKeys = pgTable(
220
+ "api_keys",
221
+ {
222
+ id: uuid("id").primaryKey().defaultRandom(),
223
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
224
+ workspaceId: uuid("workspace_id").references(() => workspaces.id, { onDelete: "cascade" }),
225
+ name: text("name").notNull(),
226
+ prefix: text("prefix").notNull(),
227
+ keyHash: text("key_hash").notNull(),
228
+ permissions: jsonb("permissions").$type().notNull().default([]),
229
+ expiresAt: timestamp("expires_at", { withTimezone: true }),
230
+ revokedAt: timestamp("revoked_at", { withTimezone: true }),
231
+ lastUsedAt: timestamp("last_used_at", { withTimezone: true }),
232
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
233
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
234
+ },
235
+ (table) => ({
236
+ prefix: index("api_keys_prefix_idx").on(table.prefix),
237
+ hash: uniqueIndex("api_keys_key_hash_idx").on(table.keyHash),
238
+ account: index("api_keys_account_idx").on(table.accountId),
239
+ workspace: index("api_keys_workspace_idx").on(table.workspaceId)
240
+ })
241
+ );
242
+ var workspaceVariableSets = pgTable(
243
+ "workspace_variable_sets",
244
+ {
245
+ id: uuid("id").primaryKey().defaultRandom(),
246
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
247
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
248
+ name: text("name").notNull(),
249
+ description: text("description"),
250
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
251
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
252
+ },
253
+ (table) => ({
254
+ workspaceName: uniqueIndex("workspace_variable_sets_workspace_name_idx").on(
255
+ table.workspaceId,
256
+ table.name
257
+ ),
258
+ workspaceCreated: index("workspace_variable_sets_workspace_created_idx").on(
259
+ table.workspaceId,
260
+ table.createdAt
261
+ )
262
+ })
263
+ );
264
+ var workspaceVariableSetVariables = pgTable(
265
+ "workspace_variable_set_variables",
266
+ {
267
+ id: uuid("id").primaryKey().defaultRandom(),
268
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
269
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
270
+ variableSetId: uuid("variable_set_id").notNull().references(() => workspaceVariableSets.id, { onDelete: "cascade" }),
271
+ name: text("name").notNull(),
272
+ // Format: v1:<base64 iv>:<base64 ciphertext||gcm-tag>. Never returned by any API.
273
+ valueEncrypted: text("value_encrypted").notNull(),
274
+ version: integer("version").notNull().default(1),
275
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
276
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
277
+ },
278
+ (table) => ({
279
+ variableSetName: uniqueIndex("workspace_variable_set_variables_env_name_idx").on(
280
+ table.workspaceId,
281
+ table.variableSetId,
282
+ table.name
283
+ ),
284
+ variableSet: index("workspace_variable_set_variables_workspace_env_idx").on(
285
+ table.workspaceId,
286
+ table.variableSetId
287
+ )
288
+ })
289
+ );
290
+ var codexSubscriptionCredentials = pgTable(
291
+ "codex_subscription_credentials",
292
+ {
293
+ id: uuid("id").primaryKey().defaultRandom(),
294
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
295
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
296
+ // Format: v1:<base64 iv>:<base64 ciphertext||gcm-tag>. JSON {access_token, refresh_token, id_token}. Never returned by any API.
297
+ credentialEncrypted: text("credential_encrypted").notNull(),
298
+ chatgptAccountId: text("chatgpt_account_id"),
299
+ // plaintext ChatGPT-Account-ID header value (non-secret)
300
+ scopes: text("scopes"),
301
+ // space-delimited, as granted
302
+ planType: text("plan_type"),
303
+ isFedramp: boolean("is_fedramp").notNull().default(false),
304
+ expiresAt: timestamp("expires_at", { withTimezone: true }),
305
+ // derived from access-token JWT exp
306
+ lastRefreshAt: timestamp("last_refresh_at", { withTimezone: true }),
307
+ status: text("status").notNull().default("active"),
308
+ // active | needs_relogin | error
309
+ lastError: text("last_error"),
310
+ version: integer("version").notNull().default(1),
311
+ label: text("label"),
312
+ // user-chosen nickname; null ⇒ derive from email/plan/account
313
+ accountEmail: text("account_email"),
314
+ // email from the id_token (user's own email; non-secret)
315
+ // P2 usage cache (plaintext metadata; NEVER a token). Snapshotted from
316
+ // GET /wham/usage; drives the quota bars + the cache TTL. primary = 5h window
317
+ // (limit_window_seconds 18000), secondary = weekly (604800).
318
+ primaryUsedPercent: integer("primary_used_percent"),
319
+ primaryResetAt: timestamp("primary_reset_at", { withTimezone: true }),
320
+ secondaryUsedPercent: integer("secondary_used_percent"),
321
+ secondaryResetAt: timestamp("secondary_reset_at", { withTimezone: true }),
322
+ usageCheckedAt: timestamp("usage_checked_at", { withTimezone: true }),
323
+ // snapshot freshness → cache TTL clock
324
+ // P3 rotation cooldown (plaintext metadata; NEVER a token). Set when this account hit its
325
+ // usage cap on a rotation turn; the rotation engine treats `exhausted_until > now()` as
326
+ // capped/skip so it isn't immediately re-picked. Self-clears via the now() comparison.
327
+ exhaustedUntil: timestamp("exhausted_until", { withTimezone: true }),
328
+ // P4 connector-aware rotation cache (plaintext metadata; NEVER a token). The set
329
+ // of ORIGINAL-dotted connector namespaces (github/gmail/linear/…) this account
330
+ // exposes via codex_apps, captured from the per-turn tools/list. null ⇒ never
331
+ // probed (the ranker treats it as unknown: never credited as covering, never
332
+ // excluded). The writer only ever sets a NON-empty set, so a flaky empty turn
333
+ // can't false-drop coverage. connectorsCheckedAt is the freshness clock.
334
+ connectorNamespaces: text("connector_namespaces").array(),
335
+ connectorsCheckedAt: timestamp("connectors_checked_at", { withTimezone: true }),
336
+ // Workspace-local, server-held fairness cursor. Provider usage headers are
337
+ // capacity hints, never the sole allocator: live lease count is ranked first
338
+ // and this cursor deterministically breaks equal-load/equal-capacity ties.
339
+ // This flag controls NEW automatic allocations only. Credential health,
340
+ // refresh, encrypted material, and already-frozen/in-flight turns are
341
+ // intentionally independent. OPE-24 owns toggle OCC/audit and product UI.
342
+ allocatorEnabled: boolean("allocator_enabled").notNull().default(true),
343
+ selectionCount: integer("selection_count").notNull().default(0),
344
+ lastSelectedAt: timestamp("last_selected_at", { withTimezone: true }),
345
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
346
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
347
+ },
348
+ (table) => ({
349
+ // REPLACES codex_subscription_credentials_workspace_idx (the one-per-workspace cap).
350
+ // One row per (workspace, ChatGPT account). Partial WHERE chatgpt_account_id IS NOT NULL
351
+ // so degenerate null-account rows can't collide; the device-grant connect path always
352
+ // populates chatgpt_account_id.
353
+ wsAccount: uniqueIndex("codex_subscription_credentials_ws_account_idx").on(table.workspaceId, table.chatgptAccountId).where(sql`${table.chatgptAccountId} is not null`),
354
+ workspace: index("codex_subscription_credentials_workspace_lookup_idx").on(table.workspaceId),
355
+ // Composite identity is the defense-in-depth FK target for workspace-local
356
+ // lease references in migration 0053.
357
+ workspaceIdentity: uniqueIndex("codex_subscription_credentials_workspace_id_idx").on(
358
+ table.workspaceId,
359
+ table.id
360
+ )
361
+ })
362
+ );
363
+ var connections = pgTable(
364
+ "connections",
365
+ {
366
+ id: uuid("id").primaryKey().defaultRandom(),
367
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
368
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
369
+ subjectId: text("subject_id"),
370
+ providerDomain: text("provider_domain").notNull(),
371
+ kind: text("kind").notNull(),
372
+ status: text("status").notNull().default("active"),
373
+ credentialEncrypted: text("credential_encrypted").notNull(),
374
+ grantedScopes: jsonb("granted_scopes").$type().notNull().default([]),
375
+ expiresAt: timestamp("expires_at", { withTimezone: true }),
376
+ lastRefreshAt: timestamp("last_refresh_at", { withTimezone: true }),
377
+ lastUsedAt: timestamp("last_used_at", { withTimezone: true }),
378
+ lastError: text("last_error"),
379
+ version: integer("version").notNull().default(1),
380
+ metadata: jsonb("metadata").$type().notNull().default({}),
381
+ createdBySubjectId: text("created_by_subject_id"),
382
+ updatedBySubjectId: text("updated_by_subject_id"),
383
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
384
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
385
+ },
386
+ (table) => ({
387
+ workspaceProviderStatus: index("connections_workspace_provider_status_idx").on(
388
+ table.workspaceId,
389
+ table.providerDomain,
390
+ table.status
391
+ ),
392
+ workspaceSubjectProvider: index("connections_workspace_subject_provider_idx").on(
393
+ table.workspaceId,
394
+ table.subjectId,
395
+ table.providerDomain
396
+ ),
397
+ workspaceKind: index("connections_workspace_kind_idx").on(table.workspaceId, table.kind),
398
+ workspaceExpires: index("connections_workspace_expires_idx").on(
399
+ table.workspaceId,
400
+ table.expiresAt
401
+ )
402
+ })
403
+ );
404
+ var integrationOauthClients = pgTable(
405
+ "integration_oauth_clients",
406
+ {
407
+ id: uuid("id").primaryKey().defaultRandom(),
408
+ issuer: text("issuer").notNull(),
409
+ authorizationServer: text("authorization_server").notNull(),
410
+ clientId: text("client_id").notNull(),
411
+ clientSecretEncrypted: text("client_secret_encrypted"),
412
+ tokenEndpointAuthMethod: text("token_endpoint_auth_method").notNull().default("none"),
413
+ metadata: jsonb("metadata").$type().notNull().default({}),
414
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
415
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
416
+ },
417
+ (table) => ({
418
+ issuer: uniqueIndex("integration_oauth_clients_issuer_idx").on(table.issuer),
419
+ authorizationServer: index("integration_oauth_clients_as_idx").on(table.authorizationServer)
420
+ })
421
+ );
422
+ var integrationOauthStateNonces = pgTable(
423
+ "integration_oauth_state_nonces",
424
+ {
425
+ nonce: text("nonce").primaryKey(),
426
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
427
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
428
+ subjectId: text("subject_id").notNull(),
429
+ expiresAt: timestamp("expires_at", { withTimezone: true }).notNull(),
430
+ usedAt: timestamp("used_at", { withTimezone: true }).notNull().defaultNow(),
431
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow()
432
+ },
433
+ (table) => ({
434
+ workspace: index("integration_oauth_state_nonces_workspace_idx").on(table.workspaceId),
435
+ expires: index("integration_oauth_state_nonces_expires_idx").on(table.expiresAt)
436
+ })
437
+ );
438
+ var codexRotationSettings = pgTable(
439
+ "codex_rotation_settings",
440
+ {
441
+ id: uuid("id").primaryKey().defaultRandom(),
442
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
443
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
444
+ activeCredentialId: uuid("active_credential_id"),
445
+ // Legacy selector bit. Keep false as the DB default forever: an old worker
446
+ // only understands this column, so a schema-first rollout or binary
447
+ // rollback must never make it enter the non-atomic rotation path.
448
+ rotationEnabled: boolean("rotation_enabled").notNull().default(false),
449
+ // Revision-aware allocator cutover. Only migration-compatible API/worker
450
+ // code reads this bit; old binaries safely ignore it and keep the legacy
451
+ // pin/rotation policy.
452
+ leaseRotationEnabled: boolean("lease_rotation_enabled").notNull().default(false),
453
+ rotationStrategy: text("rotation_strategy").notNull().default("most_remaining"),
454
+ // P3, inert
455
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
456
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
457
+ },
458
+ (table) => ({
459
+ workspace: uniqueIndex("codex_rotation_settings_workspace_idx").on(table.workspaceId)
460
+ })
461
+ );
462
+ var workspaceModelPolicies = pgTable(
463
+ "workspace_model_policies",
464
+ {
465
+ id: uuid("id").primaryKey().defaultRandom(),
466
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
467
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
468
+ allowedProviders: text("allowed_providers").array(),
469
+ allowedModels: text("allowed_models").array(),
470
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
471
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
472
+ },
473
+ (table) => ({
474
+ workspace: uniqueIndex("workspace_model_policies_workspace_idx").on(table.workspaceId)
475
+ })
476
+ );
477
+ var codexCredentialLeases = pgTable(
478
+ "codex_credential_leases",
479
+ {
480
+ id: uuid("id").primaryKey().defaultRandom(),
481
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
482
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
483
+ credentialId: uuid("credential_id").notNull(),
484
+ turnId: uuid("turn_id").notNull(),
485
+ // Temporal activity execution fence. A successor dispatch for the same
486
+ // durable turn replaces holderId and increments generation atomically;
487
+ // stale/zombie heartbeats and releases must match both values.
488
+ holderId: text("holder_id").notNull(),
489
+ generation: integer("generation").notNull().default(1),
490
+ leasedUntil: timestamp("leased_until", { withTimezone: true }).notNull(),
491
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
492
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
493
+ },
494
+ (table) => ({
495
+ turn: uniqueIndex("codex_credential_leases_workspace_turn_idx").on(
496
+ table.workspaceId,
497
+ table.turnId
498
+ ),
499
+ activeCredential: index("codex_credential_leases_active_credential_idx").on(
500
+ table.workspaceId,
501
+ table.credentialId,
502
+ table.leasedUntil
503
+ ),
504
+ expiry: index("codex_credential_leases_expiry_idx").on(table.leasedUntil)
505
+ })
506
+ );
507
+ var sessions = pgTable(
508
+ "sessions",
509
+ {
510
+ id: uuid("id").primaryKey().defaultRandom(),
511
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
512
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
513
+ status: text("status").notNull().default("queued"),
514
+ initialMessage: text("initial_message").notNull(),
515
+ title: text("title"),
516
+ titleSource: text("title_source"),
517
+ // Per-session agent persona/system instructions supplied at create (the
518
+ // per-agent-type prompt lever for embedding hosts). NULL ⇒ the session
519
+ // carried none, so the composed agent instructions are byte-identical to a
520
+ // workspace-only persona (no backfill, no behavior change for existing rows).
521
+ // Composed system-level AFTER the workspace agentInstructions; never emitted
522
+ // as a timeline event.
523
+ instructions: text("instructions"),
524
+ resources: jsonb("resources").$type().notNull().default([]),
525
+ tools: jsonb("tools").$type().notNull().default([]),
526
+ metadata: jsonb("metadata").$type().notNull().default({}),
527
+ model: text("model").notNull(),
528
+ sandboxBackend: text("sandbox_backend").notNull(),
529
+ // The OS this session's box runs. Defaults to 'linux' (today's only OS, so
530
+ // every existing + new row is a behavior-preserving no-op). CHECK-constrained
531
+ // to the SandboxOs enum (linux|macos|windows) in migration 0018.
532
+ sandboxOs: text("sandbox_os").notNull().default("linux"),
533
+ // The shared-sandbox group this session's box belongs to. Defaults to the
534
+ // session's OWN id (a singleton group: group === session — today's 1:1
535
+ // behavior). When spawned shared via session_create, set to the PARENT's
536
+ // sandboxGroupId so both run in ONE box. Immutable once set. NOT an FK (the
537
+ // value is this row's id or an ancestor session's id in the same workspace;
538
+ // the live lease row, not a sandbox_groups table, materializes the group).
539
+ // The app generates the uuid and uses it for both id and sandbox_group_id in
540
+ // one insert — it cannot SQL-default to id (id is defaultRandom()).
541
+ sandboxGroupId: uuid("sandbox_group_id").notNull(),
542
+ // The first-class swappable-sandbox POINTER (bring-your-own-compute M2,
543
+ // dossier §10.3). NULL == "use the session's own group sandbox" (the
544
+ // backward-compat default — every existing/new row is a behavior-preserving
545
+ // no-op). The routing proxy re-reads (active_sandbox_id, active_epoch) PER
546
+ // TOOL CALL to make a Modal<->selfhosted hot-swap seamless. The FK
547
+ // (-> sandboxes(id) ON DELETE SET NULL — a deleted sandbox degrades the
548
+ // pointer to the group default, never dangles) lives in migration 0024, NOT a
549
+ // Drizzle .references() — exactly like parentSessionId below, so the const
550
+ // ordering imposes no forward-reference.
551
+ activeSandboxId: uuid("active_sandbox_id"),
552
+ // The SECOND epoch ABOVE sandbox_leases.lease_epoch, bumped on every swap; an
553
+ // in-flight op fenced by a stale active_epoch retries against the new active
554
+ // sandbox. integer (NOT bigint) — the lease-epoch spike: int8 reads back as a
555
+ // JS string and breaks the strict fence; int4 returns a number.
556
+ activeEpoch: integer("active_epoch").notNull().default(0),
557
+ // The session's WORKING DIRECTORY — the path/cwd base the (selfhosted) box's
558
+ // agent/terminal/file-dock operate under. A launch-workspace_root-relative
559
+ // subdir or an absolute machine path; surfaced alongside the active-sandbox
560
+ // pointer (readActiveSandbox) and written through the epoch-fenced
561
+ // setActiveSandbox CAS, NOT the row INSERT. NULL (the default) ⇒ today's
562
+ // behavior exactly — the agent substitutes its workspace_root for an empty cwd,
563
+ // so an unset working_dir is a byte-identical no-op. Create-time only (Stage A).
564
+ workingDir: text("working_dir"),
565
+ variableSetId: uuid("variable_set_id").references(() => workspaceVariableSets.id, {
566
+ onDelete: "set null"
567
+ }),
568
+ // The rig this session rides + the exact rig version frozen at create time
569
+ // (migration 0047). NULL ⇒ the session rides no rig (today's behavior). FKs
570
+ // (-> rigs(id)/rig_versions(id) ON DELETE SET NULL) live in migration 0047,
571
+ // not Drizzle .references(), because those tables are declared later in this
572
+ // file (forward-reference pattern, same as activeSandboxId). Consumed in M3.
573
+ rigId: uuid("rig_id"),
574
+ rigVersionId: uuid("rig_version_id"),
575
+ // Non-default first-party MCP token permissions (manager-style sessions);
576
+ // null means the fixed worker default set in @opengeni/runtime.
577
+ firstPartyMcpPermissions: jsonb("first_party_mcp_permissions").$type(),
578
+ // The manager session that spawned this one via session_create. Set only
579
+ // when the creating grant carried a worker-signed sessionId claim (a session
580
+ // spawning a worker); null for direct API creates and scheduled-task runs.
581
+ // When set, this worker's terminal-for-now transitions wake the parent so a
582
+ // manager can orchestrate workers without busy-polling. Self-referencing FK,
583
+ // ON DELETE SET NULL so deleting a manager never cascades into its workers.
584
+ parentSessionId: uuid("parent_session_id"),
585
+ // Workspace-scoped CREATE idempotency key. NULL means the create carried no
586
+ // key (each such create is independent). When set, the partial unique index
587
+ // below collapses concurrent/retried creates with the same key in the same
588
+ // workspace to a single session row — the dedup that closes the
589
+ // double-submit/double-dispatch stuck-queued bug.
590
+ createIdempotencyKey: text("create_idempotency_key"),
591
+ temporalWorkflowId: text("temporal_workflow_id"),
592
+ activeTurnId: uuid("active_turn_id"),
593
+ // Actual input tokens reported for the last model call of the most recent
594
+ // turn. The pre-turn portable compaction trigger reads this as its budget
595
+ // signal (char/4 estimate is the same-turn fallback). Null until a turn with
596
+ // usage has completed.
597
+ lastInputTokens: integer("last_input_tokens"),
598
+ // Operator /compact request flag. The API sets
599
+ // it true; the worker honors it BEFORE the next turn's model call by forcing
600
+ // a compaction, then clears it. A durable flag (not a transient signal) so
601
+ // the trigger survives a worker restart and converges before the next turn.
602
+ compactRequested: boolean("compact_requested").notNull().default(false),
603
+ queueVersion: integer("queue_version").notNull().default(0),
604
+ queueHeadPosition: bigint("queue_head_position", { mode: "number" }).notNull().default(0),
605
+ queueTailPosition: bigint("queue_tail_position", { mode: "number" }).notNull().default(0),
606
+ directControlState: text("direct_control_state").notNull().default("active"),
607
+ directPauseRevision: bigint("direct_pause_revision", { mode: "number" }),
608
+ subtreeRunOverrideRevision: bigint("subtree_run_override_revision", { mode: "number" }),
609
+ controlVersion: bigint("control_version", { mode: "number" }).notNull().default(0),
610
+ directControlReason: text("direct_control_reason"),
611
+ directControlChangedBy: text("direct_control_changed_by"),
612
+ directControlChangedAt: timestamp("direct_control_changed_at", { withTimezone: true }),
613
+ lastSequence: integer("last_sequence").notNull().default(0),
614
+ // The session's PINNED Codex account (manual override from the in-session
615
+ // switcher). NULL ⇒ follow the workspace active pointer. FK declared in the
616
+ // migration with ON DELETE SET NULL (a disconnected pin degrades to "follow
617
+ // active", never dangles), same pattern as activeSandboxId.
618
+ codexPinnedCredentialId: uuid("codex_pinned_credential_id"),
619
+ // The Codex account the session's most recent turn ACTUALLY ran on — drives
620
+ // the "Running on:" indicator. Written by the worker at the turn boundary. FK
621
+ // ON DELETE SET NULL (migration).
622
+ codexLastCredentialId: uuid("codex_last_credential_id"),
623
+ // The SOURCE of codex_pinned_credential_id (AM-2): 'manual' — the user's
624
+ // in-session account switcher, which is SACRED and never moved by any policy —
625
+ // or 'policy' — the sharded rotation strategy's deterministic per-session home
626
+ // assignment, which MAY be re-sharded to another account when its own account
627
+ // caps. NULL when there is no pin (and for every pre-existing row). CHECK
628
+ // (manual|policy) lives in the migration; no FK (it describes the pin, not an
629
+ // account).
630
+ codexPinSource: text("codex_pin_source"),
631
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
632
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
633
+ },
634
+ (table) => ({
635
+ workspaceIdentity: uniqueIndex("sessions_workspace_id_idx").on(table.workspaceId, table.id),
636
+ workspaceCreated: index("sessions_workspace_created_idx").on(
637
+ table.workspaceId,
638
+ table.createdAt
639
+ ),
640
+ variableSet: index("sessions_variable_set_idx").on(table.workspaceId, table.variableSetId),
641
+ parent: index("sessions_parent_idx").on(table.workspaceId, table.parentSessionId),
642
+ // Routing index: resolve session_id -> sandbox_group_id at every lease entry
643
+ // point and enumerate all sessions in a group for attribution/disclosure.
644
+ sandboxGroup: index("sessions_sandbox_group_idx").on(table.workspaceId, table.sandboxGroupId),
645
+ // Partial unique index: one session per (workspace, create_idempotency_key)
646
+ // when a key is present. Concurrent creates racing on the same key see a
647
+ // unique violation on all but one; the domain layer catches it and returns
648
+ // the winning row instead of erroring.
649
+ createIdempotency: uniqueIndex("sessions_workspace_create_idempotency_idx").on(table.workspaceId, table.createIdempotencyKey).where(sql`${table.createIdempotencyKey} is not null`)
650
+ })
651
+ );
652
+ var sessionPins = pgTable(
653
+ "session_pins",
654
+ {
655
+ id: uuid("id").primaryKey().defaultRandom(),
656
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
657
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
658
+ subjectId: text("subject_id").notNull(),
659
+ sessionId: uuid("session_id").notNull().references(() => sessions.id, { onDelete: "cascade" }),
660
+ // Keep an unpinned tombstone (pinned=false, pinned_at=null) rather than
661
+ // deleting it. That preserves a monotonic version and prevents an ABA race:
662
+ // a stale client that saw pin version 1 cannot silently overwrite a later
663
+ // unpin+re-pin that would otherwise recreate version 1.
664
+ pinned: boolean("pinned").notNull().default(true),
665
+ pinnedAt: timestamp("pinned_at", { withTimezone: true }).defaultNow(),
666
+ version: integer("version").notNull().default(1)
667
+ },
668
+ (table) => ({
669
+ subjectNonempty: check(
670
+ "session_pins_subject_nonempty",
671
+ sql`length(btrim(${table.subjectId})) > 0`
672
+ ),
673
+ versionPositive: check("session_pins_version_positive", sql`${table.version} >= 1`),
674
+ stateConsistent: check(
675
+ "session_pins_state_consistent",
676
+ sql`((${table.pinned}) and (${table.pinnedAt}) is not null) or ((not ${table.pinned}) and (${table.pinnedAt}) is null)`
677
+ ),
678
+ workspaceAccount: foreignKey({
679
+ name: "session_pins_workspace_account_fk",
680
+ columns: [table.workspaceId, table.accountId],
681
+ foreignColumns: [workspaces.id, workspaces.accountId]
682
+ }).onDelete("cascade"),
683
+ workspaceSession: foreignKey({
684
+ name: "session_pins_workspace_session_fk",
685
+ columns: [table.workspaceId, table.sessionId],
686
+ foreignColumns: [sessions.workspaceId, sessions.id]
687
+ }).onDelete("cascade"),
688
+ subjectSession: uniqueIndex("session_pins_subject_workspace_session_idx").on(
689
+ table.subjectId,
690
+ table.workspaceId,
691
+ table.sessionId
692
+ ),
693
+ subjectPinned: index("session_pins_workspace_subject_pinned_idx").on(
694
+ table.workspaceId,
695
+ table.subjectId,
696
+ table.pinned,
697
+ table.pinnedAt.desc(),
698
+ table.sessionId.desc()
699
+ )
700
+ })
701
+ );
702
+ var sessionListSnapshots = pgTable(
703
+ "session_list_snapshots",
704
+ {
705
+ id: uuid("id").primaryKey().defaultRandom(),
706
+ accountId: uuid("account_id").notNull(),
707
+ workspaceId: uuid("workspace_id").notNull(),
708
+ subjectId: text("subject_id").notNull(),
709
+ parentSessionFilter: text("parent_session_filter").notNull().default("all"),
710
+ search: text("search"),
711
+ ordinarySessionIds: uuid("ordinary_session_ids").array().notNull().default(sql`'{}'::uuid[]`),
712
+ expiresAt: timestamp("expires_at", { withTimezone: true }).notNull(),
713
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow()
714
+ },
715
+ (table) => ({
716
+ workspaceAccount: foreignKey({
717
+ name: "session_list_snapshots_workspace_account_fk",
718
+ columns: [table.workspaceId, table.accountId],
719
+ foreignColumns: [workspaces.id, workspaces.accountId]
720
+ }).onDelete("cascade"),
721
+ subjectNonempty: check(
722
+ "session_list_snapshots_subject_nonempty",
723
+ sql`length(btrim(${table.subjectId})) > 0`
724
+ ),
725
+ parentFilterValid: check(
726
+ "session_list_snapshots_parent_filter_valid",
727
+ sql`${table.parentSessionFilter} = 'all' or ${table.parentSessionFilter} = 'null' or ${table.parentSessionFilter} ~ '^[0-9a-fA-F-]{36}$'`
728
+ ),
729
+ searchLength: check(
730
+ "session_list_snapshots_search_length",
731
+ sql`${table.search} is null or length(${table.search}) <= 200`
732
+ ),
733
+ workspaceExpiry: index("session_list_snapshots_workspace_expiry_idx").on(
734
+ table.workspaceId,
735
+ table.subjectId,
736
+ table.expiresAt
737
+ ),
738
+ expiryReaper: index("session_list_snapshots_expiry_reaper_idx").on(table.expiresAt, table.id)
739
+ })
740
+ );
741
+ var sessionMcpServers = pgTable(
742
+ "session_mcp_servers",
743
+ {
744
+ id: uuid("id").primaryKey().defaultRandom(),
745
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
746
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
747
+ sessionId: uuid("session_id").notNull().references(() => sessions.id, { onDelete: "cascade" }),
748
+ serverId: text("server_id").notNull(),
749
+ name: text("name"),
750
+ url: text("url").notNull(),
751
+ allowedTools: jsonb("allowed_tools").$type(),
752
+ timeoutMs: integer("timeout_ms"),
753
+ cacheToolsList: boolean("cache_tools_list").notNull().default(false),
754
+ // Human-approval policy: `true` = every tool requires approval, a string[] of
755
+ // UNPREFIXED tool names = only those require it, null/absent = auto-run.
756
+ requireApproval: jsonb("require_approval").$type(),
757
+ // Map of header name -> AES-GCM ciphertext. Values are decrypted only by the
758
+ // worker's run-preparation path and never returned by API helpers.
759
+ headersEncrypted: jsonb("headers_encrypted").$type().notNull().default({}),
760
+ credentialVersion: integer("credential_version").notNull().default(1),
761
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
762
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
763
+ },
764
+ (table) => ({
765
+ sessionServer: uniqueIndex("session_mcp_servers_session_server_idx").on(
766
+ table.workspaceId,
767
+ table.sessionId,
768
+ table.serverId
769
+ ),
770
+ session: index("session_mcp_servers_session_idx").on(table.workspaceId, table.sessionId)
771
+ })
772
+ );
773
+ var files = pgTable(
774
+ "files",
775
+ {
776
+ id: uuid("id").primaryKey().defaultRandom(),
777
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
778
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
779
+ status: text("status").notNull().default("pending_upload"),
780
+ filename: text("filename").notNull(),
781
+ safeFilename: text("safe_filename").notNull(),
782
+ contentType: text("content_type").notNull(),
783
+ sizeBytes: bigint("size_bytes", { mode: "number" }).notNull(),
784
+ sha256: text("sha256"),
785
+ bucket: text("bucket").notNull(),
786
+ objectKey: text("object_key").notNull(),
787
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
788
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
789
+ },
790
+ (table) => ({
791
+ workspaceCreated: index("files_workspace_created_idx").on(table.workspaceId, table.createdAt),
792
+ objectKey: uniqueIndex("files_object_key_idx").on(table.objectKey),
793
+ status: index("files_status_idx").on(table.status)
794
+ })
795
+ );
796
+ var fileUploads = pgTable(
797
+ "file_uploads",
798
+ {
799
+ id: uuid("id").primaryKey().defaultRandom(),
800
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
801
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
802
+ fileId: uuid("file_id").notNull().references(() => files.id, { onDelete: "cascade" }),
803
+ status: text("status").notNull().default("pending"),
804
+ expiresAt: timestamp("expires_at", { withTimezone: true }).notNull(),
805
+ completedAt: timestamp("completed_at", { withTimezone: true }),
806
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
807
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
808
+ },
809
+ (table) => ({
810
+ workspace: index("file_uploads_workspace_idx").on(table.workspaceId),
811
+ fileId: index("file_uploads_file_id_idx").on(table.fileId),
812
+ status: index("file_uploads_status_idx").on(table.status)
813
+ })
814
+ );
815
+ var documentBases = pgTable(
816
+ "document_bases",
817
+ {
818
+ id: uuid("id").primaryKey().defaultRandom(),
819
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
820
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
821
+ name: text("name").notNull(),
822
+ description: text("description"),
823
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
824
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
825
+ },
826
+ (table) => ({
827
+ workspaceCreated: index("document_bases_workspace_created_idx").on(
828
+ table.workspaceId,
829
+ table.createdAt
830
+ )
831
+ })
832
+ );
833
+ var documents = pgTable(
834
+ "documents",
835
+ {
836
+ id: uuid("id").primaryKey().defaultRandom(),
837
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
838
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
839
+ baseId: uuid("base_id").notNull().references(() => documentBases.id, { onDelete: "cascade" }),
840
+ fileId: uuid("file_id").notNull().references(() => files.id, { onDelete: "restrict" }),
841
+ status: text("status").notNull().default("queued"),
842
+ title: text("title").notNull(),
843
+ parser: text("parser").notNull().default("liteparse"),
844
+ chunkCount: integer("chunk_count").notNull().default(0),
845
+ error: text("error"),
846
+ sourceKind: text("source_kind").notNull().default("manual_upload"),
847
+ sourceUri: text("source_uri"),
848
+ sourceExternalId: text("source_external_id"),
849
+ sourceTitle: text("source_title"),
850
+ sourceAuthor: text("source_author"),
851
+ sourceCreatedAt: timestamp("source_created_at", { withTimezone: true }),
852
+ sourceUpdatedAt: timestamp("source_updated_at", { withTimezone: true }),
853
+ sourceVersion: text("source_version"),
854
+ aclTags: jsonb("acl_tags").$type().notNull().default([]),
855
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
856
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
857
+ },
858
+ (table) => ({
859
+ baseFile: uniqueIndex("documents_workspace_base_file_idx").on(
860
+ table.workspaceId,
861
+ table.baseId,
862
+ table.fileId
863
+ ),
864
+ baseStatus: index("documents_workspace_base_status_idx").on(
865
+ table.workspaceId,
866
+ table.baseId,
867
+ table.status
868
+ ),
869
+ sourceKind: index("documents_workspace_source_kind_idx").on(
870
+ table.workspaceId,
871
+ table.sourceKind
872
+ ),
873
+ sourceExternalId: index("documents_workspace_source_external_id_idx").on(
874
+ table.workspaceId,
875
+ table.sourceExternalId
876
+ )
877
+ })
878
+ );
879
+ var documentChunks = pgTable(
880
+ "document_chunks",
881
+ {
882
+ id: uuid("id").primaryKey().defaultRandom(),
883
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
884
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
885
+ documentId: uuid("document_id").notNull().references(() => documents.id, { onDelete: "cascade" }),
886
+ baseId: uuid("base_id").notNull().references(() => documentBases.id, { onDelete: "cascade" }),
887
+ fileId: uuid("file_id").notNull().references(() => files.id, { onDelete: "restrict" }),
888
+ chunkIndex: integer("chunk_index").notNull(),
889
+ text: text("text").notNull(),
890
+ metadata: jsonb("metadata").$type().notNull().default({}),
891
+ embedding: vector("embedding").notNull(),
892
+ embeddingModel: text("embedding_model").notNull(),
893
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow()
894
+ },
895
+ (table) => ({
896
+ documentIndex: uniqueIndex("document_chunks_workspace_document_index_idx").on(
897
+ table.workspaceId,
898
+ table.documentId,
899
+ table.chunkIndex
900
+ ),
901
+ base: index("document_chunks_workspace_base_idx").on(table.workspaceId, table.baseId)
902
+ })
903
+ );
904
+ var knowledgeMemories = pgTable(
905
+ "knowledge_memories",
906
+ {
907
+ id: uuid("id").primaryKey().defaultRandom(),
908
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
909
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
910
+ status: text("status").notNull().default("proposed"),
911
+ kind: text("kind").notNull().default("semantic"),
912
+ scope: text("scope").notNull().default("workspace"),
913
+ text: text("text").notNull(),
914
+ sourceRefs: jsonb("source_refs").$type().notNull().default([]),
915
+ confidence: integer("confidence").notNull().default(50),
916
+ metadata: jsonb("metadata").$type().notNull().default({}),
917
+ createdBySessionId: uuid("created_by_session_id").references(() => sessions.id, {
918
+ onDelete: "set null"
919
+ }),
920
+ reviewedBy: text("reviewed_by"),
921
+ reviewedAt: timestamp("reviewed_at", { withTimezone: true }),
922
+ // Workspace Memory V1 (migration 0045). Embedding is nullable: fail-soft writes
923
+ // (embedder unavailable) persist keyword-searchable rows without a vector.
924
+ embedding: vector("embedding"),
925
+ embeddingModel: text("embedding_model"),
926
+ pinned: boolean("pinned").notNull().default(false),
927
+ usageCount: integer("usage_count").notNull().default(0),
928
+ lastUsedAt: timestamp("last_used_at", { withTimezone: true }),
929
+ // Self-referential supersession chain. FKs live in migration 0045 (ON DELETE SET
930
+ // NULL); declared here as plain columns like the migration-only composite FK.
931
+ supersedesId: uuid("supersedes_id"),
932
+ supersededById: uuid("superseded_by_id"),
933
+ validFrom: timestamp("valid_from", { withTimezone: true }).notNull().defaultNow(),
934
+ validUntil: timestamp("valid_until", { withTimezone: true }),
935
+ // sha256(normalizeMemoryText(text)) — exact-dedup key; see memory-domain.
936
+ textHash: text("text_hash"),
937
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
938
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
939
+ },
940
+ (table) => ({
941
+ workspaceStatus: index("knowledge_memories_workspace_status_idx").on(
942
+ table.workspaceId,
943
+ table.status,
944
+ table.updatedAt
945
+ ),
946
+ workspaceKind: index("knowledge_memories_workspace_kind_idx").on(table.workspaceId, table.kind),
947
+ workspaceScope: index("knowledge_memories_workspace_scope_idx").on(
948
+ table.workspaceId,
949
+ table.scope
950
+ ),
951
+ createdBySession: index("knowledge_memories_workspace_created_by_session_idx").on(
952
+ table.workspaceId,
953
+ table.createdBySessionId
954
+ ),
955
+ // Working-set selection (partial index mirrors migration 0045).
956
+ workspaceVisible: index("knowledge_memories_workspace_visible_idx").on(table.workspaceId, table.pinned, table.updatedAt).where(sql`${table.status} in ('active', 'approved')`),
957
+ workspaceTextHash: index("knowledge_memories_workspace_text_hash_idx").on(
958
+ table.workspaceId,
959
+ table.textHash
960
+ ),
961
+ workspaceVisibleTextHashUnique: uniqueIndex("knowledge_memories_workspace_visible_text_hash_uq").on(table.workspaceId, table.textHash).where(sql`${table.status} in ('active', 'approved') and ${table.textHash} is not null`)
962
+ })
963
+ );
964
+ var sessionTurns = pgTable(
965
+ "session_turns",
966
+ {
967
+ id: uuid("id").primaryKey().defaultRandom(),
968
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
969
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
970
+ sessionId: uuid("session_id").notNull().references(() => sessions.id, { onDelete: "cascade" }),
971
+ triggerEventId: uuid("trigger_event_id").notNull(),
972
+ temporalWorkflowId: text("temporal_workflow_id").notNull(),
973
+ status: text("status").notNull(),
974
+ source: text("source").notNull().default("user"),
975
+ position: bigint("position", { mode: "number" }).notNull(),
976
+ prompt: text("prompt").notNull(),
977
+ resources: jsonb("resources").$type().notNull().default([]),
978
+ tools: jsonb("tools").$type().notNull().default([]),
979
+ model: text("model").notNull(),
980
+ reasoningEffort: text("reasoning_effort").notNull(),
981
+ sandboxBackend: text("sandbox_backend").notNull(),
982
+ // Per-turn OS override. NULL = inherit the session's sandbox_os. CHECK-
983
+ // constrained to the SandboxOs enum (or NULL) in migration 0018.
984
+ sandboxOs: text("sandbox_os"),
985
+ metadata: jsonb("metadata").$type().notNull().default({}),
986
+ version: integer("version").notNull().default(1),
987
+ executionGeneration: integer("execution_generation").notNull().default(0),
988
+ // Composite FK to session_turn_attempts is installed by migration 0063.
989
+ // It lives in SQL because attempts carry the reciprocal turn FK and because
990
+ // the claim transaction preallocates this ID before inserting the attempt;
991
+ // the SQL constraint is therefore DEFERRABLE INITIALLY DEFERRED.
992
+ activeAttemptId: uuid("active_attempt_id"),
993
+ lineage: jsonb("lineage").$type().notNull().default({}),
994
+ cancelledBy: text("cancelled_by"),
995
+ cancelReason: text("cancel_reason"),
996
+ // Atomic per-turn toolspace call budget counter (migration 0043). Incremented
997
+ // by a single conditional UPDATE at tools/call time; the row lock serializes
998
+ // concurrent reservations so exactly `toolspaceMaxCallsPerTurn` succeed.
999
+ toolspaceCallCount: integer("toolspace_call_count").notNull().default(0),
1000
+ startedAt: timestamp("started_at", { withTimezone: true }),
1001
+ finishedAt: timestamp("finished_at", { withTimezone: true }),
1002
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
1003
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
1004
+ },
1005
+ (table) => ({
1006
+ workspaceIdentity: uniqueIndex("session_turns_workspace_id_idx").on(
1007
+ table.workspaceId,
1008
+ table.id
1009
+ ),
1010
+ queue: index("session_turns_workspace_queue_idx").on(
1011
+ table.workspaceId,
1012
+ table.sessionId,
1013
+ table.status,
1014
+ table.position
1015
+ ),
1016
+ oneCurrentInference: uniqueIndex("session_turns_one_current_inference_uq").on(table.workspaceId, table.sessionId).where(sql`${table.status} in ('running','requires_action','recovering','waiting_capacity')`)
1017
+ })
1018
+ );
1019
+ var sessionTurnAttempts = pgTable(
1020
+ "session_turn_attempts",
1021
+ {
1022
+ id: uuid("id").primaryKey(),
1023
+ accountId: uuid("account_id").notNull(),
1024
+ workspaceId: uuid("workspace_id").notNull(),
1025
+ sessionId: uuid("session_id").notNull(),
1026
+ turnId: uuid("turn_id").notNull(),
1027
+ executionGeneration: integer("execution_generation").notNull(),
1028
+ state: text("state").notNull().default("claimed"),
1029
+ outcome: text("outcome"),
1030
+ temporalWorkflowId: text("temporal_workflow_id").notNull(),
1031
+ temporalWorkflowRunId: text("temporal_workflow_run_id").notNull(),
1032
+ temporalActivityId: text("temporal_activity_id").notNull(),
1033
+ workerId: text("worker_id"),
1034
+ leaseId: text("lease_id"),
1035
+ leaseExpiresAt: timestamp("lease_expires_at", { withTimezone: true }),
1036
+ verifiedControlRevision: bigint("verified_control_revision", { mode: "number" }).notNull(),
1037
+ startedAt: timestamp("started_at", { withTimezone: true }).notNull().defaultNow(),
1038
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
1039
+ closedAt: timestamp("closed_at", { withTimezone: true })
1040
+ },
1041
+ (table) => ({
1042
+ workspaceAccount: foreignKey({
1043
+ name: "session_turn_attempts_workspace_account_fk",
1044
+ columns: [table.workspaceId, table.accountId],
1045
+ foreignColumns: [workspaces.id, workspaces.accountId]
1046
+ }).onDelete("cascade"),
1047
+ workspaceSession: foreignKey({
1048
+ name: "session_turn_attempts_workspace_session_fk",
1049
+ columns: [table.workspaceId, table.sessionId],
1050
+ foreignColumns: [sessions.workspaceId, sessions.id]
1051
+ }).onDelete("restrict"),
1052
+ workspaceTurn: foreignKey({
1053
+ name: "session_turn_attempts_workspace_turn_fk",
1054
+ columns: [table.workspaceId, table.turnId],
1055
+ foreignColumns: [sessionTurns.workspaceId, sessionTurns.id]
1056
+ }).onDelete("restrict"),
1057
+ workspaceIdentity: uniqueIndex("session_turn_attempts_workspace_id_uq").on(
1058
+ table.workspaceId,
1059
+ table.id
1060
+ ),
1061
+ liveTurn: uniqueIndex("session_turn_attempts_live_turn_uq").on(table.workspaceId, table.turnId).where(sql`${table.state} in ('claimed', 'running')`),
1062
+ liveSession: uniqueIndex("session_turn_attempts_live_session_uq").on(table.workspaceId, table.sessionId).where(sql`${table.state} in ('claimed', 'running')`),
1063
+ dispatch: uniqueIndex("session_turn_attempts_dispatch_uq").on(
1064
+ table.workspaceId,
1065
+ table.temporalWorkflowRunId,
1066
+ table.temporalActivityId
1067
+ ),
1068
+ leaseExpiry: index("session_turn_attempts_lease_expiry_idx").on(table.leaseExpiresAt, table.workspaceId, table.sessionId).where(sql`${table.state} in ('claimed', 'running')`),
1069
+ stateValid: check(
1070
+ "session_turn_attempts_state_check",
1071
+ sql`${table.state} in ('claimed', 'running', 'closed')`
1072
+ ),
1073
+ outcomeValid: check(
1074
+ "session_turn_attempts_outcome_check",
1075
+ sql`${table.outcome} is null or ${table.outcome} in (
1076
+ 'completed', 'failed', 'cancelled', 'superseded', 'requires_action',
1077
+ 'interrupted_recoverable', 'lease_lost_recoverable', 'pre_cutover_closed'
1078
+ )`
1079
+ ),
1080
+ closedConsistent: check(
1081
+ "session_turn_attempts_closed_check",
1082
+ sql`(${table.state} = 'closed' and ${table.outcome} is not null and ${table.closedAt} is not null)
1083
+ or (${table.state} <> 'closed' and ${table.outcome} is null and ${table.closedAt} is null)`
1084
+ )
1085
+ })
1086
+ );
1087
+ var sessionCommandReceipts = pgTable(
1088
+ "session_command_receipts",
1089
+ {
1090
+ id: uuid("id").primaryKey().defaultRandom(),
1091
+ accountId: uuid("account_id").notNull(),
1092
+ workspaceId: uuid("workspace_id").notNull(),
1093
+ actorType: text("actor_type").notNull(),
1094
+ actorSubjectId: text("actor_subject_id"),
1095
+ actorAttemptId: uuid("actor_attempt_id"),
1096
+ action: text("action").notNull(),
1097
+ targetSessionId: uuid("target_session_id"),
1098
+ targetTurnId: uuid("target_turn_id"),
1099
+ operationKey: text("operation_key").notNull(),
1100
+ canonicalRequestHash: text("canonical_request_hash").notNull(),
1101
+ appliedControlRevision: bigint("applied_control_revision", { mode: "number" }),
1102
+ appliedQueueVersion: integer("applied_queue_version"),
1103
+ appliedTurnVersion: integer("applied_turn_version"),
1104
+ appliedDraftRevision: bigint("applied_draft_revision", { mode: "number" }),
1105
+ result: jsonb("result").$type().notNull().default({}),
1106
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
1107
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
1108
+ },
1109
+ (table) => ({
1110
+ workspaceAccount: foreignKey({
1111
+ name: "session_command_receipts_workspace_account_fk",
1112
+ columns: [table.workspaceId, table.accountId],
1113
+ foreignColumns: [workspaces.id, workspaces.accountId]
1114
+ }).onDelete("cascade"),
1115
+ actorAttempt: foreignKey({
1116
+ name: "session_command_receipts_actor_attempt_fk",
1117
+ columns: [table.workspaceId, table.actorAttemptId],
1118
+ foreignColumns: [sessionTurnAttempts.workspaceId, sessionTurnAttempts.id]
1119
+ }).onDelete("restrict"),
1120
+ targetSession: foreignKey({
1121
+ name: "session_command_receipts_target_session_fk",
1122
+ columns: [table.workspaceId, table.targetSessionId],
1123
+ foreignColumns: [sessions.workspaceId, sessions.id]
1124
+ }).onDelete("restrict"),
1125
+ targetTurn: foreignKey({
1126
+ name: "session_command_receipts_target_turn_fk",
1127
+ columns: [table.workspaceId, table.targetTurnId],
1128
+ foreignColumns: [sessionTurns.workspaceId, sessionTurns.id]
1129
+ }).onDelete("restrict"),
1130
+ workspaceIdentity: uniqueIndex("session_command_receipts_workspace_id_uq").on(
1131
+ table.workspaceId,
1132
+ table.id
1133
+ ),
1134
+ targetCreated: index("session_command_receipts_target_created_idx").on(
1135
+ table.workspaceId,
1136
+ table.targetSessionId,
1137
+ table.createdAt
1138
+ ),
1139
+ actorValid: check(
1140
+ "session_command_receipts_actor_check",
1141
+ sql`(
1142
+ ${table.actorType} = 'agent_attempt'
1143
+ and ${table.actorAttemptId} is not null
1144
+ and ${table.actorSubjectId} is null
1145
+ ) or (
1146
+ ${table.actorType} in ('human', 'operator')
1147
+ and ${table.actorSubjectId} is not null
1148
+ and ${table.actorAttemptId} is null
1149
+ )`
1150
+ )
1151
+ })
1152
+ );
1153
+ var workspaceControlEvents = pgTable(
1154
+ "workspace_control_events",
1155
+ {
1156
+ id: uuid("id").primaryKey().defaultRandom(),
1157
+ accountId: uuid("account_id").notNull(),
1158
+ workspaceId: uuid("workspace_id").notNull(),
1159
+ revision: bigint("revision", { mode: "number" }).notNull(),
1160
+ scope: text("scope").notNull(),
1161
+ rootSessionId: uuid("root_session_id"),
1162
+ action: text("action").notNull(),
1163
+ automatic: boolean("automatic").notNull().default(false),
1164
+ reason: text("reason"),
1165
+ actor: text("actor").notNull(),
1166
+ occurredAt: timestamp("occurred_at", { withTimezone: true }).notNull().defaultNow()
1167
+ },
1168
+ (table) => ({
1169
+ workspaceAccount: foreignKey({
1170
+ name: "workspace_control_events_workspace_account_fk",
1171
+ columns: [table.workspaceId, table.accountId],
1172
+ foreignColumns: [workspaces.id, workspaces.accountId]
1173
+ }).onDelete("cascade"),
1174
+ rootSession: foreignKey({
1175
+ name: "workspace_control_events_root_session_fk",
1176
+ columns: [table.workspaceId, table.rootSessionId],
1177
+ foreignColumns: [sessions.workspaceId, sessions.id]
1178
+ }).onDelete("restrict"),
1179
+ workspaceRevision: uniqueIndex("workspace_control_events_workspace_revision_uq").on(
1180
+ table.workspaceId,
1181
+ table.revision
1182
+ ),
1183
+ revisionValid: check("workspace_control_events_revision_check", sql`${table.revision} > 0`),
1184
+ shapeValid: check(
1185
+ "workspace_control_events_shape_check",
1186
+ sql`(${table.scope} = 'workspace' and ${table.rootSessionId} is null)
1187
+ or (${table.scope} = 'session' and ${table.rootSessionId} is not null)`
1188
+ ),
1189
+ actionValid: check(
1190
+ "workspace_control_events_action_check",
1191
+ sql`${table.action} in ('pause', 'resume')`
1192
+ )
1193
+ })
1194
+ );
1195
+ var sessionAttemptInterruptions = pgTable(
1196
+ "session_attempt_interruptions",
1197
+ {
1198
+ id: uuid("id").primaryKey().defaultRandom(),
1199
+ accountId: uuid("account_id").notNull(),
1200
+ workspaceId: uuid("workspace_id").notNull(),
1201
+ sessionId: uuid("session_id").notNull(),
1202
+ operationId: uuid("operation_id").notNull(),
1203
+ attemptId: uuid("attempt_id").notNull(),
1204
+ kind: text("kind").notNull(),
1205
+ controlRevision: bigint("control_revision", { mode: "number" }).notNull(),
1206
+ state: text("state").notNull().default("pending"),
1207
+ requestedAt: timestamp("requested_at", { withTimezone: true }).notNull().defaultNow(),
1208
+ deliveredAt: timestamp("delivered_at", { withTimezone: true }),
1209
+ acknowledgedAt: timestamp("acknowledged_at", { withTimezone: true }),
1210
+ settledAt: timestamp("settled_at", { withTimezone: true })
1211
+ },
1212
+ (table) => ({
1213
+ workspaceAccount: foreignKey({
1214
+ name: "session_attempt_interruptions_workspace_account_fk",
1215
+ columns: [table.workspaceId, table.accountId],
1216
+ foreignColumns: [workspaces.id, workspaces.accountId]
1217
+ }).onDelete("cascade"),
1218
+ workspaceSession: foreignKey({
1219
+ name: "session_attempt_interruptions_workspace_session_fk",
1220
+ columns: [table.workspaceId, table.sessionId],
1221
+ foreignColumns: [sessions.workspaceId, sessions.id]
1222
+ }).onDelete("restrict"),
1223
+ operation: foreignKey({
1224
+ name: "session_attempt_interruptions_operation_fk",
1225
+ columns: [table.workspaceId, table.operationId],
1226
+ foreignColumns: [sessionCommandReceipts.workspaceId, sessionCommandReceipts.id]
1227
+ }).onDelete("restrict"),
1228
+ attempt: foreignKey({
1229
+ name: "session_attempt_interruptions_attempt_fk",
1230
+ columns: [table.workspaceId, table.attemptId],
1231
+ foreignColumns: [sessionTurnAttempts.workspaceId, sessionTurnAttempts.id]
1232
+ }).onDelete("restrict"),
1233
+ operationAttempt: uniqueIndex("session_attempt_interruptions_operation_attempt_uq").on(
1234
+ table.operationId,
1235
+ table.attemptId
1236
+ ),
1237
+ unsettled: index("session_attempt_interruptions_unsettled_idx").on(table.workspaceId, table.sessionId, table.requestedAt).where(sql`${table.state} in ('pending', 'delivered', 'acknowledged')`),
1238
+ kindValid: check(
1239
+ "session_attempt_interruptions_kind_check",
1240
+ sql`${table.kind} in ('session_pause', 'workspace_pause', 'steer', 'maintenance')`
1241
+ ),
1242
+ stateValid: check(
1243
+ "session_attempt_interruptions_state_check",
1244
+ sql`${table.state} in ('pending', 'delivered', 'acknowledged', 'settled', 'rejected_stale')`
1245
+ )
1246
+ })
1247
+ );
1248
+ var composerDrafts = pgTable(
1249
+ "composer_drafts",
1250
+ {
1251
+ id: uuid("id").primaryKey().defaultRandom(),
1252
+ accountId: uuid("account_id").notNull(),
1253
+ workspaceId: uuid("workspace_id").notNull(),
1254
+ sessionId: uuid("session_id").notNull(),
1255
+ subjectId: text("subject_id").notNull(),
1256
+ revision: bigint("revision", { mode: "number" }).notNull().default(1),
1257
+ text: text("text").notNull().default(""),
1258
+ resources: jsonb("resources").$type().notNull().default([]),
1259
+ tools: jsonb("tools").$type().notNull().default([]),
1260
+ model: text("model").notNull(),
1261
+ reasoningEffort: text("reasoning_effort").notNull(),
1262
+ sourceTurnId: uuid("source_turn_id"),
1263
+ sourceTurnVersion: integer("source_turn_version"),
1264
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
1265
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
1266
+ },
1267
+ (table) => ({
1268
+ workspaceAccount: foreignKey({
1269
+ name: "composer_drafts_workspace_account_fk",
1270
+ columns: [table.workspaceId, table.accountId],
1271
+ foreignColumns: [workspaces.id, workspaces.accountId]
1272
+ }).onDelete("cascade"),
1273
+ workspaceSession: foreignKey({
1274
+ name: "composer_drafts_workspace_session_fk",
1275
+ columns: [table.workspaceId, table.sessionId],
1276
+ foreignColumns: [sessions.workspaceId, sessions.id]
1277
+ }).onDelete("cascade"),
1278
+ sourceTurn: foreignKey({
1279
+ name: "composer_drafts_source_turn_fk",
1280
+ columns: [table.workspaceId, table.sourceTurnId],
1281
+ foreignColumns: [sessionTurns.workspaceId, sessionTurns.id]
1282
+ }).onDelete("restrict"),
1283
+ subjectSession: uniqueIndex("composer_drafts_subject_session_uq").on(
1284
+ table.workspaceId,
1285
+ table.sessionId,
1286
+ table.subjectId
1287
+ ),
1288
+ subjectValid: check(
1289
+ "composer_drafts_subject_check",
1290
+ sql`length(btrim(${table.subjectId})) > 0`
1291
+ ),
1292
+ revisionValid: check("composer_drafts_revision_check", sql`${table.revision} >= 1`)
1293
+ })
1294
+ );
1295
+ var sessionSystemUpdates = pgTable(
1296
+ "session_system_updates",
1297
+ {
1298
+ id: uuid("id").primaryKey().defaultRandom(),
1299
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
1300
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
1301
+ sessionId: uuid("session_id").notNull().references(() => sessions.id, { onDelete: "cascade" }),
1302
+ kind: text("kind").notNull(),
1303
+ classification: text("classification").notNull().default("info"),
1304
+ sourceId: text("source_id").notNull(),
1305
+ dedupeKey: text("dedupe_key").notNull(),
1306
+ summary: text("summary").notNull(),
1307
+ payload: jsonb("payload").$type().notNull().default({}),
1308
+ lineage: jsonb("lineage").$type().notNull().default({}),
1309
+ // pending: eligible to start/attach to an inference; deferred: preserved
1310
+ // after a failed internal-only inference but dormant until a real prompt or
1311
+ // a genuinely new pending update arrives; delivered/cancelled/failed are
1312
+ // terminal for that delivery attempt.
1313
+ state: text("state").notNull().default("pending"),
1314
+ deliveredTurnId: uuid("delivered_turn_id").references(() => sessionTurns.id, {
1315
+ onDelete: "set null"
1316
+ }),
1317
+ deliveredAt: timestamp("delivered_at", { withTimezone: true }),
1318
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow()
1319
+ },
1320
+ (table) => ({
1321
+ kindValid: check(
1322
+ "system_updates_kind_check",
1323
+ sql`${table.kind} in ('scheduled_occurrence', 'goal_continuation', 'agent_message', 'agent_steer_instruction', 'child_terminal_result')`
1324
+ ),
1325
+ payloadKindValid: check(
1326
+ "system_updates_payload_kind_check",
1327
+ sql`${table.payload} ->> 'type' = ${table.kind}`
1328
+ ),
1329
+ stateValid: check(
1330
+ "system_updates_state_check",
1331
+ sql`${table.state} in ('pending', 'deferred', 'delivered', 'cancelled', 'superseded', 'failed')`
1332
+ ),
1333
+ dedupe: uniqueIndex("session_system_updates_dedupe_uq").on(
1334
+ table.workspaceId,
1335
+ table.sessionId,
1336
+ table.dedupeKey
1337
+ ),
1338
+ pending: index("session_system_updates_pending_idx").on(
1339
+ table.workspaceId,
1340
+ table.sessionId,
1341
+ table.state,
1342
+ table.createdAt
1343
+ )
1344
+ })
1345
+ );
1346
+ var sessionSystemUpdateOutbox = pgTable(
1347
+ "session_system_update_outbox",
1348
+ {
1349
+ id: uuid("id").primaryKey().defaultRandom(),
1350
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
1351
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
1352
+ sourceSessionId: uuid("source_session_id").notNull().references(() => sessions.id, { onDelete: "cascade" }),
1353
+ targetSessionId: uuid("target_session_id").notNull().references(() => sessions.id, { onDelete: "cascade" }),
1354
+ dedupeKey: text("dedupe_key").notNull(),
1355
+ kind: text("kind").notNull(),
1356
+ classification: text("classification").notNull(),
1357
+ sourceId: text("source_id").notNull(),
1358
+ summary: text("summary").notNull(),
1359
+ payload: jsonb("payload").$type().notNull().default({}),
1360
+ lineage: jsonb("lineage").$type().notNull().default({}),
1361
+ status: text("status").notNull().default("pending"),
1362
+ attempts: integer("attempts").notNull().default(0),
1363
+ updateId: uuid("update_id"),
1364
+ lastError: text("last_error"),
1365
+ deliveredAt: timestamp("delivered_at", { withTimezone: true }),
1366
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
1367
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
1368
+ },
1369
+ (table) => ({
1370
+ kindValid: check(
1371
+ "system_update_outbox_kind_check",
1372
+ sql`${table.kind} = 'child_terminal_result'`
1373
+ ),
1374
+ payloadKindValid: check(
1375
+ "system_update_outbox_payload_kind_check",
1376
+ sql`${table.payload} ->> 'type' = 'child_terminal_result'`
1377
+ ),
1378
+ dedupe: uniqueIndex("session_system_update_outbox_dedupe_uq").on(
1379
+ table.workspaceId,
1380
+ table.dedupeKey
1381
+ ),
1382
+ pending: index("session_system_update_outbox_pending_idx").on(table.status, table.createdAt)
1383
+ })
1384
+ );
1385
+ var sessionWorkflowWakeOutbox = pgTable(
1386
+ "session_workflow_wake_outbox",
1387
+ {
1388
+ sessionId: uuid("session_id").primaryKey(),
1389
+ accountId: uuid("account_id").notNull(),
1390
+ workspaceId: uuid("workspace_id").notNull(),
1391
+ temporalWorkflowId: text("temporal_workflow_id").notNull(),
1392
+ wakeRevision: bigint("wake_revision", { mode: "number" }).notNull().default(1),
1393
+ deliveredRevision: bigint("delivered_revision", { mode: "number" }).notNull().default(0),
1394
+ reason: text("reason").notNull(),
1395
+ attempts: integer("attempts").notNull().default(0),
1396
+ nextAttemptAt: timestamp("next_attempt_at", { withTimezone: true }).notNull().defaultNow(),
1397
+ lastError: text("last_error"),
1398
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
1399
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
1400
+ },
1401
+ (table) => ({
1402
+ revisionValid: check(
1403
+ "session_workflow_wake_outbox_revision_check",
1404
+ sql`${table.wakeRevision} > 0 and ${table.deliveredRevision} >= 0 and ${table.deliveredRevision} <= ${table.wakeRevision}`
1405
+ ),
1406
+ workspaceAccount: foreignKey({
1407
+ name: "session_workflow_wake_outbox_workspace_account_fk",
1408
+ columns: [table.workspaceId, table.accountId],
1409
+ foreignColumns: [workspaces.id, workspaces.accountId]
1410
+ }).onDelete("cascade"),
1411
+ workspaceSessionFk: foreignKey({
1412
+ name: "session_workflow_wake_outbox_workspace_session_fk",
1413
+ columns: [table.workspaceId, table.sessionId],
1414
+ foreignColumns: [sessions.workspaceId, sessions.id]
1415
+ }).onDelete("cascade"),
1416
+ workspaceSession: uniqueIndex("session_workflow_wake_outbox_workspace_session_uq").on(
1417
+ table.workspaceId,
1418
+ table.sessionId
1419
+ ),
1420
+ pending: index("session_workflow_wake_outbox_pending_idx").on(table.nextAttemptAt, table.updatedAt, table.sessionId).where(sql`${table.wakeRevision} > ${table.deliveredRevision}`)
1421
+ })
1422
+ );
1423
+ var sessionGoals = pgTable(
1424
+ "session_goals",
1425
+ {
1426
+ id: uuid("id").primaryKey().defaultRandom(),
1427
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
1428
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
1429
+ sessionId: uuid("session_id").notNull().references(() => sessions.id, { onDelete: "cascade" }),
1430
+ status: text("status").notNull().default("active"),
1431
+ // active | paused | completed
1432
+ text: text("text").notNull(),
1433
+ successCriteria: text("success_criteria"),
1434
+ evidence: text("evidence"),
1435
+ // set by goal_complete
1436
+ rationale: text("rationale"),
1437
+ // set by goal_pause
1438
+ pausedReason: text("paused_reason"),
1439
+ // agent | user_pause | api | no_progress | max_auto_continuations | limits
1440
+ createdBy: text("created_by").notNull().default("api"),
1441
+ // api | agent | scheduled_task
1442
+ version: integer("version").notNull().default(1),
1443
+ // bumped on every set/update; progress signal
1444
+ autoContinuations: integer("auto_continuations").notNull().default(0),
1445
+ noProgressStreak: integer("no_progress_streak").notNull().default(0),
1446
+ maxAutoContinuations: integer("max_auto_continuations"),
1447
+ // per-goal override; a configured settings cap (if any) remains the hard ceiling
1448
+ lastContinuationTurnId: uuid("last_continuation_turn_id"),
1449
+ versionAtLastContinuation: integer("version_at_last_continuation"),
1450
+ metadata: jsonb("metadata").$type().notNull().default({}),
1451
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
1452
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
1453
+ },
1454
+ (table) => ({
1455
+ workspaceIdentity: uniqueIndex("session_goals_workspace_id_idx").on(
1456
+ table.workspaceId,
1457
+ table.id
1458
+ ),
1459
+ workspaceSession: uniqueIndex("session_goals_workspace_session_idx").on(
1460
+ table.workspaceId,
1461
+ table.sessionId
1462
+ ),
1463
+ status: index("session_goals_workspace_status_idx").on(table.workspaceId, table.status)
1464
+ })
1465
+ );
1466
+ var codexCapacityWaiters = pgTable(
1467
+ "codex_capacity_waiters",
1468
+ {
1469
+ id: uuid("id").primaryKey().defaultRandom(),
1470
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
1471
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
1472
+ sessionId: uuid("session_id").notNull(),
1473
+ goalId: uuid("goal_id").notNull(),
1474
+ blockedTurnId: uuid("blocked_turn_id").notNull(),
1475
+ workflowId: text("workflow_id").notNull(),
1476
+ generation: integer("generation").notNull().default(1),
1477
+ status: text("status").notNull().default("waiting"),
1478
+ // waiting | resumed | superseded
1479
+ goalVersion: integer("goal_version").notNull(),
1480
+ policyHash: text("policy_hash"),
1481
+ earliestResetAt: timestamp("earliest_reset_at", { withTimezone: true }),
1482
+ nextCheckAt: timestamp("next_check_at", { withTimezone: true }).notNull(),
1483
+ resetKind: text("reset_kind").notNull(),
1484
+ // authoritative | bounded_refresh
1485
+ refreshAttempt: integer("refresh_attempt").notNull().default(0),
1486
+ // Coalescing outbox generation. Every eligibility-affecting mutation bumps
1487
+ // wakeRevision. Duplicate/lost Temporal signals are harmless because only
1488
+ // the row-locked evaluator moves observedWakeRevision and may enqueue work.
1489
+ wakeRevision: integer("wake_revision").notNull().default(1),
1490
+ observedWakeRevision: integer("observed_wake_revision").notNull().default(0),
1491
+ lastWakeReason: text("last_wake_reason").notNull().default("capacity_wait_armed"),
1492
+ resumedUpdateId: uuid("resumed_update_id"),
1493
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
1494
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
1495
+ },
1496
+ (table) => ({
1497
+ workspaceSession: uniqueIndex("codex_capacity_waiters_workspace_session_idx").on(
1498
+ table.workspaceId,
1499
+ table.sessionId
1500
+ ),
1501
+ workspaceId: uniqueIndex("codex_capacity_waiters_workspace_id_idx").on(
1502
+ table.workspaceId,
1503
+ table.id
1504
+ ),
1505
+ pending: index("codex_capacity_waiters_pending_idx").on(
1506
+ table.workspaceId,
1507
+ table.status,
1508
+ table.nextCheckAt
1509
+ ),
1510
+ wakeRepair: index("codex_capacity_waiters_wake_repair_idx").on(
1511
+ table.status,
1512
+ table.wakeRevision,
1513
+ table.observedWakeRevision
1514
+ )
1515
+ })
1516
+ );
1517
+ var sessionEvents = pgTable(
1518
+ "session_events",
1519
+ {
1520
+ id: uuid("id").primaryKey().defaultRandom(),
1521
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
1522
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
1523
+ sessionId: uuid("session_id").notNull().references(() => sessions.id, { onDelete: "cascade" }),
1524
+ turnId: uuid("turn_id"),
1525
+ turnGeneration: integer("turn_generation"),
1526
+ turnAttemptId: uuid("turn_attempt_id"),
1527
+ turnAssociation: text("turn_association"),
1528
+ duplicateOfEventId: uuid("duplicate_of_event_id"),
1529
+ duplicateReason: text("duplicate_reason"),
1530
+ sequence: integer("sequence").notNull(),
1531
+ type: text("type").notNull(),
1532
+ payload: jsonb("payload").$type().notNull().default({}),
1533
+ clientEventId: text("client_event_id"),
1534
+ producerId: text("producer_id"),
1535
+ producerSeq: integer("producer_seq"),
1536
+ occurredAt: timestamp("occurred_at", { withTimezone: true }).notNull().defaultNow(),
1537
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow()
1538
+ },
1539
+ (table) => ({
1540
+ workspaceAttempt: foreignKey({
1541
+ name: "session_events_workspace_attempt_fk",
1542
+ columns: [table.workspaceId, table.turnAttemptId],
1543
+ foreignColumns: [sessionTurnAttempts.workspaceId, sessionTurnAttempts.id]
1544
+ }).onDelete("restrict"),
1545
+ sessionSequence: uniqueIndex("session_events_workspace_session_sequence_idx").on(
1546
+ table.workspaceId,
1547
+ table.sessionId,
1548
+ table.sequence
1549
+ ),
1550
+ clientEvent: uniqueIndex("session_events_workspace_client_event_idx").on(table.workspaceId, table.sessionId, table.clientEventId).where(sql`${table.clientEventId} is not null`),
1551
+ producer: uniqueIndex("session_events_workspace_producer_idx").on(table.workspaceId, table.sessionId, table.producerId, table.producerSeq).where(sql`${table.producerId} is not null and ${table.producerSeq} is not null`),
1552
+ sessionCreated: index("session_events_workspace_session_created_idx").on(
1553
+ table.workspaceId,
1554
+ table.sessionId,
1555
+ table.createdAt
1556
+ )
1557
+ })
1558
+ );
1559
+ var agentRunStates = pgTable("agent_run_states", {
1560
+ id: uuid("id").primaryKey().defaultRandom(),
1561
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
1562
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
1563
+ sessionId: uuid("session_id").notNull().references(() => sessions.id, { onDelete: "cascade" }),
1564
+ turnId: uuid("turn_id").references(() => sessionTurns.id, { onDelete: "set null" }),
1565
+ stateVersion: integer("state_version").notNull(),
1566
+ serializedRunState: text("serialized_run_state").notNull(),
1567
+ pendingApprovals: jsonb("pending_approvals").$type().notNull().default([]),
1568
+ // The Codex account that FROZE this run state: the turn's resolved codex
1569
+ // credential id (pin > workspace-active), or NULL when frozen on the
1570
+ // non-codex / Azure path (or before this column existed). The serialized
1571
+ // RunState blob round-trips `reasoning.encrypted_content` minted by the
1572
+ // ChatGPT/Codex backend — account/org-bound, so a foreign blob 400s — and the
1573
+ // foreign reasoning ids the Responses backend validates; but the blob carries
1574
+ // NO per-item producer tag (those live only on session_history_items). So we
1575
+ // stamp the freezing account here: on an approval resume whose codex account
1576
+ // DIFFERS from this value,
1577
+ // the replay path neutralizes every reasoning item's account-bound identity
1578
+ // (encrypted_content + provider id) in the blob before it reaches the model.
1579
+ // Deliberately NO FK: provenance must OUTLIVE the account's hard-disconnect (a
1580
+ // stale-but-null tag still mismatches a live codex id, so the strip stays
1581
+ // correct either way). NULL on both sides (non-codex freeze + non-codex
1582
+ // resume) is a no-op, so single-account and non-codex sessions are unchanged.
1583
+ frozenCodexCredentialId: uuid("frozen_codex_credential_id"),
1584
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow()
1585
+ });
1586
+ var sessionHistoryItems = pgTable(
1587
+ "session_history_items",
1588
+ {
1589
+ id: uuid("id").primaryKey().defaultRandom(),
1590
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
1591
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
1592
+ sessionId: uuid("session_id").notNull().references(() => sessions.id, { onDelete: "cascade" }),
1593
+ turnId: uuid("turn_id").references(() => sessionTurns.id, { onDelete: "set null" }),
1594
+ // Numeric (not integer) so the synthetic compaction-summary row can be
1595
+ // inserted at a FRACTIONAL position (boundaryPosition - 0.5) that sorts ahead
1596
+ // of the kept tail without colliding with — and thus overwriting — the real
1597
+ // prefix row at boundaryPosition - 1. Normally-appended rows keep whole-number
1598
+ // positions; only the summary uses the half-step. `mode: "number"` maps the
1599
+ // postgres.js string back to a JS number so every reader stays numeric.
1600
+ position: numeric("position", { mode: "number" }).notNull(),
1601
+ item: jsonb("item").$type().notNull(),
1602
+ // Live-row flag for client-side context compaction. The read path selects
1603
+ // only active rows; a compaction supersedes the summarized prefix (sets this
1604
+ // false — never deletes, so the full transcript stays as an audit trail) and
1605
+ // inserts ONE synthetic active summary row at the boundary. Defaults true so
1606
+ // every existing and normally-appended row is live.
1607
+ active: boolean("active").notNull().default(true),
1608
+ // The Codex account that PRODUCED these items: the per-turn resolved codex
1609
+ // credential id (pin > workspace-active), or NULL when produced on the
1610
+ // non-codex / Azure path (or before this column existed). Used to strip
1611
+ // cross-account `reasoning.encrypted_content` blobs — those are account/org-
1612
+ // bound, minted by the ChatGPT/Codex backend, so replaying account A's blob
1613
+ // into a turn running on account B 400s. The read path drops the encrypted
1614
+ // reasoning of any item whose producer != the turn's current codex account.
1615
+ // Deliberately NO FK: provenance must OUTLIVE the account's hard-disconnect
1616
+ // (an ON DELETE SET NULL would erase the tag, and a stale-but-null tag still
1617
+ // mismatches a live codex id so the strip stays correct either way).
1618
+ producerCodexCredentialId: uuid("producer_codex_credential_id"),
1619
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow()
1620
+ },
1621
+ (table) => ({
1622
+ positionIdx: uniqueIndex("session_history_items_position_idx").on(
1623
+ table.workspaceId,
1624
+ table.sessionId,
1625
+ table.position
1626
+ )
1627
+ })
1628
+ );
1629
+ var sessionPendingToolCalls = pgTable(
1630
+ "session_pending_tool_calls",
1631
+ {
1632
+ id: uuid("id").primaryKey().defaultRandom(),
1633
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
1634
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
1635
+ sessionId: uuid("session_id").notNull().references(() => sessions.id, { onDelete: "cascade" }),
1636
+ turnId: uuid("turn_id").notNull().references(() => sessionTurns.id, { onDelete: "cascade" }),
1637
+ executionGeneration: integer("execution_generation").notNull(),
1638
+ attemptId: uuid("attempt_id").notNull(),
1639
+ callId: text("call_id").notNull(),
1640
+ callType: text("call_type").notNull(),
1641
+ callItem: jsonb("call_item").$type().notNull(),
1642
+ resultItem: jsonb("result_item").$type(),
1643
+ resultRecordedAt: timestamp("result_recorded_at", { withTimezone: true }),
1644
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow()
1645
+ },
1646
+ (table) => ({
1647
+ workspaceAttempt: foreignKey({
1648
+ name: "pending_tool_calls_workspace_attempt_fk",
1649
+ columns: [table.workspaceId, table.attemptId],
1650
+ foreignColumns: [sessionTurnAttempts.workspaceId, sessionTurnAttempts.id]
1651
+ }).onDelete("restrict"),
1652
+ turnCall: uniqueIndex("session_pending_tool_calls_turn_call_idx").on(
1653
+ table.workspaceId,
1654
+ table.turnId,
1655
+ table.callId
1656
+ ),
1657
+ sessionTurn: index("session_pending_tool_calls_session_turn_idx").on(
1658
+ table.workspaceId,
1659
+ table.sessionId,
1660
+ table.turnId
1661
+ )
1662
+ })
1663
+ );
1664
+ var sandboxSessionEnvelopes = pgTable(
1665
+ "sandbox_session_envelopes",
1666
+ {
1667
+ id: uuid("id").primaryKey().defaultRandom(),
1668
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
1669
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
1670
+ sessionId: uuid("session_id").notNull().references(() => sessions.id, { onDelete: "cascade" }),
1671
+ envelope: jsonb("envelope").$type().notNull(),
1672
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
1673
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
1674
+ },
1675
+ (table) => ({
1676
+ sessionIdx: uniqueIndex("sandbox_session_envelopes_session_idx").on(
1677
+ table.workspaceId,
1678
+ table.sessionId
1679
+ )
1680
+ })
1681
+ );
1682
+ var sandboxLeaseLivenessValues = ["cold", "warming", "warm", "draining"];
1683
+ var sandboxLeases = pgTable(
1684
+ "sandbox_leases",
1685
+ {
1686
+ id: uuid("id").primaryKey().defaultRandom(),
1687
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
1688
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
1689
+ sandboxGroupId: uuid("sandbox_group_id").notNull(),
1690
+ liveness: text("liveness", { enum: sandboxLeaseLivenessValues }).notNull().default("cold"),
1691
+ refcount: integer("refcount").notNull().default(0),
1692
+ turnHolders: integer("turn_holders").notNull().default(0),
1693
+ viewerHolders: integer("viewer_holders").notNull().default(0),
1694
+ instanceId: text("instance_id"),
1695
+ backend: text("backend").notNull(),
1696
+ os: text("os").notNull().default("linux"),
1697
+ // The container IMAGE the group box runs (Modal image ref / docker image). A shared
1698
+ // box is SHARED STATE: all its sessions run the SAME filesystem, so they must run the
1699
+ // same image. This column stamps the image the live box was created with; a resume
1700
+ // whose resolved image DIFFERS is a conflict (B3): a solo holder recreates the box on
1701
+ // the new image, N-holders are rejected (SandboxImageConflictError). Nullable — a
1702
+ // legacy/cold row reads NULL = "image unknown", which never conflicts.
1703
+ image: text("image"),
1704
+ // The frozen rig version the live box was created under (M3). Like `image`,
1705
+ // this is SHARED STATE: all the box's sessions run the same rig-baked setup,
1706
+ // so a resume resolving a DIFFERENT rig_version_id conflicts (solo holder
1707
+ // recreates cold on the new rig; N-holders throw SandboxRigConflictError).
1708
+ // Nullable — a legacy/cold row or a rig-less session reads NULL = "rig
1709
+ // unknown", which never conflicts. No FK (symmetric with sandbox_group_id's
1710
+ // bare-uuid rationale: this lease outlives no single rig_versions row's RLS).
1711
+ rigVersionId: uuid("rig_version_id"),
1712
+ dataPlaneUrl: text("data_plane_url"),
1713
+ // The REAL PTY terminal (ttyd pty-ws) rides a SEPARATE provider tunnel (7681)
1714
+ // from the desktop noVNC (6080), so its resolved URL is cached independently.
1715
+ // Recorded under the epoch fence by recordLeaseTerminalDataPlaneUrl; reset to
1716
+ // null on every box re-key (warm-commit / fail / drain), symmetric with
1717
+ // data_plane_url.
1718
+ terminalDataPlaneUrl: text("terminal_data_plane_url"),
1719
+ // integer (NOT bigint): the lease-epoch spike proved a raw int8 read returns a
1720
+ // JS STRING from postgres-js, breaking the strict epoch-fence comparison (it
1721
+ // was always-true → every turn fenced); int4 returns a JS number, the fix.
1722
+ // Epochs never approach 2^31, so the narrower type loses nothing.
1723
+ leaseEpoch: integer("lease_epoch").notNull().default(0),
1724
+ // The group box-envelope (the "envelope split" Critical): the small recovery
1725
+ // descriptor to resume()-by-id the group's box without a per-session join.
1726
+ resumeBackendId: text("resume_backend_id"),
1727
+ resumeState: jsonb("resume_state").$type(),
1728
+ // Warm-time billing cursor: last_meter_at = accrual cursor; last_meter_tick =
1729
+ // idempotency tick (warm_seconds accrued idempotent on
1730
+ // (sandbox_group_id, lease_epoch, last_meter_tick) in P2.1).
1731
+ lastMeterAt: timestamp("last_meter_at", { withTimezone: true }),
1732
+ lastMeterTick: integer("last_meter_tick").notNull().default(0),
1733
+ expiresAt: timestamp("expires_at", { withTimezone: true }).notNull(),
1734
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
1735
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
1736
+ },
1737
+ (table) => ({
1738
+ groupIdx: uniqueIndex("sandbox_leases_group_idx").on(table.workspaceId, table.sandboxGroupId),
1739
+ reaperIdx: index("sandbox_leases_reaper_idx").on(table.expiresAt).where(sql`${table.liveness} in ('warming','warm','draining')`)
1740
+ })
1741
+ );
1742
+ var sandboxLeaseHolders = pgTable(
1743
+ "sandbox_lease_holders",
1744
+ {
1745
+ id: uuid("id").primaryKey().defaultRandom(),
1746
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
1747
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
1748
+ leaseId: uuid("lease_id").notNull().references(() => sandboxLeases.id, { onDelete: "cascade" }),
1749
+ kind: text("kind", { enum: ["turn", "viewer"] }).notNull(),
1750
+ holderId: text("holder_id").notNull(),
1751
+ // The attributing session within the (possibly shared) group.
1752
+ subjectId: uuid("subject_id"),
1753
+ lastHeartbeatAt: timestamp("last_heartbeat_at", { withTimezone: true }).notNull().defaultNow(),
1754
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow()
1755
+ },
1756
+ (table) => ({
1757
+ holderIdx: uniqueIndex("sandbox_lease_holders_holder_idx").on(
1758
+ table.leaseId,
1759
+ table.kind,
1760
+ table.holderId
1761
+ ),
1762
+ staleIdx: index("sandbox_lease_holders_stale_idx").on(table.kind, table.lastHeartbeatAt),
1763
+ leaseIdx: index("sandbox_lease_holders_lease_idx").on(table.leaseId)
1764
+ })
1765
+ );
1766
+ var sessionRecordingStateValues = [
1767
+ "recording",
1768
+ "finalizing",
1769
+ "available",
1770
+ "failed"
1771
+ ];
1772
+ var sessionRecordingModeValues = ["manual", "on-turn", "on-verify"];
1773
+ var sessionRecordingCodecValues = ["h264-mp4", "vp9-webm"];
1774
+ var sessionRecordings = pgTable(
1775
+ "session_recordings",
1776
+ {
1777
+ id: uuid("id").primaryKey().defaultRandom(),
1778
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
1779
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
1780
+ sessionId: uuid("session_id").notNull().references(() => sessions.id, { onDelete: "cascade" }),
1781
+ turnId: uuid("turn_id").references(() => sessionTurns.id, { onDelete: "set null" }),
1782
+ state: text("state", { enum: sessionRecordingStateValues }).notNull(),
1783
+ mode: text("mode", { enum: sessionRecordingModeValues }).notNull(),
1784
+ codec: text("codec", { enum: sessionRecordingCodecValues }).notNull(),
1785
+ storageKey: text("storage_key"),
1786
+ sizeBytes: bigint("size_bytes", { mode: "number" }),
1787
+ durationSeconds: numeric("duration_seconds").$type(),
1788
+ width: integer("width").notNull(),
1789
+ height: integer("height").notNull(),
1790
+ reason: text("reason"),
1791
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
1792
+ finalizedAt: timestamp("finalized_at", { withTimezone: true })
1793
+ },
1794
+ (table) => ({
1795
+ sessionIdx: index("session_recordings_session_idx").on(
1796
+ table.workspaceId,
1797
+ table.sessionId,
1798
+ table.createdAt
1799
+ )
1800
+ })
1801
+ );
1802
+ var workspaceCaptures = pgTable(
1803
+ "workspace_captures",
1804
+ {
1805
+ id: uuid("id").primaryKey().defaultRandom(),
1806
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
1807
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
1808
+ sessionId: uuid("session_id").notNull().references(() => sessions.id, { onDelete: "cascade" }),
1809
+ turnId: uuid("turn_id").references(() => sessionTurns.id, { onDelete: "set null" }),
1810
+ revision: bigint("revision", { mode: "number" }).notNull(),
1811
+ leaseEpoch: integer("lease_epoch").notNull(),
1812
+ // 'available' on a committed capture. 'failed' reserved for a future two-phase
1813
+ // write; the current synchronous capture only ever inserts 'available'.
1814
+ state: text("state", { enum: ["available", "failed"] }).notNull().default("available"),
1815
+ // Single JSON manifest blob (tree index + repos + file refs) — the cold-paint payload.
1816
+ manifestKey: text("manifest_key"),
1817
+ // The fs tree index blob, kept separate from the manifest so the API can inline
1818
+ // or sign it independently of the (usually small) manifest metadata.
1819
+ treeIndexKey: text("tree_index_key"),
1820
+ // Content-addressed after-image blob keys this revision references (GC input).
1821
+ blobKeys: jsonb("blob_keys").$type().notNull().default([]),
1822
+ sizeBytes: bigint("size_bytes", { mode: "number" }),
1823
+ stats: jsonb("stats").$type().notNull().default({}),
1824
+ capturedAt: timestamp("captured_at", { withTimezone: true }).notNull().defaultNow()
1825
+ },
1826
+ (table) => ({
1827
+ sessionRevision: uniqueIndex("workspace_captures_session_revision_idx").on(
1828
+ table.sessionId,
1829
+ table.revision
1830
+ ),
1831
+ latest: index("workspace_captures_latest_idx").on(
1832
+ table.workspaceId,
1833
+ table.sessionId,
1834
+ table.revision
1835
+ )
1836
+ })
1837
+ );
1838
+ var sandboxPtySessions = pgTable(
1839
+ "sandbox_pty_sessions",
1840
+ {
1841
+ id: uuid("id").primaryKey().defaultRandom(),
1842
+ // == ptyId on the wire
1843
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
1844
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
1845
+ sessionId: uuid("session_id").notNull().references(() => sessions.id, { onDelete: "cascade" }),
1846
+ // The SDK numeric exec-session id used by writeStdin({ sessionId }). Null until
1847
+ // the open exec yields a still-running process (a fast-exiting shell has none).
1848
+ execSessionId: integer("exec_session_id"),
1849
+ leaseEpoch: integer("lease_epoch").notNull(),
1850
+ // fenced to the box that opened it
1851
+ cols: integer("cols").notNull(),
1852
+ rows: integer("rows").notNull(),
1853
+ shell: text("shell").notNull(),
1854
+ cwd: text("cwd").notNull(),
1855
+ status: text("status").notNull().default("open"),
1856
+ // 'open' | 'closed'
1857
+ // The viewer grant/subject that opened it (free-text — access subjects are not
1858
+ // always UUIDs, M5; so a text column, never a uuid NOT NULL).
1859
+ openedBy: text("opened_by").notNull(),
1860
+ lastInputAt: timestamp("last_input_at", { withTimezone: true }).notNull().defaultNow(),
1861
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
1862
+ closedAt: timestamp("closed_at", { withTimezone: true })
1863
+ },
1864
+ (table) => ({
1865
+ openIdx: index("sandbox_pty_sessions_session_idx").on(table.workspaceId, table.sessionId).where(sql`${table.status} = 'open'`)
1866
+ })
1867
+ );
1868
+ var enrollmentExposureValues = ["whole-machine"];
1869
+ var enrollmentStatusValues = ["active", "revoked"];
1870
+ var enrollmentOsValues = ["linux", "macos", "windows"];
1871
+ var sandboxKindValues = ["modal", "selfhosted"];
1872
+ var enrollments = pgTable(
1873
+ "enrollments",
1874
+ {
1875
+ id: uuid("id").primaryKey().defaultRandom(),
1876
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
1877
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
1878
+ // The agent's ed25519 public key (the machine identity).
1879
+ pubkey: text("pubkey").notNull(),
1880
+ exposure: text("exposure", { enum: enrollmentExposureValues }).notNull().default("whole-machine"),
1881
+ hasDisplay: boolean("has_display").notNull().default(false),
1882
+ // Refreshed from every connect Hello (Capabilities.op_stream); false for
1883
+ // agents predating the op-stream engine.
1884
+ opStream: boolean("op_stream").notNull().default(false),
1885
+ // When the machine has a display it CANNOT capture (macOS Screen Recording / TCC
1886
+ // not granted), the agent reports has_display=false AND a human, actionable reason
1887
+ // here (e.g. "grant Screen Recording in System Settings"). NULL means capture is
1888
+ // permitted (has_display=true) or the machine is genuinely headless — the reason
1889
+ // distinguishes "display present but capture not granted" from plain "no display"
1890
+ // so the Machines dashboard / VM picker can surface the specific hint. Refreshed
1891
+ // from every connect Hello alongside has_display.
1892
+ desktopUnavailableReason: text("desktop_unavailable_reason"),
1893
+ allowScreenControl: boolean("allow_screen_control").notNull().default(false),
1894
+ status: text("status", { enum: enrollmentStatusValues }).notNull().default("active"),
1895
+ os: text("os", { enum: enrollmentOsValues }).notNull().default("linux"),
1896
+ arch: text("arch").notNull().default("x86_64"),
1897
+ // Heartbeat liveness cursor. Null until the first connect.
1898
+ lastSeenAt: timestamp("last_seen_at", { withTimezone: true }),
1899
+ // Clean going-offline marker (migration 0049). Set when the machine announces a
1900
+ // typed GoingOffline (user-stop / self-update / host-shutdown); the liveness
1901
+ // derivation reads an un-cleared marker as OFFLINE immediately, regardless of a
1902
+ // still-fresh last_seen. Any newer liveness signal (a reconnect Hello or a
1903
+ // fresher heartbeat via touchEnrollmentLastSeen) clears BOTH back to NULL. NULL
1904
+ // (the default) ⇒ no goodbye pending — today's last_seen-aging behavior.
1905
+ wentOfflineAt: timestamp("went_offline_at", { withTimezone: true }),
1906
+ wentOfflineReason: text("went_offline_reason"),
1907
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
1908
+ revokedAt: timestamp("revoked_at", { withTimezone: true }),
1909
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
1910
+ },
1911
+ (table) => ({
1912
+ // One enrollment per (workspace, pubkey): a re-enroll is an idempotent upsert.
1913
+ workspacePubkey: uniqueIndex("enrollments_workspace_pubkey_idx").on(
1914
+ table.workspaceId,
1915
+ table.pubkey
1916
+ ),
1917
+ // List a workspace's ACTIVE machines without scanning revoked rows.
1918
+ workspaceStatus: index("enrollments_workspace_status_idx").on(table.workspaceId, table.status)
1919
+ })
1920
+ );
1921
+ var deviceEnrollmentStatusValues = ["pending", "approved", "denied", "consumed"];
1922
+ var deviceEnrollmentRequests = pgTable(
1923
+ "device_enrollment_requests",
1924
+ {
1925
+ id: uuid("id").primaryKey().defaultRandom(),
1926
+ // The opaque code the agent polls with (unguessable, single-use). Unique.
1927
+ deviceCode: text("device_code").notNull(),
1928
+ // The short human-typed code (e.g. "WDJB-MJHT"). Unique among LIVE (pending)
1929
+ // rows via a partial unique index so a recycled code never collides with a
1930
+ // terminal row.
1931
+ userCode: text("user_code").notNull(),
1932
+ // The workspace this request was started for (resolved from the deployment-edge
1933
+ // request context — the agent presents the access key, the flow binds to the
1934
+ // single managed workspace OR a workspace hint). account_id rides along for RLS.
1935
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
1936
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
1937
+ // The agent's ed25519 public key (the machine identity the enrollment binds to).
1938
+ pubkey: text("pubkey").notNull(),
1939
+ os: text("os", { enum: enrollmentOsValues }).notNull().default("linux"),
1940
+ arch: text("arch").notNull().default("x86_64"),
1941
+ machineName: text("machine_name"),
1942
+ // The exposure the agent REQUESTED (whole-machine in v1; loudly consented at
1943
+ // approve). Mirrors the enrollment column domain.
1944
+ requestedExposure: text("requested_exposure", { enum: enrollmentExposureValues }).notNull().default("whole-machine"),
1945
+ // The agent CAN offer a display (a real screen / Xvfb is available) — gates
1946
+ // whether screen-control consent is even meaningful. has_display on the
1947
+ // resulting enrollment is derived from this.
1948
+ canOfferDisplay: boolean("can_offer_display").notNull().default(false),
1949
+ // The agent REQUESTS screen control (computer-use). The user's allow_screen_control
1950
+ // at approve is the AUTHORITATIVE consent; this is only the agent's request.
1951
+ requestsScreenControl: boolean("requests_screen_control").notNull().default(false),
1952
+ status: text("status", { enum: deviceEnrollmentStatusValues }).notNull().default("pending"),
1953
+ // ── LOUD CONSENT capture (who/when/what), stamped at approve ──────────────
1954
+ approvedBySubjectId: text("approved_by_subject_id"),
1955
+ approvedBySubjectLabel: text("approved_by_subject_label"),
1956
+ // The user's screen-control consent decision (whole-machine is mandatory at
1957
+ // approve; screen-control is opt-in per this flag).
1958
+ allowScreenControl: boolean("allow_screen_control").notNull().default(false),
1959
+ approvedAt: timestamp("approved_at", { withTimezone: true }),
1960
+ // The enrollment + sandbox the approve produced (acceptance #2: an enrollment
1961
+ // row AND a sandbox row appear). Null until approved.
1962
+ enrollmentId: uuid("enrollment_id").references(() => enrollments.id, { onDelete: "set null" }),
1963
+ sandboxId: uuid("sandbox_id").references(() => sandboxes.id, { onDelete: "set null" }),
1964
+ // The short-TTL expiry; a pending row past this is EXPIRED on poll.
1965
+ expiresAt: timestamp("expires_at", { withTimezone: true }).notNull(),
1966
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
1967
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
1968
+ },
1969
+ (table) => ({
1970
+ // The device_code is the agent's poll key — globally unique + indexed.
1971
+ deviceCode: uniqueIndex("device_enrollment_requests_device_code_idx").on(table.deviceCode),
1972
+ // The user_code must be unique among LIVE (pending) rows so the approve lookup
1973
+ // is unambiguous; a terminal row's code may be recycled.
1974
+ userCodePending: uniqueIndex("device_enrollment_requests_user_code_pending_idx").on(table.userCode).where(sql`${table.status} = 'pending'`),
1975
+ workspaceCreated: index("device_enrollment_requests_workspace_created_idx").on(
1976
+ table.workspaceId,
1977
+ table.createdAt
1978
+ ),
1979
+ expires: index("device_enrollment_requests_expires_idx").on(table.expiresAt)
1980
+ })
1981
+ );
1982
+ var sandboxes = pgTable(
1983
+ "sandboxes",
1984
+ {
1985
+ id: uuid("id").primaryKey().defaultRandom(),
1986
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
1987
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
1988
+ kind: text("kind", { enum: sandboxKindValues }).notNull(),
1989
+ name: text("name").notNull(),
1990
+ enrollmentId: uuid("enrollment_id").references(() => enrollments.id, { onDelete: "set null" }),
1991
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
1992
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
1993
+ },
1994
+ (table) => ({
1995
+ workspaceCreated: index("sandboxes_workspace_created_idx").on(
1996
+ table.workspaceId,
1997
+ table.createdAt
1998
+ ),
1999
+ enrollment: index("sandboxes_enrollment_idx").on(table.enrollmentId).where(sql`${table.enrollmentId} is not null`)
2000
+ })
2001
+ );
2002
+ var machineMetricsLatest = pgTable(
2003
+ "machine_metrics_latest",
2004
+ {
2005
+ enrollmentId: uuid("enrollment_id").primaryKey().references(() => enrollments.id, { onDelete: "cascade" }),
2006
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
2007
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
2008
+ cpuPercent: numeric("cpu_percent").$type(),
2009
+ load1: numeric("load1").$type(),
2010
+ load5: numeric("load5").$type(),
2011
+ load15: numeric("load15").$type(),
2012
+ memUsedBytes: bigint("mem_used_bytes", { mode: "number" }),
2013
+ memTotalBytes: bigint("mem_total_bytes", { mode: "number" }),
2014
+ diskUsedBytes: bigint("disk_used_bytes", { mode: "number" }),
2015
+ diskTotalBytes: bigint("disk_total_bytes", { mode: "number" }),
2016
+ gpuUtilPercent: numeric("gpu_util_percent").$type(),
2017
+ gpuMemUsedBytes: bigint("gpu_mem_used_bytes", { mode: "number" }),
2018
+ gpuMemTotalBytes: bigint("gpu_mem_total_bytes", { mode: "number" }),
2019
+ contention: numeric("contention").$type(),
2020
+ sampledAt: timestamp("sampled_at", { withTimezone: true }).notNull(),
2021
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
2022
+ },
2023
+ (table) => ({
2024
+ workspace: index("machine_metrics_latest_workspace_idx").on(table.workspaceId)
2025
+ })
2026
+ );
2027
+ var machineMetricsSeries = pgTable(
2028
+ "machine_metrics_series",
2029
+ {
2030
+ id: uuid("id").primaryKey().defaultRandom(),
2031
+ enrollmentId: uuid("enrollment_id").notNull().references(() => enrollments.id, { onDelete: "cascade" }),
2032
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
2033
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
2034
+ cpuPercent: numeric("cpu_percent").$type(),
2035
+ load1: numeric("load1").$type(),
2036
+ load5: numeric("load5").$type(),
2037
+ load15: numeric("load15").$type(),
2038
+ memUsedBytes: bigint("mem_used_bytes", { mode: "number" }),
2039
+ memTotalBytes: bigint("mem_total_bytes", { mode: "number" }),
2040
+ diskUsedBytes: bigint("disk_used_bytes", { mode: "number" }),
2041
+ diskTotalBytes: bigint("disk_total_bytes", { mode: "number" }),
2042
+ gpuUtilPercent: numeric("gpu_util_percent").$type(),
2043
+ gpuMemUsedBytes: bigint("gpu_mem_used_bytes", { mode: "number" }),
2044
+ gpuMemTotalBytes: bigint("gpu_mem_total_bytes", { mode: "number" }),
2045
+ contention: numeric("contention").$type(),
2046
+ sampledAt: timestamp("sampled_at", { withTimezone: true }).notNull(),
2047
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow()
2048
+ },
2049
+ (table) => ({
2050
+ enrollmentSampled: index("machine_metrics_series_enrollment_sampled_idx").on(
2051
+ table.enrollmentId,
2052
+ table.sampledAt
2053
+ ),
2054
+ sampled: index("machine_metrics_series_sampled_idx").on(table.sampledAt)
2055
+ })
2056
+ );
2057
+ var scheduledTasks = pgTable(
2058
+ "scheduled_tasks",
2059
+ {
2060
+ id: uuid("id").primaryKey().defaultRandom(),
2061
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
2062
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
2063
+ name: text("name").notNull(),
2064
+ status: text("status").notNull().default("active"),
2065
+ schedule: jsonb("schedule").$type().notNull(),
2066
+ temporalScheduleId: text("temporal_schedule_id").notNull(),
2067
+ runMode: text("run_mode").notNull().default("new_session_per_run"),
2068
+ overlapPolicy: text("overlap_policy").notNull().default("allow_concurrent"),
2069
+ agentConfig: jsonb("agent_config").$type().notNull(),
2070
+ reusableSessionId: uuid("reusable_session_id").references(() => sessions.id, {
2071
+ onDelete: "set null"
2072
+ }),
2073
+ variableSetId: uuid("variable_set_id").references(() => workspaceVariableSets.id, {
2074
+ onDelete: "restrict"
2075
+ }),
2076
+ // The rig this task's runs ride; the active version is resolved per fire
2077
+ // (migration 0047). NULL ⇒ no rig. FK (-> rigs(id) ON DELETE SET NULL) lives
2078
+ // in migration 0047 (forward-reference pattern). Consumed in M3.
2079
+ rigId: uuid("rig_id"),
2080
+ metadata: jsonb("metadata").$type().notNull().default({}),
2081
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
2082
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
2083
+ },
2084
+ (table) => ({
2085
+ temporalScheduleId: uniqueIndex("scheduled_tasks_workspace_temporal_schedule_id_idx").on(
2086
+ table.workspaceId,
2087
+ table.temporalScheduleId
2088
+ ),
2089
+ status: index("scheduled_tasks_workspace_status_idx").on(table.workspaceId, table.status),
2090
+ variableSet: index("scheduled_tasks_variable_set_idx").on(
2091
+ table.workspaceId,
2092
+ table.variableSetId
2093
+ )
2094
+ })
2095
+ );
2096
+ var scheduledTaskRuns = pgTable(
2097
+ "scheduled_task_runs",
2098
+ {
2099
+ id: uuid("id").primaryKey().defaultRandom(),
2100
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
2101
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
2102
+ taskId: uuid("task_id").notNull().references(() => scheduledTasks.id, { onDelete: "cascade" }),
2103
+ status: text("status").notNull().default("queued"),
2104
+ triggerType: text("trigger_type").notNull(),
2105
+ scheduledAt: timestamp("scheduled_at", { withTimezone: true }),
2106
+ firedAt: timestamp("fired_at", { withTimezone: true }).notNull().defaultNow(),
2107
+ sessionId: uuid("session_id").references(() => sessions.id, { onDelete: "set null" }),
2108
+ triggerEventId: uuid("trigger_event_id"),
2109
+ // Stable Temporal producer identity. Activity replay/re-dispatch returns
2110
+ // the exact run instead of allocating a second schedule source row.
2111
+ producerKey: text("producer_key"),
2112
+ error: text("error"),
2113
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
2114
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
2115
+ },
2116
+ (table) => ({
2117
+ taskCreated: index("scheduled_task_runs_workspace_task_created_idx").on(
2118
+ table.workspaceId,
2119
+ table.taskId,
2120
+ table.createdAt
2121
+ ),
2122
+ session: index("scheduled_task_runs_workspace_session_idx").on(
2123
+ table.workspaceId,
2124
+ table.sessionId
2125
+ ),
2126
+ producer: uniqueIndex("scheduled_task_runs_producer_key_uq").on(table.workspaceId, table.producerKey).where(sql`${table.producerKey} is not null`)
2127
+ })
2128
+ );
2129
+ var githubInstallations = pgTable(
2130
+ "github_installations",
2131
+ {
2132
+ id: uuid("id").primaryKey().defaultRandom(),
2133
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
2134
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
2135
+ installationId: integer("installation_id").notNull(),
2136
+ accountLogin: text("account_login"),
2137
+ accountType: text("account_type"),
2138
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
2139
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
2140
+ },
2141
+ (table) => ({
2142
+ workspaceInstallation: uniqueIndex("github_installations_workspace_installation_idx").on(
2143
+ table.workspaceId,
2144
+ table.installationId
2145
+ ),
2146
+ installation: index("github_installations_installation_idx").on(table.installationId),
2147
+ workspace: index("github_installations_workspace_idx").on(table.workspaceId)
2148
+ })
2149
+ );
2150
+ var usageEvents = pgTable(
2151
+ "usage_events",
2152
+ {
2153
+ id: uuid("id").primaryKey().defaultRandom(),
2154
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
2155
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
2156
+ subjectId: text("subject_id"),
2157
+ eventType: text("event_type").notNull(),
2158
+ quantity: bigint("quantity", { mode: "number" }).notNull(),
2159
+ unit: text("unit").notNull(),
2160
+ sourceResourceType: text("source_resource_type"),
2161
+ sourceResourceId: text("source_resource_id"),
2162
+ idempotencyKey: text("idempotency_key").notNull(),
2163
+ occurredAt: timestamp("occurred_at", { withTimezone: true }).notNull(),
2164
+ recordedAt: timestamp("recorded_at", { withTimezone: true }).notNull().defaultNow(),
2165
+ exportedToBillingAt: timestamp("exported_to_billing_at", { withTimezone: true }),
2166
+ billingProviderEventId: text("billing_provider_event_id")
2167
+ },
2168
+ (table) => ({
2169
+ idempotency: uniqueIndex("usage_events_idempotency_idx").on(table.idempotencyKey),
2170
+ workspaceMetric: index("usage_events_workspace_metric_idx").on(
2171
+ table.workspaceId,
2172
+ table.eventType,
2173
+ table.occurredAt
2174
+ ),
2175
+ accountMetric: index("usage_events_account_metric_idx").on(
2176
+ table.accountId,
2177
+ table.eventType,
2178
+ table.occurredAt
2179
+ )
2180
+ })
2181
+ );
2182
+ var creditLedgerEntries = pgTable(
2183
+ "credit_ledger_entries",
2184
+ {
2185
+ id: uuid("id").primaryKey().defaultRandom(),
2186
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
2187
+ workspaceId: uuid("workspace_id").references(() => workspaces.id, { onDelete: "set null" }),
2188
+ type: text("type").notNull(),
2189
+ amountMicros: bigint("amount_micros", { mode: "number" }).notNull(),
2190
+ currency: text("currency").notNull().default("usd"),
2191
+ sourceType: text("source_type"),
2192
+ sourceId: text("source_id"),
2193
+ idempotencyKey: text("idempotency_key").notNull(),
2194
+ metadata: jsonb("metadata").$type().notNull().default({}),
2195
+ occurredAt: timestamp("occurred_at", { withTimezone: true }).notNull().defaultNow(),
2196
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow()
2197
+ },
2198
+ (table) => ({
2199
+ idempotency: uniqueIndex("credit_ledger_entries_idempotency_idx").on(table.idempotencyKey),
2200
+ accountCreated: index("credit_ledger_entries_account_created_idx").on(
2201
+ table.accountId,
2202
+ table.createdAt
2203
+ )
2204
+ })
2205
+ );
2206
+ var billingCustomers = pgTable(
2207
+ "billing_customers",
2208
+ {
2209
+ id: uuid("id").primaryKey().defaultRandom(),
2210
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
2211
+ provider: text("provider").notNull().default("stripe"),
2212
+ providerCustomerId: text("provider_customer_id").notNull(),
2213
+ email: text("email"),
2214
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
2215
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
2216
+ },
2217
+ (table) => ({
2218
+ accountProvider: uniqueIndex("billing_customers_account_provider_idx").on(
2219
+ table.accountId,
2220
+ table.provider
2221
+ ),
2222
+ providerCustomer: uniqueIndex("billing_customers_provider_customer_idx").on(
2223
+ table.provider,
2224
+ table.providerCustomerId
2225
+ )
2226
+ })
2227
+ );
2228
+ var stripeWebhookEvents = pgTable("stripe_webhook_events", {
2229
+ id: text("id").primaryKey(),
2230
+ type: text("type").notNull(),
2231
+ livemode: text("livemode").notNull().default("false"),
2232
+ payload: jsonb("payload").$type().notNull(),
2233
+ processedAt: timestamp("processed_at", { withTimezone: true }),
2234
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow()
2235
+ });
2236
+ var auditEvents = pgTable(
2237
+ "audit_events",
2238
+ {
2239
+ id: uuid("id").primaryKey().defaultRandom(),
2240
+ accountId: uuid("account_id").references(() => managedAccounts.id, { onDelete: "set null" }),
2241
+ workspaceId: uuid("workspace_id").references(() => workspaces.id, { onDelete: "set null" }),
2242
+ subjectId: text("subject_id"),
2243
+ action: text("action").notNull(),
2244
+ targetType: text("target_type"),
2245
+ targetId: text("target_id"),
2246
+ metadata: jsonb("metadata").$type().notNull().default({}),
2247
+ occurredAt: timestamp("occurred_at", { withTimezone: true }).notNull().defaultNow()
2248
+ },
2249
+ (table) => ({
2250
+ accountCreated: index("audit_events_account_created_idx").on(table.accountId, table.occurredAt),
2251
+ workspaceCreated: index("audit_events_workspace_created_idx").on(
2252
+ table.workspaceId,
2253
+ table.occurredAt
2254
+ )
2255
+ })
2256
+ );
2257
+ var packInstallations = pgTable(
2258
+ "pack_installations",
2259
+ {
2260
+ id: uuid("id").primaryKey().defaultRandom(),
2261
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
2262
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
2263
+ packId: text("pack_id").notNull(),
2264
+ status: text("status").notNull().default("active"),
2265
+ metadata: jsonb("metadata").$type().notNull().default({}),
2266
+ enabledAt: timestamp("enabled_at", { withTimezone: true }).notNull().defaultNow(),
2267
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
2268
+ },
2269
+ (table) => ({
2270
+ workspacePack: uniqueIndex("pack_installations_workspace_pack_idx").on(
2271
+ table.workspaceId,
2272
+ table.packId
2273
+ ),
2274
+ status: index("pack_installations_workspace_status_idx").on(table.workspaceId, table.status)
2275
+ })
2276
+ );
2277
+ var workspacePacks = pgTable(
2278
+ "workspace_packs",
2279
+ {
2280
+ id: uuid("id").primaryKey().defaultRandom(),
2281
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
2282
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
2283
+ packId: text("pack_id").notNull(),
2284
+ manifest: jsonb("manifest").$type().notNull(),
2285
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
2286
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
2287
+ },
2288
+ (table) => ({
2289
+ workspacePack: uniqueIndex("workspace_packs_workspace_pack_idx").on(
2290
+ table.workspaceId,
2291
+ table.packId
2292
+ )
2293
+ })
2294
+ );
2295
+ var importBatches = pgTable(
2296
+ "import_batches",
2297
+ {
2298
+ id: uuid("id").primaryKey().defaultRandom(),
2299
+ source: text("source").notNull(),
2300
+ snapshotDate: timestamp("snapshot_date", { withTimezone: true }).notNull(),
2301
+ snapshotRef: text("snapshot_ref"),
2302
+ attributionNote: text("attribution_note").notNull(),
2303
+ importedCount: integer("imported_count").notNull().default(0),
2304
+ skippedCount: integer("skipped_count").notNull().default(0),
2305
+ quarantinedCount: integer("quarantined_count").notNull().default(0),
2306
+ logoFailureCount: integer("logo_failure_count").notNull().default(0),
2307
+ staleCount: integer("stale_count").notNull().default(0),
2308
+ details: jsonb("details").$type().notNull().default({}),
2309
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
2310
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
2311
+ },
2312
+ (table) => ({
2313
+ sourceSnapshot: index("import_batches_source_snapshot_idx").on(
2314
+ table.source,
2315
+ table.snapshotDate
2316
+ ),
2317
+ createdAt: index("import_batches_created_at_idx").on(table.createdAt)
2318
+ })
2319
+ );
2320
+ var capabilityCatalogItems = pgTable(
2321
+ "capability_catalog_items",
2322
+ {
2323
+ id: text("id").notNull(),
2324
+ accountId: uuid("account_id").references(() => managedAccounts.id, { onDelete: "cascade" }),
2325
+ workspaceId: uuid("workspace_id").references(() => workspaces.id, { onDelete: "cascade" }),
2326
+ kind: text("kind").notNull(),
2327
+ source: text("source").notNull().default("manual"),
2328
+ name: text("name").notNull(),
2329
+ description: text("description"),
2330
+ category: text("category").notNull().default("custom"),
2331
+ tags: jsonb("tags").$type().notNull().default([]),
2332
+ homepageUrl: text("homepage_url"),
2333
+ endpointUrl: text("endpoint_url"),
2334
+ installUrl: text("install_url"),
2335
+ authModel: text("auth_model"),
2336
+ providerDomain: text("provider_domain"),
2337
+ surfaceType: text("surface_type"),
2338
+ transport: text("transport"),
2339
+ mcpUrl: text("mcp_url"),
2340
+ authKind: text("auth_kind"),
2341
+ credentialFacts: jsonb("credential_facts").$type().notNull().default([]),
2342
+ tier: text("tier"),
2343
+ provenance: text("provenance"),
2344
+ logoAssetPath: text("logo_asset_path"),
2345
+ importBatchId: uuid("import_batch_id").references(() => importBatches.id, {
2346
+ onDelete: "set null"
2347
+ }),
2348
+ stale: boolean("stale").notNull().default(false),
2349
+ staleAt: timestamp("stale_at", { withTimezone: true }),
2350
+ metadata: jsonb("metadata").$type().notNull().default({}),
2351
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
2352
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
2353
+ },
2354
+ (table) => ({
2355
+ workspaceCapability: uniqueIndex("capability_catalog_items_workspace_capability_idx").on(
2356
+ table.workspaceId,
2357
+ table.id
2358
+ ),
2359
+ registrySurface: uniqueIndex("capability_catalog_items_registry_surface_idx").on(
2360
+ table.source,
2361
+ table.providerDomain,
2362
+ table.mcpUrl
2363
+ ),
2364
+ globalCapability: uniqueIndex("capability_catalog_items_global_capability_idx").on(table.id).where(sql`${table.workspaceId} is null`),
2365
+ kind: index("capability_catalog_items_workspace_kind_idx").on(table.workspaceId, table.kind),
2366
+ category: index("capability_catalog_items_workspace_category_idx").on(
2367
+ table.workspaceId,
2368
+ table.category
2369
+ ),
2370
+ source: index("capability_catalog_items_workspace_source_idx").on(
2371
+ table.workspaceId,
2372
+ table.source
2373
+ ),
2374
+ providerDomain: index("capability_catalog_items_provider_domain_idx").on(table.providerDomain),
2375
+ importBatch: index("capability_catalog_items_import_batch_idx").on(table.importBatchId),
2376
+ stale: index("capability_catalog_items_source_stale_idx").on(table.source, table.stale)
2377
+ })
2378
+ );
2379
+ var capabilityInstallations = pgTable(
2380
+ "capability_installations",
2381
+ {
2382
+ id: uuid("id").primaryKey().defaultRandom(),
2383
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
2384
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
2385
+ capabilityId: text("capability_id").notNull(),
2386
+ kind: text("kind").notNull(),
2387
+ status: text("status").notNull().default("active"),
2388
+ config: jsonb("config").$type().notNull().default({}),
2389
+ metadata: jsonb("metadata").$type().notNull().default({}),
2390
+ enabledAt: timestamp("enabled_at", { withTimezone: true }).notNull().defaultNow(),
2391
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
2392
+ },
2393
+ (table) => ({
2394
+ workspaceCapability: uniqueIndex("capability_installations_workspace_capability_idx").on(
2395
+ table.workspaceId,
2396
+ table.capabilityId
2397
+ ),
2398
+ kind: index("capability_installations_workspace_kind_idx").on(table.workspaceId, table.kind),
2399
+ status: index("capability_installations_workspace_status_idx").on(
2400
+ table.workspaceId,
2401
+ table.status
2402
+ )
2403
+ })
2404
+ );
2405
+ var socialConnections = pgTable(
2406
+ "social_connections",
2407
+ {
2408
+ id: uuid("id").primaryKey().defaultRandom(),
2409
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
2410
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
2411
+ provider: text("provider").notNull(),
2412
+ accountHandle: text("account_handle").notNull(),
2413
+ accountName: text("account_name"),
2414
+ externalAccountId: text("external_account_id"),
2415
+ status: text("status").notNull().default("connected"),
2416
+ scopes: jsonb("scopes").$type().notNull().default([]),
2417
+ credentialRef: text("credential_ref"),
2418
+ tokenMetadata: jsonb("token_metadata").$type().notNull().default({}),
2419
+ metadata: jsonb("metadata").$type().notNull().default({}),
2420
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
2421
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
2422
+ },
2423
+ (table) => ({
2424
+ workspaceProviderHandle: uniqueIndex("social_connections_workspace_provider_handle_idx").on(
2425
+ table.workspaceId,
2426
+ table.provider,
2427
+ table.accountHandle
2428
+ ),
2429
+ providerStatus: index("social_connections_workspace_provider_status_idx").on(
2430
+ table.workspaceId,
2431
+ table.provider,
2432
+ table.status
2433
+ )
2434
+ })
2435
+ );
2436
+ var socialPosts = pgTable(
2437
+ "social_posts",
2438
+ {
2439
+ id: uuid("id").primaryKey().defaultRandom(),
2440
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
2441
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
2442
+ connectionId: uuid("connection_id").notNull().references(() => socialConnections.id, { onDelete: "cascade" }),
2443
+ provider: text("provider").notNull(),
2444
+ externalPostId: text("external_post_id"),
2445
+ url: text("url"),
2446
+ authorHandle: text("author_handle"),
2447
+ text: text("text").notNull(),
2448
+ publishedAt: timestamp("published_at", { withTimezone: true }).notNull(),
2449
+ metrics: jsonb("metrics").$type().notNull().default({}),
2450
+ raw: jsonb("raw").$type().notNull().default({}),
2451
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow()
2452
+ },
2453
+ (table) => ({
2454
+ connectionExternalPost: uniqueIndex("social_posts_workspace_connection_external_post_idx").on(
2455
+ table.workspaceId,
2456
+ table.connectionId,
2457
+ table.externalPostId
2458
+ ),
2459
+ connectionPublished: index("social_posts_workspace_connection_published_idx").on(
2460
+ table.workspaceId,
2461
+ table.connectionId,
2462
+ table.publishedAt
2463
+ ),
2464
+ providerPublished: index("social_posts_workspace_provider_published_idx").on(
2465
+ table.workspaceId,
2466
+ table.provider,
2467
+ table.publishedAt
2468
+ )
2469
+ })
2470
+ );
2471
+ var rigs = pgTable(
2472
+ "rigs",
2473
+ {
2474
+ id: uuid("id").primaryKey().defaultRandom(),
2475
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
2476
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
2477
+ name: text("name").notNull(),
2478
+ description: text("description"),
2479
+ // Attribution string: 'user:<subject>' | 'session:<id>' | 'system'.
2480
+ createdBy: text("created_by"),
2481
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
2482
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
2483
+ },
2484
+ (table) => ({
2485
+ workspaceName: uniqueIndex("rigs_workspace_name_idx").on(table.workspaceId, table.name),
2486
+ workspaceCreated: index("rigs_workspace_created_idx").on(table.workspaceId, table.createdAt)
2487
+ })
2488
+ );
2489
+ var rigVersions = pgTable(
2490
+ "rig_versions",
2491
+ {
2492
+ id: uuid("id").primaryKey().defaultRandom(),
2493
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
2494
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
2495
+ rigId: uuid("rig_id").notNull().references(() => rigs.id, { onDelete: "cascade" }),
2496
+ version: integer("version").notNull(),
2497
+ image: text("image"),
2498
+ setupScript: text("setup_script"),
2499
+ // Self-declared health checks: [{ name, command }].
2500
+ checks: jsonb("checks").$type().notNull().default([]),
2501
+ // Registered credential-hook names (resolved to hook implementations in M3).
2502
+ credentialHooks: jsonb("credential_hooks").$type().notNull().default([]),
2503
+ // Variable-set ids layered below the session's variable set at run time (M3).
2504
+ defaultVariableSetIds: jsonb("default_variable_set_ids").$type().notNull().default([]),
2505
+ changelog: text("changelog"),
2506
+ createdBy: text("created_by"),
2507
+ active: boolean("active").notNull().default(false),
2508
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow()
2509
+ },
2510
+ (table) => ({
2511
+ rigVersion: uniqueIndex("rig_versions_rig_version_idx").on(table.rigId, table.version),
2512
+ // At most one active version per rig — the single-active invariant, in the DB.
2513
+ rigActive: uniqueIndex("rig_versions_rig_active_idx").on(table.rigId).where(sql`${table.active}`),
2514
+ workspaceRig: index("rig_versions_workspace_rig_idx").on(
2515
+ table.workspaceId,
2516
+ table.rigId,
2517
+ table.version
2518
+ )
2519
+ })
2520
+ );
2521
+ var rigChanges = pgTable(
2522
+ "rig_changes",
2523
+ {
2524
+ id: uuid("id").primaryKey().defaultRandom(),
2525
+ accountId: uuid("account_id").notNull().references(() => managedAccounts.id, { onDelete: "cascade" }),
2526
+ workspaceId: uuid("workspace_id").notNull().references(() => workspaces.id, { onDelete: "cascade" }),
2527
+ rigId: uuid("rig_id").notNull().references(() => rigs.id, { onDelete: "cascade" }),
2528
+ baseVersionId: uuid("base_version_id").references(() => rigVersions.id, {
2529
+ onDelete: "set null"
2530
+ }),
2531
+ // 'setup_append' | 'definition_edit' (CHECK in migration 0047).
2532
+ kind: text("kind").notNull(),
2533
+ payload: jsonb("payload").$type().notNull(),
2534
+ // 'proposed' | 'verifying' | 'merged' | 'rejected' | 'failed' (CHECK in 0047).
2535
+ status: text("status").notNull().default("proposed"),
2536
+ proposedBy: text("proposed_by"),
2537
+ verification: jsonb("verification").$type(),
2538
+ resultVersionId: uuid("result_version_id").references(() => rigVersions.id, {
2539
+ onDelete: "set null"
2540
+ }),
2541
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
2542
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
2543
+ },
2544
+ (table) => ({
2545
+ workspaceRig: index("rig_changes_workspace_rig_idx").on(
2546
+ table.workspaceId,
2547
+ table.rigId,
2548
+ table.createdAt
2549
+ ),
2550
+ workspaceStatus: index("rig_changes_workspace_status_idx").on(table.workspaceId, table.status)
2551
+ })
2552
+ );
2553
+
2554
+ export {
2555
+ managedAccounts,
2556
+ workspaces,
2557
+ workspaceInferenceControls,
2558
+ workspaceMemberships,
2559
+ apiKeys,
2560
+ workspaceVariableSets,
2561
+ workspaceVariableSetVariables,
2562
+ codexSubscriptionCredentials,
2563
+ connections,
2564
+ integrationOauthClients,
2565
+ integrationOauthStateNonces,
2566
+ codexRotationSettings,
2567
+ workspaceModelPolicies,
2568
+ codexCredentialLeases,
2569
+ sessions,
2570
+ sessionPins,
2571
+ sessionListSnapshots,
2572
+ sessionMcpServers,
2573
+ files,
2574
+ fileUploads,
2575
+ documentBases,
2576
+ documents,
2577
+ documentChunks,
2578
+ knowledgeMemories,
2579
+ sessionTurns,
2580
+ sessionTurnAttempts,
2581
+ sessionCommandReceipts,
2582
+ workspaceControlEvents,
2583
+ sessionAttemptInterruptions,
2584
+ composerDrafts,
2585
+ sessionSystemUpdates,
2586
+ sessionSystemUpdateOutbox,
2587
+ sessionWorkflowWakeOutbox,
2588
+ sessionGoals,
2589
+ codexCapacityWaiters,
2590
+ sessionEvents,
2591
+ agentRunStates,
2592
+ sessionHistoryItems,
2593
+ sessionPendingToolCalls,
2594
+ sandboxSessionEnvelopes,
2595
+ sandboxLeaseLivenessValues,
2596
+ sandboxLeases,
2597
+ sandboxLeaseHolders,
2598
+ sessionRecordingStateValues,
2599
+ sessionRecordingModeValues,
2600
+ sessionRecordingCodecValues,
2601
+ sessionRecordings,
2602
+ workspaceCaptures,
2603
+ sandboxPtySessions,
2604
+ enrollmentExposureValues,
2605
+ enrollmentStatusValues,
2606
+ enrollmentOsValues,
2607
+ sandboxKindValues,
2608
+ enrollments,
2609
+ deviceEnrollmentStatusValues,
2610
+ deviceEnrollmentRequests,
2611
+ sandboxes,
2612
+ machineMetricsLatest,
2613
+ machineMetricsSeries,
2614
+ scheduledTasks,
2615
+ scheduledTaskRuns,
2616
+ githubInstallations,
2617
+ usageEvents,
2618
+ creditLedgerEntries,
2619
+ billingCustomers,
2620
+ stripeWebhookEvents,
2621
+ auditEvents,
2622
+ packInstallations,
2623
+ workspacePacks,
2624
+ importBatches,
2625
+ capabilityCatalogItems,
2626
+ capabilityInstallations,
2627
+ socialConnections,
2628
+ socialPosts,
2629
+ rigs,
2630
+ rigVersions,
2631
+ rigChanges,
2632
+ schema_exports
2633
+ };
2634
+ //# sourceMappingURL=chunk-B22X3IEZ.js.map