@opengeni/db 0.14.3 → 0.17.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.
- package/dist/{chunk-Y5WZZVQK.js → chunk-SK7YYHBI.js} +5 -2
- package/dist/chunk-SK7YYHBI.js.map +1 -0
- package/dist/{chunk-ELMUCYZF.js → chunk-T6RSJT6C.js} +202 -43
- package/dist/chunk-T6RSJT6C.js.map +1 -0
- package/dist/chunk-TLAC622R.js +4990 -0
- package/dist/chunk-TLAC622R.js.map +1 -0
- package/dist/codex-token-resolver.d.ts +64 -0
- package/dist/connection-token-resolver.d.ts +90 -0
- package/dist/environment-crypto.d.ts +11 -0
- package/dist/event-payload-sanitizer.d.ts +32 -0
- package/dist/index.d.ts +6374 -10
- package/dist/index.js +8075 -2776
- package/dist/index.js.map +1 -1
- package/dist/insights.d.ts +157 -0
- package/dist/memory-domain.d.ts +44 -0
- package/dist/migrate.d.ts +5 -7
- package/dist/migrate.js +1 -1
- package/dist/new-session-drafts.d.ts +49 -0
- package/dist/persistence-errors.d.ts +69 -0
- package/dist/preference-registry-schema.d.ts +1147 -0
- package/dist/preference-registry.d.ts +878 -0
- package/dist/provision-roles.d.ts +4 -6489
- package/dist/provision-roles.js +1 -1
- package/dist/role-relationships.d.ts +35 -0
- package/dist/runtime-posture-cli.d.ts +1 -0
- package/dist/runtime-posture.d.ts +103 -0
- package/dist/schema.d.ts +25330 -3
- package/dist/schema.js +31 -1
- package/dist/session-control.d.ts +331 -0
- package/dist/session-queue-commands.d.ts +186 -0
- package/dist/session-tool-call-settlement.d.ts +32 -0
- package/dist/turn-initiator.d.ts +28 -0
- package/dist/workspace-artifacts.d.ts +62 -0
- package/dist/workspace-instruction-policies-schema.d.ts +735 -0
- package/dist/workspace-instruction-policies.d.ts +64 -0
- package/drizzle/0136_unified_session_tool_policy.sql +1 -1
- package/drizzle/0137_preference_registry.sql +1347 -0
- package/drizzle/0138_sandbox_checkpoint_artifacts_and_deadlines.sql +1074 -0
- package/drizzle/0139_codex_provider_artifact_invalidations.sql +51 -0
- package/drizzle/0140_sandbox_restore_and_reaper_fences.sql +276 -0
- package/drizzle/0142_sandbox_archive_capture_gate.sql +80 -0
- package/drizzle/0143_session_codex_compaction_mode.sql +20 -0
- package/drizzle/0144_sandbox_viewer_force_drain_gate.sql +95 -0
- package/drizzle/0145_model_call_facts.sql +96 -0
- package/drizzle/0146_slack_bot_delete_idempotency.sql +105 -0
- package/drizzle/0147_draft_latency_mode.sql +12 -0
- package/drizzle/0148_session_turn_latency_mode.sql +12 -0
- package/drizzle/0149_workspace_artifacts.sql +348 -0
- package/drizzle/0150_slack_task_interactions.sql +344 -0
- package/package.json +6 -6
- package/src/index.ts +5766 -275
- package/src/insights.ts +837 -0
- package/src/migrate.ts +9 -1
- package/src/new-session-drafts.ts +4 -0
- package/src/preference-registry-schema.ts +170 -0
- package/src/preference-registry.ts +1220 -0
- package/src/provision-roles.ts +95 -22
- package/src/role-relationships.ts +132 -0
- package/src/runtime-posture.ts +47 -27
- package/src/schema.ts +875 -19
- package/src/session-queue-commands.ts +39 -6
- package/src/workspace-artifacts.ts +751 -0
- package/dist/chunk-DW24CKCT.js +0 -4046
- package/dist/chunk-DW24CKCT.js.map +0 -1
- package/dist/chunk-ELMUCYZF.js.map +0 -1
- package/dist/chunk-Y5WZZVQK.js.map +0 -1
- package/dist/schema-DhkRhcuQ.d.ts +0 -22666
package/src/schema.ts
CHANGED
|
@@ -73,6 +73,17 @@ export const workspaces = pgTable(
|
|
|
73
73
|
// .references(), because `rigs` is declared later in this file (same
|
|
74
74
|
// forward-reference pattern as sessions.activeSandboxId). Consumed in M3.
|
|
75
75
|
defaultRigId: uuid("default_rig_id"),
|
|
76
|
+
// Workspace-wide viewer admission intent set by the warm-meter reaper when
|
|
77
|
+
// managed credits or the monthly warm allowance are exhausted. It is
|
|
78
|
+
// deliberately independent of a lease so a dashboard cannot re-arm a
|
|
79
|
+
// draining box or spawn a cold successor before a fresh limit evaluation
|
|
80
|
+
// clears the gate.
|
|
81
|
+
sandboxViewerForceDrainReason: text("sandbox_viewer_force_drain_reason", {
|
|
82
|
+
enum: ["balance", "warm_cap"],
|
|
83
|
+
}),
|
|
84
|
+
sandboxViewerForceDrainRequestedAt: timestamp("sandbox_viewer_force_drain_requested_at", {
|
|
85
|
+
withTimezone: true,
|
|
86
|
+
}),
|
|
76
87
|
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
77
88
|
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
|
|
78
89
|
},
|
|
@@ -82,6 +93,182 @@ export const workspaces = pgTable(
|
|
|
82
93
|
.on(table.accountId, table.slug)
|
|
83
94
|
.where(sql`${table.slug} is not null`),
|
|
84
95
|
external: uniqueIndex("workspaces_external_idx").on(table.externalSource, table.externalId),
|
|
96
|
+
sandboxViewerForceDrain: index("workspaces_sandbox_viewer_force_drain_idx")
|
|
97
|
+
.on(table.id)
|
|
98
|
+
.where(sql`${table.sandboxViewerForceDrainReason} is not null`),
|
|
99
|
+
sandboxViewerForceDrainValid: check(
|
|
100
|
+
"workspaces_sandbox_viewer_force_drain_check",
|
|
101
|
+
sql`(
|
|
102
|
+
${table.sandboxViewerForceDrainReason} is null
|
|
103
|
+
and ${table.sandboxViewerForceDrainRequestedAt} is null
|
|
104
|
+
) or (
|
|
105
|
+
${table.sandboxViewerForceDrainReason} in ('balance', 'warm_cap')
|
|
106
|
+
and ${table.sandboxViewerForceDrainRequestedAt} is not null
|
|
107
|
+
)`,
|
|
108
|
+
),
|
|
109
|
+
}),
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
// A single generic workspace-published surface. Presentation labels such as
|
|
113
|
+
// app, page, gallery, or document are intentionally not persisted as types.
|
|
114
|
+
export const workspaceArtifacts = pgTable(
|
|
115
|
+
"workspace_artifacts",
|
|
116
|
+
{
|
|
117
|
+
id: uuid("id").primaryKey().defaultRandom(),
|
|
118
|
+
accountId: uuid("account_id")
|
|
119
|
+
.notNull()
|
|
120
|
+
.references(() => managedAccounts.id, { onDelete: "cascade" }),
|
|
121
|
+
workspaceId: uuid("workspace_id")
|
|
122
|
+
.notNull()
|
|
123
|
+
.references(() => workspaces.id, { onDelete: "cascade" }),
|
|
124
|
+
slug: text("slug").notNull(),
|
|
125
|
+
title: text("title").notNull(),
|
|
126
|
+
description: text("description"),
|
|
127
|
+
status: text("status").$type<"active" | "archived">().notNull().default("active"),
|
|
128
|
+
// The FK to workspace_artifact_versions is installed by migration after
|
|
129
|
+
// that table exists. Keeping this pointer here makes reads inexpensive.
|
|
130
|
+
currentVersionId: uuid("current_version_id"),
|
|
131
|
+
createdBySubjectId: text("created_by_subject_id").notNull(),
|
|
132
|
+
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
133
|
+
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
|
|
134
|
+
},
|
|
135
|
+
(table) => ({
|
|
136
|
+
workspaceAccount: foreignKey({
|
|
137
|
+
name: "workspace_artifacts_workspace_account_fk",
|
|
138
|
+
columns: [table.workspaceId, table.accountId],
|
|
139
|
+
foreignColumns: [workspaces.id, workspaces.accountId],
|
|
140
|
+
}).onDelete("cascade"),
|
|
141
|
+
workspaceSlug: uniqueIndex("workspace_artifacts_workspace_slug_uq").on(
|
|
142
|
+
table.workspaceId,
|
|
143
|
+
table.slug,
|
|
144
|
+
),
|
|
145
|
+
workspaceId: uniqueIndex("workspace_artifacts_workspace_id_uq").on(table.workspaceId, table.id),
|
|
146
|
+
list: index("workspace_artifacts_list_idx").on(table.workspaceId, table.updatedAt),
|
|
147
|
+
}),
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
export const workspaceArtifactVersions = pgTable(
|
|
151
|
+
"workspace_artifact_versions",
|
|
152
|
+
{
|
|
153
|
+
id: uuid("id").primaryKey().defaultRandom(),
|
|
154
|
+
accountId: uuid("account_id")
|
|
155
|
+
.notNull()
|
|
156
|
+
.references(() => managedAccounts.id, { onDelete: "cascade" }),
|
|
157
|
+
workspaceId: uuid("workspace_id")
|
|
158
|
+
.notNull()
|
|
159
|
+
.references(() => workspaces.id, { onDelete: "cascade" }),
|
|
160
|
+
artifactId: uuid("artifact_id").notNull(),
|
|
161
|
+
revision: integer("revision").notNull(),
|
|
162
|
+
contentKey: text("content_key").notNull(),
|
|
163
|
+
contentType: text("content_type").$type<"text/html">().notNull().default("text/html"),
|
|
164
|
+
contentSha256: text("content_sha256").notNull(),
|
|
165
|
+
sizeBytes: integer("size_bytes").notNull(),
|
|
166
|
+
operationKey: text("operation_key").notNull(),
|
|
167
|
+
sourceSessionId: uuid("source_session_id"),
|
|
168
|
+
sourceTurnId: uuid("source_turn_id"),
|
|
169
|
+
sourceAttemptId: uuid("source_attempt_id"),
|
|
170
|
+
sourceExecutionGeneration: integer("source_execution_generation"),
|
|
171
|
+
createdBySubjectId: text("created_by_subject_id").notNull(),
|
|
172
|
+
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
173
|
+
},
|
|
174
|
+
(table) => ({
|
|
175
|
+
workspaceAccount: foreignKey({
|
|
176
|
+
name: "workspace_artifact_versions_workspace_account_fk",
|
|
177
|
+
columns: [table.workspaceId, table.accountId],
|
|
178
|
+
foreignColumns: [workspaces.id, workspaces.accountId],
|
|
179
|
+
}).onDelete("cascade"),
|
|
180
|
+
artifact: foreignKey({
|
|
181
|
+
name: "workspace_artifact_versions_artifact_fk",
|
|
182
|
+
columns: [table.workspaceId, table.artifactId],
|
|
183
|
+
foreignColumns: [workspaceArtifacts.workspaceId, workspaceArtifacts.id],
|
|
184
|
+
}).onDelete("cascade"),
|
|
185
|
+
workspaceId: uniqueIndex("workspace_artifact_versions_workspace_id_uq").on(
|
|
186
|
+
table.workspaceId,
|
|
187
|
+
table.id,
|
|
188
|
+
),
|
|
189
|
+
revision: uniqueIndex("workspace_artifact_versions_revision_uq").on(
|
|
190
|
+
table.workspaceId,
|
|
191
|
+
table.artifactId,
|
|
192
|
+
table.revision,
|
|
193
|
+
),
|
|
194
|
+
operation: uniqueIndex("workspace_artifact_versions_operation_uq").on(
|
|
195
|
+
table.workspaceId,
|
|
196
|
+
table.operationKey,
|
|
197
|
+
),
|
|
198
|
+
provenance: check(
|
|
199
|
+
"workspace_artifact_versions_provenance_chk",
|
|
200
|
+
sql`(
|
|
201
|
+
${table.sourceSessionId} is null
|
|
202
|
+
and ${table.sourceTurnId} is null
|
|
203
|
+
and ${table.sourceAttemptId} is null
|
|
204
|
+
and ${table.sourceExecutionGeneration} is null
|
|
205
|
+
) or (
|
|
206
|
+
${table.sourceSessionId} is not null
|
|
207
|
+
and ${table.sourceTurnId} is not null
|
|
208
|
+
and ${table.sourceAttemptId} is not null
|
|
209
|
+
and ${table.sourceExecutionGeneration} > 0
|
|
210
|
+
)`,
|
|
211
|
+
),
|
|
212
|
+
}),
|
|
213
|
+
);
|
|
214
|
+
|
|
215
|
+
export const workspaceArtifactEvents = pgTable(
|
|
216
|
+
"workspace_artifact_events",
|
|
217
|
+
{
|
|
218
|
+
id: uuid("id").primaryKey().defaultRandom(),
|
|
219
|
+
accountId: uuid("account_id")
|
|
220
|
+
.notNull()
|
|
221
|
+
.references(() => managedAccounts.id, { onDelete: "cascade" }),
|
|
222
|
+
workspaceId: uuid("workspace_id")
|
|
223
|
+
.notNull()
|
|
224
|
+
.references(() => workspaces.id, { onDelete: "cascade" }),
|
|
225
|
+
artifactId: uuid("artifact_id").notNull(),
|
|
226
|
+
type: text("type").$type<"published" | "rolled_back">().notNull(),
|
|
227
|
+
fromVersionId: uuid("from_version_id"),
|
|
228
|
+
toVersionId: uuid("to_version_id").notNull(),
|
|
229
|
+
operationKey: text("operation_key").notNull(),
|
|
230
|
+
sourceSessionId: uuid("source_session_id"),
|
|
231
|
+
sourceTurnId: uuid("source_turn_id"),
|
|
232
|
+
sourceAttemptId: uuid("source_attempt_id"),
|
|
233
|
+
sourceExecutionGeneration: integer("source_execution_generation"),
|
|
234
|
+
actorSubjectId: text("actor_subject_id").notNull(),
|
|
235
|
+
reason: text("reason").notNull(),
|
|
236
|
+
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
237
|
+
},
|
|
238
|
+
(table) => ({
|
|
239
|
+
workspaceAccount: foreignKey({
|
|
240
|
+
name: "workspace_artifact_events_workspace_account_fk",
|
|
241
|
+
columns: [table.workspaceId, table.accountId],
|
|
242
|
+
foreignColumns: [workspaces.id, workspaces.accountId],
|
|
243
|
+
}).onDelete("cascade"),
|
|
244
|
+
artifact: foreignKey({
|
|
245
|
+
name: "workspace_artifact_events_artifact_fk",
|
|
246
|
+
columns: [table.workspaceId, table.artifactId],
|
|
247
|
+
foreignColumns: [workspaceArtifacts.workspaceId, workspaceArtifacts.id],
|
|
248
|
+
}).onDelete("cascade"),
|
|
249
|
+
operation: uniqueIndex("workspace_artifact_events_operation_uq").on(
|
|
250
|
+
table.workspaceId,
|
|
251
|
+
table.operationKey,
|
|
252
|
+
),
|
|
253
|
+
list: index("workspace_artifact_events_list_idx").on(
|
|
254
|
+
table.workspaceId,
|
|
255
|
+
table.artifactId,
|
|
256
|
+
table.createdAt,
|
|
257
|
+
),
|
|
258
|
+
provenance: check(
|
|
259
|
+
"workspace_artifact_events_provenance_chk",
|
|
260
|
+
sql`(
|
|
261
|
+
${table.sourceSessionId} is null
|
|
262
|
+
and ${table.sourceTurnId} is null
|
|
263
|
+
and ${table.sourceAttemptId} is null
|
|
264
|
+
and ${table.sourceExecutionGeneration} is null
|
|
265
|
+
) or (
|
|
266
|
+
${table.sourceSessionId} is not null
|
|
267
|
+
and ${table.sourceTurnId} is not null
|
|
268
|
+
and ${table.sourceAttemptId} is not null
|
|
269
|
+
and ${table.sourceExecutionGeneration} > 0
|
|
270
|
+
)`,
|
|
271
|
+
),
|
|
85
272
|
}),
|
|
86
273
|
);
|
|
87
274
|
|
|
@@ -357,12 +544,16 @@ export const codexSubscriptionCredentials = pgTable(
|
|
|
357
544
|
// continues to own `version`; quota/cache writes own neither counter.
|
|
358
545
|
allocatorVersion: integer("allocator_version").notNull().default(1),
|
|
359
546
|
allocatorUpdatedBySubjectId: text("allocator_updated_by_subject_id"),
|
|
360
|
-
allocatorUpdatedAt: timestamp("allocator_updated_at", {
|
|
547
|
+
allocatorUpdatedAt: timestamp("allocator_updated_at", {
|
|
548
|
+
withTimezone: true,
|
|
549
|
+
}),
|
|
361
550
|
// Authoritative count-only summary cached from /wham/usage. Detailed rows
|
|
362
551
|
// are never persisted as redemption authority; every first POST preflights
|
|
363
552
|
// the provider's fresh detail endpoint.
|
|
364
553
|
resetCreditAvailableCount: integer("reset_credit_available_count"),
|
|
365
|
-
resetCreditsCheckedAt: timestamp("reset_credits_checked_at", {
|
|
554
|
+
resetCreditsCheckedAt: timestamp("reset_credits_checked_at", {
|
|
555
|
+
withTimezone: true,
|
|
556
|
+
}),
|
|
366
557
|
// Set only by a direct Better Auth cookie connection/reconnection. Legacy,
|
|
367
558
|
// configured, delegated, API-key, and agent-created rows remain view-only.
|
|
368
559
|
connectedBySubjectId: text("connected_by_subject_id"),
|
|
@@ -412,7 +603,9 @@ export const codexResetRedemptionAttempts = pgTable(
|
|
|
412
603
|
outcome: text("outcome"),
|
|
413
604
|
claimHolderId: uuid("claim_holder_id"),
|
|
414
605
|
claimExpiresAt: timestamp("claim_expires_at", { withTimezone: true }),
|
|
415
|
-
confirmationExpiresAt: timestamp("confirmation_expires_at", {
|
|
606
|
+
confirmationExpiresAt: timestamp("confirmation_expires_at", {
|
|
607
|
+
withTimezone: true,
|
|
608
|
+
}).notNull(),
|
|
416
609
|
providerStartedAt: timestamp("provider_started_at", { withTimezone: true }),
|
|
417
610
|
completedAt: timestamp("completed_at", { withTimezone: true }),
|
|
418
611
|
lastFailureKind: text("last_failure_kind"),
|
|
@@ -520,6 +713,194 @@ export const connections = pgTable(
|
|
|
520
713
|
}),
|
|
521
714
|
);
|
|
522
715
|
|
|
716
|
+
export const slackBotUserLinks = pgTable(
|
|
717
|
+
"slack_bot_user_links",
|
|
718
|
+
{
|
|
719
|
+
id: uuid("id").primaryKey().defaultRandom(),
|
|
720
|
+
accountId: uuid("account_id")
|
|
721
|
+
.notNull()
|
|
722
|
+
.references(() => managedAccounts.id, { onDelete: "cascade" }),
|
|
723
|
+
workspaceId: uuid("workspace_id")
|
|
724
|
+
.notNull()
|
|
725
|
+
.references(() => workspaces.id, { onDelete: "cascade" }),
|
|
726
|
+
connectionId: uuid("connection_id")
|
|
727
|
+
.notNull()
|
|
728
|
+
.references(() => connections.id, { onDelete: "cascade" }),
|
|
729
|
+
slackTeamId: text("slack_team_id").notNull(),
|
|
730
|
+
slackUserId: text("slack_user_id").notNull(),
|
|
731
|
+
subjectId: text("subject_id").notNull(),
|
|
732
|
+
linkedBySubjectId: text("linked_by_subject_id").notNull(),
|
|
733
|
+
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
734
|
+
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
|
|
735
|
+
},
|
|
736
|
+
(table) => ({
|
|
737
|
+
connectionUser: uniqueIndex("slack_bot_user_links_connection_user_uq").on(
|
|
738
|
+
table.connectionId,
|
|
739
|
+
table.slackUserId,
|
|
740
|
+
),
|
|
741
|
+
workspaceSubject: index("slack_bot_user_links_workspace_subject_idx").on(
|
|
742
|
+
table.workspaceId,
|
|
743
|
+
table.subjectId,
|
|
744
|
+
),
|
|
745
|
+
}),
|
|
746
|
+
);
|
|
747
|
+
|
|
748
|
+
export const slackInteractionInbox = pgTable(
|
|
749
|
+
"slack_interaction_inbox",
|
|
750
|
+
{
|
|
751
|
+
id: uuid("id").primaryKey().defaultRandom(),
|
|
752
|
+
accountId: uuid("account_id")
|
|
753
|
+
.notNull()
|
|
754
|
+
.references(() => managedAccounts.id, { onDelete: "cascade" }),
|
|
755
|
+
workspaceId: uuid("workspace_id")
|
|
756
|
+
.notNull()
|
|
757
|
+
.references(() => workspaces.id, { onDelete: "cascade" }),
|
|
758
|
+
connectionId: uuid("connection_id")
|
|
759
|
+
.notNull()
|
|
760
|
+
.references(() => connections.id, { onDelete: "cascade" }),
|
|
761
|
+
providerEventId: text("provider_event_id").notNull(),
|
|
762
|
+
providerMessageId: text("provider_message_id").notNull(),
|
|
763
|
+
slackTeamId: text("slack_team_id").notNull(),
|
|
764
|
+
slackUserId: text("slack_user_id").notNull(),
|
|
765
|
+
slackChannelId: text("slack_channel_id").notNull(),
|
|
766
|
+
slackMessageTs: text("slack_message_ts").notNull(),
|
|
767
|
+
slackThreadTs: text("slack_thread_ts"),
|
|
768
|
+
triggerKind: text("trigger_kind")
|
|
769
|
+
.$type<"app_mention" | "dm" | "slash_command" | "message_shortcut" | "thread_reply">()
|
|
770
|
+
.notNull(),
|
|
771
|
+
text: text("text").notNull(),
|
|
772
|
+
status: text("status")
|
|
773
|
+
.$type<"pending" | "processing" | "processed" | "failed">()
|
|
774
|
+
.notNull()
|
|
775
|
+
.default("pending"),
|
|
776
|
+
claimHolderId: uuid("claim_holder_id"),
|
|
777
|
+
claimExpiresAt: timestamp("claim_expires_at", { withTimezone: true }),
|
|
778
|
+
attemptCount: integer("attempt_count").notNull().default(0),
|
|
779
|
+
lastErrorCode: text("last_error_code"),
|
|
780
|
+
processedAt: timestamp("processed_at", { withTimezone: true }),
|
|
781
|
+
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
782
|
+
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
|
|
783
|
+
},
|
|
784
|
+
(table) => ({
|
|
785
|
+
providerEvent: uniqueIndex("slack_interaction_inbox_provider_event_uq").on(
|
|
786
|
+
table.connectionId,
|
|
787
|
+
table.providerEventId,
|
|
788
|
+
),
|
|
789
|
+
providerMessage: uniqueIndex("slack_interaction_inbox_provider_message_uq").on(
|
|
790
|
+
table.connectionId,
|
|
791
|
+
table.providerMessageId,
|
|
792
|
+
),
|
|
793
|
+
pending: index("slack_interaction_inbox_pending_idx").on(
|
|
794
|
+
table.status,
|
|
795
|
+
table.createdAt,
|
|
796
|
+
table.id,
|
|
797
|
+
),
|
|
798
|
+
}),
|
|
799
|
+
);
|
|
800
|
+
|
|
801
|
+
export const slackInteractions = pgTable(
|
|
802
|
+
"slack_interactions",
|
|
803
|
+
{
|
|
804
|
+
id: uuid("id").primaryKey().defaultRandom(),
|
|
805
|
+
accountId: uuid("account_id")
|
|
806
|
+
.notNull()
|
|
807
|
+
.references(() => managedAccounts.id, { onDelete: "cascade" }),
|
|
808
|
+
workspaceId: uuid("workspace_id")
|
|
809
|
+
.notNull()
|
|
810
|
+
.references(() => workspaces.id, { onDelete: "cascade" }),
|
|
811
|
+
connectionId: uuid("connection_id")
|
|
812
|
+
.notNull()
|
|
813
|
+
.references(() => connections.id, { onDelete: "cascade" }),
|
|
814
|
+
slackTeamId: text("slack_team_id").notNull(),
|
|
815
|
+
slackChannelId: text("slack_channel_id").notNull(),
|
|
816
|
+
slackThreadTs: text("slack_thread_ts").notNull(),
|
|
817
|
+
routeKey: text("route_key").notNull(),
|
|
818
|
+
triggeringProviderEventId: text("triggering_provider_event_id").notNull(),
|
|
819
|
+
owningSubjectId: text("owning_subject_id").notNull(),
|
|
820
|
+
visibility: text("visibility").$type<"private" | "workspace">().notNull(),
|
|
821
|
+
sessionReservationId: uuid("session_reservation_id").notNull().defaultRandom(),
|
|
822
|
+
sessionId: uuid("session_id").references(() => sessions.id, {
|
|
823
|
+
onDelete: "cascade",
|
|
824
|
+
}),
|
|
825
|
+
lastDeliveredSessionEventSequence: integer("last_delivered_session_event_sequence")
|
|
826
|
+
.notNull()
|
|
827
|
+
.default(0),
|
|
828
|
+
deliveryClaimHolderId: uuid("delivery_claim_holder_id"),
|
|
829
|
+
deliveryClaimExpiresAt: timestamp("delivery_claim_expires_at", {
|
|
830
|
+
withTimezone: true,
|
|
831
|
+
}),
|
|
832
|
+
ackSlackMessageTs: text("ack_slack_message_ts"),
|
|
833
|
+
progressCount: integer("progress_count").notNull().default(0),
|
|
834
|
+
terminalDeliveryState: text("terminal_delivery_state")
|
|
835
|
+
.$type<"open" | "completed" | "failed" | "cancelled" | "blocked">()
|
|
836
|
+
.notNull()
|
|
837
|
+
.default("open"),
|
|
838
|
+
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
839
|
+
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
|
|
840
|
+
},
|
|
841
|
+
(table) => ({
|
|
842
|
+
route: uniqueIndex("slack_interactions_route_uq").on(table.connectionId, table.routeKey),
|
|
843
|
+
identity: uniqueIndex("slack_interactions_identity_uq").on(
|
|
844
|
+
table.accountId,
|
|
845
|
+
table.workspaceId,
|
|
846
|
+
table.id,
|
|
847
|
+
),
|
|
848
|
+
workspaceReservation: uniqueIndex("slack_interactions_workspace_reservation_uq").on(
|
|
849
|
+
table.workspaceId,
|
|
850
|
+
table.sessionReservationId,
|
|
851
|
+
),
|
|
852
|
+
workspaceSession: uniqueIndex("slack_interactions_workspace_session_uq")
|
|
853
|
+
.on(table.workspaceId, table.sessionId)
|
|
854
|
+
.where(sql`${table.sessionId} is not null`),
|
|
855
|
+
delivery: index("slack_interactions_delivery_idx").on(
|
|
856
|
+
table.terminalDeliveryState,
|
|
857
|
+
table.updatedAt,
|
|
858
|
+
table.id,
|
|
859
|
+
),
|
|
860
|
+
}),
|
|
861
|
+
);
|
|
862
|
+
|
|
863
|
+
export const slackInteractionProgressDeliveries = pgTable(
|
|
864
|
+
"slack_interaction_progress_deliveries",
|
|
865
|
+
{
|
|
866
|
+
id: uuid("id").primaryKey().defaultRandom(),
|
|
867
|
+
accountId: uuid("account_id")
|
|
868
|
+
.notNull()
|
|
869
|
+
.references(() => managedAccounts.id, { onDelete: "cascade" }),
|
|
870
|
+
workspaceId: uuid("workspace_id")
|
|
871
|
+
.notNull()
|
|
872
|
+
.references(() => workspaces.id, { onDelete: "cascade" }),
|
|
873
|
+
interactionId: uuid("interaction_id").notNull(),
|
|
874
|
+
sessionEventSequence: integer("session_event_sequence").notNull(),
|
|
875
|
+
slot: integer("slot").notNull(),
|
|
876
|
+
operationId: uuid("operation_id").notNull(),
|
|
877
|
+
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
878
|
+
},
|
|
879
|
+
(table) => ({
|
|
880
|
+
interactionIdentity: foreignKey({
|
|
881
|
+
columns: [table.accountId, table.workspaceId, table.interactionId],
|
|
882
|
+
foreignColumns: [
|
|
883
|
+
slackInteractions.accountId,
|
|
884
|
+
slackInteractions.workspaceId,
|
|
885
|
+
slackInteractions.id,
|
|
886
|
+
],
|
|
887
|
+
name: "slack_interaction_progress_deliveries_interaction_fk",
|
|
888
|
+
}).onDelete("cascade"),
|
|
889
|
+
event: uniqueIndex("slack_interaction_progress_deliveries_event_uq").on(
|
|
890
|
+
table.interactionId,
|
|
891
|
+
table.sessionEventSequence,
|
|
892
|
+
),
|
|
893
|
+
slot: uniqueIndex("slack_interaction_progress_deliveries_slot_uq").on(
|
|
894
|
+
table.interactionId,
|
|
895
|
+
table.slot,
|
|
896
|
+
),
|
|
897
|
+
operation: uniqueIndex("slack_interaction_progress_deliveries_operation_uq").on(
|
|
898
|
+
table.workspaceId,
|
|
899
|
+
table.operationId,
|
|
900
|
+
),
|
|
901
|
+
}),
|
|
902
|
+
);
|
|
903
|
+
|
|
523
904
|
// Durable provider-operation identity for OpenGeni Slack bot posts. The
|
|
524
905
|
// caller-supplied operation UUID is also Slack's client_msg_id; a bounded claim
|
|
525
906
|
// serializes live attempts while an expired/released claim can safely retry the
|
|
@@ -599,6 +980,90 @@ export const slackBotPostOperations = pgTable(
|
|
|
599
980
|
}),
|
|
600
981
|
);
|
|
601
982
|
|
|
983
|
+
// Durable provider-operation identity for OpenGeni Slack bot deletions. Slack
|
|
984
|
+
// has no client-supplied idempotency key for chat.delete, so an expired
|
|
985
|
+
// provider_started claim becomes outcome_unknown and must be reconciled before
|
|
986
|
+
// another mutation is admitted.
|
|
987
|
+
export const slackBotDeleteOperations = pgTable(
|
|
988
|
+
"slack_bot_delete_operations",
|
|
989
|
+
{
|
|
990
|
+
id: uuid("id").primaryKey().defaultRandom(),
|
|
991
|
+
accountId: uuid("account_id")
|
|
992
|
+
.notNull()
|
|
993
|
+
.references(() => managedAccounts.id, { onDelete: "cascade" }),
|
|
994
|
+
workspaceId: uuid("workspace_id")
|
|
995
|
+
.notNull()
|
|
996
|
+
.references(() => workspaces.id, { onDelete: "cascade" }),
|
|
997
|
+
connectionId: uuid("connection_id")
|
|
998
|
+
.notNull()
|
|
999
|
+
.references(() => connections.id, { onDelete: "cascade" }),
|
|
1000
|
+
operationId: uuid("operation_id").notNull(),
|
|
1001
|
+
principalType: text("principal_type").$type<"subject" | "service">().notNull(),
|
|
1002
|
+
principalId: text("principal_id").notNull(),
|
|
1003
|
+
toolName: text("tool_name").notNull(),
|
|
1004
|
+
channelId: text("channel_id").notNull(),
|
|
1005
|
+
messageTimestamp: text("message_timestamp").notNull(),
|
|
1006
|
+
requestDigest: text("request_digest").notNull(),
|
|
1007
|
+
status: text("status")
|
|
1008
|
+
.$type<"pending" | "provider_started" | "outcome_unknown" | "completed">()
|
|
1009
|
+
.notNull(),
|
|
1010
|
+
claimHolderId: uuid("claim_holder_id"),
|
|
1011
|
+
claimExpiresAt: timestamp("claim_expires_at", { withTimezone: true }),
|
|
1012
|
+
attemptCount: integer("attempt_count").notNull().default(0),
|
|
1013
|
+
lastFailureCode: text("last_failure_code"),
|
|
1014
|
+
slackChannelId: text("slack_channel_id"),
|
|
1015
|
+
slackMessageTimestamp: text("slack_message_timestamp"),
|
|
1016
|
+
completedAt: timestamp("completed_at", { withTimezone: true }),
|
|
1017
|
+
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
1018
|
+
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
|
|
1019
|
+
},
|
|
1020
|
+
(table) => ({
|
|
1021
|
+
workspaceOperation: uniqueIndex("slack_bot_delete_operations_workspace_operation_uq").on(
|
|
1022
|
+
table.workspaceId,
|
|
1023
|
+
table.operationId,
|
|
1024
|
+
),
|
|
1025
|
+
workspaceStatus: index("slack_bot_delete_operations_workspace_status_idx").on(
|
|
1026
|
+
table.workspaceId,
|
|
1027
|
+
table.status,
|
|
1028
|
+
table.updatedAt,
|
|
1029
|
+
),
|
|
1030
|
+
principalValid: check(
|
|
1031
|
+
"slack_bot_delete_operations_principal_check",
|
|
1032
|
+
sql`${table.principalType} in ('subject', 'service')
|
|
1033
|
+
and length(${table.principalId}) between 1 and 512`,
|
|
1034
|
+
),
|
|
1035
|
+
identityValid: check(
|
|
1036
|
+
"slack_bot_delete_operations_identity_check",
|
|
1037
|
+
sql`${table.toolName} = 'slack_bot_delete_message'
|
|
1038
|
+
and length(${table.channelId}) between 1 and 64
|
|
1039
|
+
and length(${table.messageTimestamp}) between 1 and 64
|
|
1040
|
+
and ${table.requestDigest} ~ '^[0-9a-f]{64}$'
|
|
1041
|
+
and ${table.attemptCount} > 0
|
|
1042
|
+
and ((${table.claimHolderId} is null) = (${table.claimExpiresAt} is null))`,
|
|
1043
|
+
),
|
|
1044
|
+
statusValid: check(
|
|
1045
|
+
"slack_bot_delete_operations_status_check",
|
|
1046
|
+
sql`${table.status} in ('pending', 'provider_started', 'outcome_unknown', 'completed')`,
|
|
1047
|
+
),
|
|
1048
|
+
completionValid: check(
|
|
1049
|
+
"slack_bot_delete_operations_completion_check",
|
|
1050
|
+
sql`(
|
|
1051
|
+
${table.status} <> 'completed'
|
|
1052
|
+
and ${table.slackChannelId} is null
|
|
1053
|
+
and ${table.slackMessageTimestamp} is null
|
|
1054
|
+
and ${table.completedAt} is null
|
|
1055
|
+
) or (
|
|
1056
|
+
${table.status} = 'completed'
|
|
1057
|
+
and ${table.claimHolderId} is null
|
|
1058
|
+
and ${table.claimExpiresAt} is null
|
|
1059
|
+
and ${table.slackChannelId} is not null
|
|
1060
|
+
and ${table.slackMessageTimestamp} is not null
|
|
1061
|
+
and ${table.completedAt} is not null
|
|
1062
|
+
)`,
|
|
1063
|
+
),
|
|
1064
|
+
}),
|
|
1065
|
+
);
|
|
1066
|
+
|
|
602
1067
|
// OAuth client registrations minted through MCP DCR, keyed by authorization
|
|
603
1068
|
// server issuer. This is deployment-wide client identity, not a workspace
|
|
604
1069
|
// credential; per-user/provider tokens still live only in connections.
|
|
@@ -916,6 +1381,10 @@ export const sessions = pgTable(
|
|
|
916
1381
|
// (manual|policy) lives in the migration; no FK (it describes the pin, not an
|
|
917
1382
|
// account).
|
|
918
1383
|
codexPinSource: text("codex_pin_source"),
|
|
1384
|
+
// Frozen at create: remote_v2 (Codex remote compaction + Codex-only models)
|
|
1385
|
+
// or portable (plaintext compaction + free provider switching). Existing
|
|
1386
|
+
// rows backfill to portable. CHECK lives in the migration.
|
|
1387
|
+
codexCompactionMode: text("codex_compaction_mode").notNull().default("portable"),
|
|
919
1388
|
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
920
1389
|
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
|
|
921
1390
|
// Assigned by the database trigger whenever canonical updated_at activity
|
|
@@ -1473,6 +1942,8 @@ export const sessionTurns = pgTable(
|
|
|
1473
1942
|
toolsProvided: boolean("tools_provided").notNull().default(false),
|
|
1474
1943
|
model: text("model").notNull(),
|
|
1475
1944
|
reasoningEffort: text("reasoning_effort").notNull(),
|
|
1945
|
+
// Peer of model + reasoning_effort for Fast/priority inheritance.
|
|
1946
|
+
latencyMode: text("latency_mode").notNull().default("standard"),
|
|
1476
1947
|
sandboxBackend: text("sandbox_backend").notNull(),
|
|
1477
1948
|
// Per-turn OS override. NULL = inherit the session's sandbox_os. CHECK-
|
|
1478
1949
|
// constrained to the SandboxOs enum (or NULL) in migration 0018.
|
|
@@ -1519,6 +1990,10 @@ export const sessionTurns = pgTable(
|
|
|
1519
1990
|
oneCurrentInference: uniqueIndex("session_turns_one_current_inference_uq")
|
|
1520
1991
|
.on(table.workspaceId, table.sessionId)
|
|
1521
1992
|
.where(sql`${table.status} in ('running','requires_action','recovering','waiting_capacity')`),
|
|
1993
|
+
latencyModeValid: check(
|
|
1994
|
+
"session_turns_latency_mode_check",
|
|
1995
|
+
sql`${table.latencyMode} in ('standard', 'priority', 'fast')`,
|
|
1996
|
+
),
|
|
1522
1997
|
}),
|
|
1523
1998
|
);
|
|
1524
1999
|
|
|
@@ -1828,6 +2303,7 @@ export const composerDrafts = pgTable(
|
|
|
1828
2303
|
toolsProvided: boolean("tools_provided").notNull().default(false),
|
|
1829
2304
|
model: text("model").notNull(),
|
|
1830
2305
|
reasoningEffort: text("reasoning_effort").notNull(),
|
|
2306
|
+
latencyMode: text("latency_mode").notNull().default("standard"),
|
|
1831
2307
|
sourceTurnId: uuid("source_turn_id"),
|
|
1832
2308
|
sourceTurnVersion: integer("source_turn_version"),
|
|
1833
2309
|
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
@@ -1859,6 +2335,10 @@ export const composerDrafts = pgTable(
|
|
|
1859
2335
|
sql`length(btrim(${table.subjectId})) > 0`,
|
|
1860
2336
|
),
|
|
1861
2337
|
revisionValid: check("composer_drafts_revision_check", sql`${table.revision} >= 1`),
|
|
2338
|
+
latencyModeValid: check(
|
|
2339
|
+
"composer_drafts_latency_mode_check",
|
|
2340
|
+
sql`${table.latencyMode} in ('standard', 'priority', 'fast')`,
|
|
2341
|
+
),
|
|
1862
2342
|
}),
|
|
1863
2343
|
);
|
|
1864
2344
|
|
|
@@ -1877,6 +2357,7 @@ export const newSessionDrafts = pgTable(
|
|
|
1877
2357
|
tools: jsonb("tools").$type<unknown[]>().notNull().default([]),
|
|
1878
2358
|
model: text("model").notNull(),
|
|
1879
2359
|
reasoningEffort: text("reasoning_effort").notNull(),
|
|
2360
|
+
latencyMode: text("latency_mode").notNull().default("standard"),
|
|
1880
2361
|
sessionOptions: jsonb("session_options").$type<Record<string, unknown>>().notNull().default({}),
|
|
1881
2362
|
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
1882
2363
|
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
|
|
@@ -1896,6 +2377,10 @@ export const newSessionDrafts = pgTable(
|
|
|
1896
2377
|
sql`length(btrim(${table.subjectId})) > 0`,
|
|
1897
2378
|
),
|
|
1898
2379
|
revisionValid: check("new_session_drafts_revision_check", sql`${table.revision} >= 1`),
|
|
2380
|
+
latencyModeValid: check(
|
|
2381
|
+
"new_session_drafts_latency_mode_check",
|
|
2382
|
+
sql`${table.latencyMode} in ('standard', 'priority', 'fast')`,
|
|
2383
|
+
),
|
|
1899
2384
|
}),
|
|
1900
2385
|
);
|
|
1901
2386
|
|
|
@@ -2106,10 +2591,14 @@ export const sessionGoals = pgTable(
|
|
|
2106
2591
|
// update, timeline events, usage row, and workflow-wake outbox row.
|
|
2107
2592
|
// Temporal signals and workflow history are replaceable nudges over these
|
|
2108
2593
|
// monotonic revisions.
|
|
2109
|
-
continuationWakeRevision: bigint("continuation_wake_revision", {
|
|
2594
|
+
continuationWakeRevision: bigint("continuation_wake_revision", {
|
|
2595
|
+
mode: "number",
|
|
2596
|
+
})
|
|
2110
2597
|
.notNull()
|
|
2111
2598
|
.default(0),
|
|
2112
|
-
continuationObservedRevision: bigint("continuation_observed_revision", {
|
|
2599
|
+
continuationObservedRevision: bigint("continuation_observed_revision", {
|
|
2600
|
+
mode: "number",
|
|
2601
|
+
})
|
|
2113
2602
|
.notNull()
|
|
2114
2603
|
.default(0),
|
|
2115
2604
|
metadata: jsonb("metadata").$type<Record<string, unknown>>().notNull().default({}),
|
|
@@ -2322,6 +2811,14 @@ export const agentRunStates = pgTable("agent_run_states", {
|
|
|
2322
2811
|
// correct either way). NULL on both sides (non-codex freeze + non-codex
|
|
2323
2812
|
// resume) is a no-op, so single-account and non-codex sessions are unchanged.
|
|
2324
2813
|
frozenCodexCredentialId: uuid("frozen_codex_credential_id"),
|
|
2814
|
+
// Exact provider rejection invalidates only the opaque reasoning identity
|
|
2815
|
+
// inside this frozen state. The serialized receipt remains durable and
|
|
2816
|
+
// auditable; the resume path neutralizes its provider-bound identity.
|
|
2817
|
+
providerArtifactInvalidatedAt: timestamp("provider_artifact_invalidated_at", {
|
|
2818
|
+
withTimezone: true,
|
|
2819
|
+
}),
|
|
2820
|
+
providerArtifactInvalidationReason: text("provider_artifact_invalidation_reason"),
|
|
2821
|
+
providerArtifactInvalidatedByAttemptId: uuid("provider_artifact_invalidated_by_attempt_id"),
|
|
2325
2822
|
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
2326
2823
|
});
|
|
2327
2824
|
|
|
@@ -2451,6 +2948,16 @@ export const sessionHistoryItems = pgTable(
|
|
|
2451
2948
|
// (an ON DELETE SET NULL would erase the tag, and a stale-but-null tag still
|
|
2452
2949
|
// mismatches a live codex id so the strip stays correct either way).
|
|
2453
2950
|
producerCodexCredentialId: uuid("producer_codex_credential_id"),
|
|
2951
|
+
// An exact provider 400 can prove that an otherwise same-credential opaque
|
|
2952
|
+
// reasoning artifact is no longer decryptable. Keep the original item and
|
|
2953
|
+
// producer provenance immutable, but record the attempt-fenced rejection so
|
|
2954
|
+
// later model reads omit only the provider-bound identity. No FK: the receipt
|
|
2955
|
+
// must outlive operational attempt retention just like producer provenance.
|
|
2956
|
+
providerArtifactInvalidatedAt: timestamp("provider_artifact_invalidated_at", {
|
|
2957
|
+
withTimezone: true,
|
|
2958
|
+
}),
|
|
2959
|
+
providerArtifactInvalidationReason: text("provider_artifact_invalidation_reason"),
|
|
2960
|
+
providerArtifactInvalidatedByAttemptId: uuid("provider_artifact_invalidated_by_attempt_id"),
|
|
2454
2961
|
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
2455
2962
|
},
|
|
2456
2963
|
(table) => ({
|
|
@@ -2543,6 +3050,134 @@ export const sandboxSessionEnvelopes = pgTable(
|
|
|
2543
3050
|
}),
|
|
2544
3051
|
);
|
|
2545
3052
|
|
|
3053
|
+
export const sandboxCheckpointArtifactStateValues = [
|
|
3054
|
+
"candidate",
|
|
3055
|
+
"current",
|
|
3056
|
+
"previous",
|
|
3057
|
+
"delete_pending",
|
|
3058
|
+
"deleting",
|
|
3059
|
+
"delete_failed",
|
|
3060
|
+
"deleted",
|
|
3061
|
+
] as const;
|
|
3062
|
+
|
|
3063
|
+
/**
|
|
3064
|
+
* Durable ownership ledger for provider-native workspace checkpoints. These
|
|
3065
|
+
* rows intentionally have no cascading parent FK: a workspace/lease can vanish
|
|
3066
|
+
* before the provider object is deleted, and global GC still needs the exact
|
|
3067
|
+
* non-secret provider binding and object id after that deletion.
|
|
3068
|
+
*/
|
|
3069
|
+
export const sandboxCheckpointArtifacts = pgTable(
|
|
3070
|
+
"sandbox_checkpoint_artifacts",
|
|
3071
|
+
{
|
|
3072
|
+
id: uuid("id").primaryKey().defaultRandom(),
|
|
3073
|
+
accountId: uuid("account_id").notNull(),
|
|
3074
|
+
workspaceId: uuid("workspace_id").notNull(),
|
|
3075
|
+
sandboxGroupId: uuid("sandbox_group_id").notNull(),
|
|
3076
|
+
sourceLeaseId: uuid("source_lease_id").notNull(),
|
|
3077
|
+
sourceLeaseEpoch: integer("source_lease_epoch").notNull(),
|
|
3078
|
+
sourceInstanceId: text("source_instance_id"),
|
|
3079
|
+
sourceWorkspaceGeneration: integer("source_workspace_generation"),
|
|
3080
|
+
provenance: text("provenance", {
|
|
3081
|
+
enum: ["native_capture", "legacy_provider_adopted"],
|
|
3082
|
+
}).notNull(),
|
|
3083
|
+
providerBackend: text("provider_backend").notNull(),
|
|
3084
|
+
providerBindingKey: text("provider_binding_key").notNull(),
|
|
3085
|
+
providerBinding: jsonb("provider_binding").$type<Record<string, unknown>>().notNull(),
|
|
3086
|
+
objectKind: text("object_kind", {
|
|
3087
|
+
enum: ["modal_filesystem_snapshot", "modal_directory_snapshot"],
|
|
3088
|
+
}).notNull(),
|
|
3089
|
+
objectId: text("object_id").notNull(),
|
|
3090
|
+
archiveBase64: text("archive_base64").notNull(),
|
|
3091
|
+
archiveSha256: text("archive_sha256").notNull(),
|
|
3092
|
+
archiveBytes: integer("archive_bytes").notNull(),
|
|
3093
|
+
descriptor: jsonb("descriptor").$type<Record<string, unknown>>().notNull(),
|
|
3094
|
+
descriptorRevision: text("descriptor_revision").notNull(),
|
|
3095
|
+
state: text("state", { enum: sandboxCheckpointArtifactStateValues })
|
|
3096
|
+
.notNull()
|
|
3097
|
+
.default("candidate"),
|
|
3098
|
+
deleteAfter: timestamp("delete_after", { withTimezone: true }),
|
|
3099
|
+
deleteAttempts: integer("delete_attempts").notNull().default(0),
|
|
3100
|
+
deleteClaimId: uuid("delete_claim_id"),
|
|
3101
|
+
deleteClaimedAt: timestamp("delete_claimed_at", { withTimezone: true }),
|
|
3102
|
+
lastDeleteError: text("last_delete_error"),
|
|
3103
|
+
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
3104
|
+
publishedAt: timestamp("published_at", { withTimezone: true }),
|
|
3105
|
+
deletedAt: timestamp("deleted_at", { withTimezone: true }),
|
|
3106
|
+
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
|
|
3107
|
+
},
|
|
3108
|
+
(table) => ({
|
|
3109
|
+
providerObject: uniqueIndex("sandbox_checkpoint_artifacts_provider_object_uq").on(
|
|
3110
|
+
table.providerBackend,
|
|
3111
|
+
table.providerBindingKey,
|
|
3112
|
+
table.objectId,
|
|
3113
|
+
),
|
|
3114
|
+
gc: index("sandbox_checkpoint_artifacts_gc_idx")
|
|
3115
|
+
.on(table.deleteAfter, table.createdAt, table.id)
|
|
3116
|
+
.where(
|
|
3117
|
+
sql`${table.state} in (
|
|
3118
|
+
'candidate', 'current', 'previous',
|
|
3119
|
+
'delete_pending', 'delete_failed', 'deleting'
|
|
3120
|
+
)`,
|
|
3121
|
+
),
|
|
3122
|
+
source: index("sandbox_checkpoint_artifacts_source_idx").on(
|
|
3123
|
+
table.workspaceId,
|
|
3124
|
+
table.sandboxGroupId,
|
|
3125
|
+
table.sourceLeaseId,
|
|
3126
|
+
),
|
|
3127
|
+
sourceValid: check(
|
|
3128
|
+
"sandbox_checkpoint_artifacts_source_check",
|
|
3129
|
+
sql`${table.sourceLeaseEpoch} >= 0
|
|
3130
|
+
and (
|
|
3131
|
+
(
|
|
3132
|
+
${table.provenance} = 'native_capture'
|
|
3133
|
+
and ${table.sourceWorkspaceGeneration} is not null
|
|
3134
|
+
and ${table.sourceWorkspaceGeneration} >= 0
|
|
3135
|
+
and ${table.sourceInstanceId} is not null
|
|
3136
|
+
and octet_length(${table.sourceInstanceId}) between 1 and 512
|
|
3137
|
+
)
|
|
3138
|
+
or (
|
|
3139
|
+
${table.provenance} = 'legacy_provider_adopted'
|
|
3140
|
+
and ${table.sourceWorkspaceGeneration} is null
|
|
3141
|
+
and ${table.sourceInstanceId} is null
|
|
3142
|
+
)
|
|
3143
|
+
)`,
|
|
3144
|
+
),
|
|
3145
|
+
providerValid: check(
|
|
3146
|
+
"sandbox_checkpoint_artifacts_provider_check",
|
|
3147
|
+
sql`${table.providerBackend} = 'modal'
|
|
3148
|
+
and octet_length(${table.providerBindingKey}) between 1 and 1024
|
|
3149
|
+
and jsonb_typeof(${table.providerBinding}) = 'object'
|
|
3150
|
+
and ${table.providerBindingKey}::jsonb = ${table.providerBinding}
|
|
3151
|
+
and ${table.objectKind} in ('modal_filesystem_snapshot', 'modal_directory_snapshot')
|
|
3152
|
+
and octet_length(${table.objectId}) between 1 and 1024`,
|
|
3153
|
+
),
|
|
3154
|
+
archiveValid: check(
|
|
3155
|
+
"sandbox_checkpoint_artifacts_archive_check",
|
|
3156
|
+
sql`${table.archiveBytes} > 0
|
|
3157
|
+
and octet_length(${table.archiveBase64}) > 0
|
|
3158
|
+
and ${table.archiveSha256} ~ '^[0-9a-f]{64}$'
|
|
3159
|
+
and jsonb_typeof(${table.descriptor}) = 'object'
|
|
3160
|
+
and octet_length(${table.descriptorRevision}) between 1 and 256`,
|
|
3161
|
+
),
|
|
3162
|
+
stateValid: check(
|
|
3163
|
+
"sandbox_checkpoint_artifacts_state_check",
|
|
3164
|
+
sql`${table.state} in (
|
|
3165
|
+
'candidate', 'current', 'previous', 'delete_pending',
|
|
3166
|
+
'deleting', 'delete_failed', 'deleted'
|
|
3167
|
+
)`,
|
|
3168
|
+
),
|
|
3169
|
+
deleteClaimValid: check(
|
|
3170
|
+
"sandbox_checkpoint_artifacts_delete_claim_check",
|
|
3171
|
+
sql`(${table.state} = 'deleting'
|
|
3172
|
+
and ${table.deleteClaimId} is not null
|
|
3173
|
+
and ${table.deleteClaimedAt} is not null)
|
|
3174
|
+
or (${table.state} <> 'deleting'
|
|
3175
|
+
and ${table.deleteClaimId} is null
|
|
3176
|
+
and ${table.deleteClaimedAt} is null)`,
|
|
3177
|
+
),
|
|
3178
|
+
}),
|
|
3179
|
+
);
|
|
3180
|
+
|
|
2546
3181
|
// The 4 liveness states of the singleton lease. Exported so the query layer and
|
|
2547
3182
|
// the stateless resume-by-id path share one source of truth for the domain.
|
|
2548
3183
|
export const sandboxLeaseLivenessValues = ["cold", "warming", "warm", "draining"] as const;
|
|
@@ -2578,14 +3213,14 @@ export const sandboxLeases = pgTable(
|
|
|
2578
3213
|
// The container IMAGE the group box runs (Modal image ref / docker image). A shared
|
|
2579
3214
|
// box is SHARED STATE: all its sessions run the SAME filesystem, so they must run the
|
|
2580
3215
|
// same image. This column stamps the image the live box was created with; a resume
|
|
2581
|
-
// whose resolved image DIFFERS is a conflict (B3): a solo holder
|
|
2582
|
-
//
|
|
3216
|
+
// whose resolved image DIFFERS is a conflict (B3): a solo holder requests a
|
|
3217
|
+
// capture-and-drain rotation; N-holders are rejected (SandboxImageConflictError). Nullable — a
|
|
2583
3218
|
// legacy/cold row reads NULL = "image unknown", which never conflicts.
|
|
2584
3219
|
image: text("image"),
|
|
2585
3220
|
// The frozen rig version the live box was created under (M3). Like `image`,
|
|
2586
3221
|
// this is SHARED STATE: all the box's sessions run the same rig-baked setup,
|
|
2587
|
-
// so a resume resolving a DIFFERENT rig_version_id conflicts (solo holder
|
|
2588
|
-
//
|
|
3222
|
+
// so a resume resolving a DIFFERENT rig_version_id conflicts (a solo holder
|
|
3223
|
+
// requests capture-and-drain rotation; N-holders throw SandboxRigConflictError).
|
|
2589
3224
|
// Nullable — a legacy/cold row or a rig-less session reads NULL = "rig
|
|
2590
3225
|
// unknown", which never conflicts. No FK (symmetric with sandbox_group_id's
|
|
2591
3226
|
// bare-uuid rationale: this lease outlives no single rig_versions row's RLS).
|
|
@@ -2611,6 +3246,19 @@ export const sandboxLeases = pgTable(
|
|
|
2611
3246
|
// the same row update; equality is the only durable completeness proof.
|
|
2612
3247
|
workspaceGeneration: integer("workspace_generation").notNull().default(0),
|
|
2613
3248
|
archiveGeneration: integer("archive_generation"),
|
|
3249
|
+
// Provider-native capture may pause the live box. The exact claim is
|
|
3250
|
+
// acquired before provider I/O and cleared only after that capture settles;
|
|
3251
|
+
// new holders and workspace mutations fence on it. The SQL constraint also
|
|
3252
|
+
// requires the claimed generation to remain current, so an unaware writer
|
|
3253
|
+
// cannot advance generation through an active capture.
|
|
3254
|
+
archiveCaptureId: uuid("archive_capture_id"),
|
|
3255
|
+
archiveCaptureGeneration: integer("archive_capture_generation"),
|
|
3256
|
+
archiveCaptureStartedAt: timestamp("archive_capture_started_at", {
|
|
3257
|
+
withTimezone: true,
|
|
3258
|
+
}),
|
|
3259
|
+
archiveCaptureDeadlineAt: timestamp("archive_capture_deadline_at", {
|
|
3260
|
+
withTimezone: true,
|
|
3261
|
+
}),
|
|
2614
3262
|
|
|
2615
3263
|
// The group box-envelope (the "envelope split" Critical): the small recovery
|
|
2616
3264
|
// descriptor to resume()-by-id the group's box without a per-session join.
|
|
@@ -2623,6 +3271,22 @@ export const sandboxLeases = pgTable(
|
|
|
2623
3271
|
lastMeterAt: timestamp("last_meter_at", { withTimezone: true }),
|
|
2624
3272
|
lastMeterTick: integer("last_meter_tick").notNull().default(0),
|
|
2625
3273
|
|
|
3274
|
+
providerCreatedAt: timestamp("provider_created_at", { withTimezone: true }),
|
|
3275
|
+
providerDeadlineAt: timestamp("provider_deadline_at", {
|
|
3276
|
+
withTimezone: true,
|
|
3277
|
+
}),
|
|
3278
|
+
rotationRequestedAt: timestamp("rotation_requested_at", {
|
|
3279
|
+
withTimezone: true,
|
|
3280
|
+
}),
|
|
3281
|
+
rotationReason: text("rotation_reason", {
|
|
3282
|
+
enum: ["provider_deadline", "operator"],
|
|
3283
|
+
}),
|
|
3284
|
+
// The SQL migration owns the two DEFERRABLE foreign keys and deferred
|
|
3285
|
+
// scope/state constraint triggers. Drizzle does not model deferrability, so
|
|
3286
|
+
// these remain bare UUIDs here rather than generating a stricter wrong FK.
|
|
3287
|
+
currentCheckpointArtifactId: uuid("current_checkpoint_artifact_id"),
|
|
3288
|
+
previousCheckpointArtifactId: uuid("previous_checkpoint_artifact_id"),
|
|
3289
|
+
|
|
2626
3290
|
expiresAt: timestamp("expires_at", { withTimezone: true }).notNull(),
|
|
2627
3291
|
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
2628
3292
|
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
|
|
@@ -2646,6 +3310,13 @@ export const sandboxLeases = pgTable(
|
|
|
2646
3310
|
expiredDrainingInventory: index("sandbox_leases_expired_draining_inventory_idx")
|
|
2647
3311
|
.on(table.expiresAt, table.backend)
|
|
2648
3312
|
.where(sql`${table.liveness} = 'draining'`),
|
|
3313
|
+
providerDeadline: index("sandbox_leases_provider_deadline_idx")
|
|
3314
|
+
.on(table.providerDeadlineAt, table.id)
|
|
3315
|
+
.where(
|
|
3316
|
+
sql`${table.backend} = 'modal'
|
|
3317
|
+
and ${table.liveness} in ('warming', 'warm')
|
|
3318
|
+
and ${table.rotationRequestedAt} is null`,
|
|
3319
|
+
),
|
|
2649
3320
|
workspaceGenerationValid: check(
|
|
2650
3321
|
"sandbox_leases_workspace_generation_check",
|
|
2651
3322
|
sql`${table.workspaceGeneration} >= 0`,
|
|
@@ -2656,6 +3327,43 @@ export const sandboxLeases = pgTable(
|
|
|
2656
3327
|
or (${table.archiveGeneration} >= 0
|
|
2657
3328
|
and ${table.archiveGeneration} <= ${table.workspaceGeneration})`,
|
|
2658
3329
|
),
|
|
3330
|
+
archiveCaptureValid: check(
|
|
3331
|
+
"sandbox_leases_archive_capture_check",
|
|
3332
|
+
sql`(
|
|
3333
|
+
${table.archiveCaptureId} is null
|
|
3334
|
+
and ${table.archiveCaptureGeneration} is null
|
|
3335
|
+
and ${table.archiveCaptureStartedAt} is null
|
|
3336
|
+
and ${table.archiveCaptureDeadlineAt} is null
|
|
3337
|
+
) or (
|
|
3338
|
+
${table.archiveCaptureId} is not null
|
|
3339
|
+
and ${table.archiveCaptureGeneration} is not null
|
|
3340
|
+
and ${table.archiveCaptureGeneration} = ${table.workspaceGeneration}
|
|
3341
|
+
and ${table.archiveCaptureStartedAt} is not null
|
|
3342
|
+
and ${table.archiveCaptureDeadlineAt} > ${table.archiveCaptureStartedAt}
|
|
3343
|
+
)`,
|
|
3344
|
+
),
|
|
3345
|
+
archiveCaptureDeadline: index("sandbox_leases_archive_capture_deadline_idx")
|
|
3346
|
+
.on(table.archiveCaptureDeadlineAt, table.id)
|
|
3347
|
+
.where(sql`${table.archiveCaptureId} is not null`),
|
|
3348
|
+
providerDeadlineValid: check(
|
|
3349
|
+
"sandbox_leases_provider_deadline_check",
|
|
3350
|
+
sql`(${table.providerCreatedAt} is null and ${table.providerDeadlineAt} is null)
|
|
3351
|
+
or (${table.providerCreatedAt} is not null
|
|
3352
|
+
and ${table.providerDeadlineAt} is not null
|
|
3353
|
+
and ${table.providerDeadlineAt} > ${table.providerCreatedAt})`,
|
|
3354
|
+
),
|
|
3355
|
+
rotationValid: check(
|
|
3356
|
+
"sandbox_leases_rotation_check",
|
|
3357
|
+
sql`(${table.rotationRequestedAt} is null and ${table.rotationReason} is null)
|
|
3358
|
+
or (${table.rotationRequestedAt} is not null
|
|
3359
|
+
and ${table.rotationReason} in ('provider_deadline', 'operator'))`,
|
|
3360
|
+
),
|
|
3361
|
+
checkpointDistinct: check(
|
|
3362
|
+
"sandbox_leases_checkpoint_distinct_check",
|
|
3363
|
+
sql`${table.currentCheckpointArtifactId} is null
|
|
3364
|
+
or ${table.previousCheckpointArtifactId} is null
|
|
3365
|
+
or ${table.currentCheckpointArtifactId} <> ${table.previousCheckpointArtifactId}`,
|
|
3366
|
+
),
|
|
2659
3367
|
}),
|
|
2660
3368
|
);
|
|
2661
3369
|
|
|
@@ -2674,7 +3382,9 @@ export const sandboxLeaseHolders = pgTable(
|
|
|
2674
3382
|
leaseId: uuid("lease_id")
|
|
2675
3383
|
.notNull()
|
|
2676
3384
|
.references(() => sandboxLeases.id, { onDelete: "cascade" }),
|
|
2677
|
-
kind: text("kind", {
|
|
3385
|
+
kind: text("kind", {
|
|
3386
|
+
enum: ["turn", "viewer", "direct", "process"],
|
|
3387
|
+
}).notNull(),
|
|
2678
3388
|
holderId: text("holder_id").notNull(),
|
|
2679
3389
|
// The attributing session within the (possibly shared) group.
|
|
2680
3390
|
subjectId: uuid("subject_id"),
|
|
@@ -2719,7 +3429,9 @@ export const sandboxWorkspaceMutationAdmissions = pgTable(
|
|
|
2719
3429
|
.references(() => sandboxLeases.id, { onDelete: "cascade" }),
|
|
2720
3430
|
sandboxGroupId: uuid("sandbox_group_id").notNull(),
|
|
2721
3431
|
sessionId: uuid("session_id").notNull(),
|
|
2722
|
-
actorKind: text("actor_kind", {
|
|
3432
|
+
actorKind: text("actor_kind", {
|
|
3433
|
+
enum: sandboxWorkspaceMutationActorKindValues,
|
|
3434
|
+
}).notNull(),
|
|
2723
3435
|
actorId: uuid("actor_id").notNull(),
|
|
2724
3436
|
// Exact turn authority is present only for actor_kind='turn'. Direct HTTP
|
|
2725
3437
|
// requests and retained processes never invent a turn or quiescence owner.
|
|
@@ -2866,7 +3578,9 @@ export const sandboxRetainedProcesses = pgTable(
|
|
|
2866
3578
|
sandboxGroupId: uuid("sandbox_group_id").notNull(),
|
|
2867
3579
|
parentAdmissionId: uuid("parent_admission_id").notNull(),
|
|
2868
3580
|
holderId: text("holder_id").notNull(),
|
|
2869
|
-
ownerActorKind: text("owner_actor_kind", {
|
|
3581
|
+
ownerActorKind: text("owner_actor_kind", {
|
|
3582
|
+
enum: ["turn", "direct"],
|
|
3583
|
+
}).notNull(),
|
|
2870
3584
|
ownerActorId: uuid("owner_actor_id").notNull(),
|
|
2871
3585
|
ownerTurnId: uuid("owner_turn_id"),
|
|
2872
3586
|
ownerAttemptId: uuid("owner_attempt_id"),
|
|
@@ -2874,6 +3588,11 @@ export const sandboxRetainedProcesses = pgTable(
|
|
|
2874
3588
|
leaseEpoch: integer("lease_epoch").notNull(),
|
|
2875
3589
|
providerBackend: text("provider_backend").notNull(),
|
|
2876
3590
|
providerInstanceId: text("provider_instance_id").notNull(),
|
|
3591
|
+
// Provider object ids are namespace-scoped. New Modal processes bind the
|
|
3592
|
+
// exact authenticated workspace before execution; legacy rows remain null
|
|
3593
|
+
// until a positive lookup proves which namespace owns the historical box.
|
|
3594
|
+
providerBindingKey: text("provider_binding_key"),
|
|
3595
|
+
providerBinding: jsonb("provider_binding").$type<Record<string, unknown>>(),
|
|
2877
3596
|
routeKind: text("route_kind", { enum: ["home", "active"] }).notNull(),
|
|
2878
3597
|
routeTargetId: uuid("route_target_id"),
|
|
2879
3598
|
routeEpoch: integer("route_epoch").notNull(),
|
|
@@ -2889,13 +3608,19 @@ export const sandboxRetainedProcesses = pgTable(
|
|
|
2889
3608
|
// never exit/loss proof.
|
|
2890
3609
|
reconcileAfter: timestamp("reconcile_after", { withTimezone: true }).notNull().defaultNow(),
|
|
2891
3610
|
reconcileClaimId: uuid("reconcile_claim_id"),
|
|
2892
|
-
reconcileClaimedAt: timestamp("reconcile_claimed_at", {
|
|
3611
|
+
reconcileClaimedAt: timestamp("reconcile_claimed_at", {
|
|
3612
|
+
withTimezone: true,
|
|
3613
|
+
}),
|
|
2893
3614
|
reconcileAttempts: integer("reconcile_attempts").notNull().default(0),
|
|
2894
3615
|
lastReconcileOutcome: text("last_reconcile_outcome"),
|
|
2895
|
-
reconcileProofOutcome: text("reconcile_proof_outcome", {
|
|
3616
|
+
reconcileProofOutcome: text("reconcile_proof_outcome", {
|
|
3617
|
+
enum: ["exited", "lost"],
|
|
3618
|
+
}),
|
|
2896
3619
|
reconcileProofExitCode: integer("reconcile_proof_exit_code"),
|
|
2897
3620
|
reconcileProofReason: text("reconcile_proof_reason"),
|
|
2898
|
-
reconcileProofObservedAt: timestamp("reconcile_proof_observed_at", {
|
|
3621
|
+
reconcileProofObservedAt: timestamp("reconcile_proof_observed_at", {
|
|
3622
|
+
withTimezone: true,
|
|
3623
|
+
}),
|
|
2899
3624
|
},
|
|
2900
3625
|
(table) => ({
|
|
2901
3626
|
workspaceAccount: foreignKey({
|
|
@@ -2990,6 +3715,33 @@ export const sandboxRetainedProcesses = pgTable(
|
|
|
2990
3715
|
sql`${table.settlementReason} is null
|
|
2991
3716
|
or octet_length(${table.settlementReason}) between 1 and 512`,
|
|
2992
3717
|
),
|
|
3718
|
+
providerBindingValid: check(
|
|
3719
|
+
"sandbox_retained_processes_provider_binding_check",
|
|
3720
|
+
sql`(
|
|
3721
|
+
${table.providerBindingKey} is null
|
|
3722
|
+
and ${table.providerBinding} is null
|
|
3723
|
+
) or (
|
|
3724
|
+
${table.providerBackend} = 'modal'
|
|
3725
|
+
and octet_length(${table.providerBindingKey}) between 1 and 1024
|
|
3726
|
+
and jsonb_typeof(${table.providerBinding}) = 'object'
|
|
3727
|
+
and ${table.providerBindingKey}::jsonb = ${table.providerBinding}
|
|
3728
|
+
and ${table.providerBindingKey} = format(
|
|
3729
|
+
'{"version":1,"serverUrl":%s,"workspaceName":%s,"environment":%s}',
|
|
3730
|
+
to_jsonb(${table.providerBinding} ->> 'serverUrl')::text,
|
|
3731
|
+
to_jsonb(${table.providerBinding} ->> 'workspaceName')::text,
|
|
3732
|
+
to_jsonb(${table.providerBinding} ->> 'environment')::text
|
|
3733
|
+
)
|
|
3734
|
+
and ${table.providerBinding} = jsonb_build_object(
|
|
3735
|
+
'version', 1,
|
|
3736
|
+
'serverUrl', ${table.providerBinding} ->> 'serverUrl',
|
|
3737
|
+
'workspaceName', ${table.providerBinding} ->> 'workspaceName',
|
|
3738
|
+
'environment', ${table.providerBinding} ->> 'environment'
|
|
3739
|
+
)
|
|
3740
|
+
and coalesce(octet_length(${table.providerBinding} ->> 'serverUrl'), 0) > 0
|
|
3741
|
+
and coalesce(octet_length(${table.providerBinding} ->> 'workspaceName'), 0) > 0
|
|
3742
|
+
and ${table.providerBinding} ->> 'environment' is not null
|
|
3743
|
+
)`,
|
|
3744
|
+
),
|
|
2993
3745
|
reconcileClaimValid: check(
|
|
2994
3746
|
"sandbox_retained_processes_reconcile_claim_check",
|
|
2995
3747
|
sql`(${table.reconcileClaimId} is null and ${table.reconcileClaimedAt} is null)
|
|
@@ -3020,7 +3772,8 @@ export const sandboxRetainedProcesses = pgTable(
|
|
|
3020
3772
|
${table.reconcileProofOutcome} = 'lost'
|
|
3021
3773
|
and ${table.reconcileProofExitCode} is null
|
|
3022
3774
|
and ${table.reconcileProofReason} in (
|
|
3023
|
-
'provider_session_lost_banner', 'provider_instance_not_found'
|
|
3775
|
+
'provider_session_lost_banner', 'provider_instance_not_found',
|
|
3776
|
+
'provider_instance_terminated'
|
|
3024
3777
|
)
|
|
3025
3778
|
and ${table.reconcileProofObservedAt} is not null
|
|
3026
3779
|
)`,
|
|
@@ -3619,8 +4372,12 @@ export const githubInstallations = pgTable(
|
|
|
3619
4372
|
githubActorId: bigint("github_actor_id", { mode: "number" }),
|
|
3620
4373
|
githubActorLogin: text("github_actor_login"),
|
|
3621
4374
|
authorityKind: text("authority_kind"),
|
|
3622
|
-
authorityCheckedAt: timestamp("authority_checked_at", {
|
|
3623
|
-
|
|
4375
|
+
authorityCheckedAt: timestamp("authority_checked_at", {
|
|
4376
|
+
withTimezone: true,
|
|
4377
|
+
}),
|
|
4378
|
+
authorityExpiresAt: timestamp("authority_expires_at", {
|
|
4379
|
+
withTimezone: true,
|
|
4380
|
+
}),
|
|
3624
4381
|
authorityNonce: text("authority_nonce"),
|
|
3625
4382
|
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
3626
4383
|
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
|
|
@@ -3805,6 +4562,102 @@ export const usageEvents = pgTable(
|
|
|
3805
4562
|
}),
|
|
3806
4563
|
);
|
|
3807
4564
|
|
|
4565
|
+
/**
|
|
4566
|
+
* Per model-call Insights facts. Additive observability only — never the billing
|
|
4567
|
+
* ledger. Written after an authoritative `agent.model.usage` emit.
|
|
4568
|
+
*/
|
|
4569
|
+
export const modelCallFacts = pgTable(
|
|
4570
|
+
"model_call_facts",
|
|
4571
|
+
{
|
|
4572
|
+
id: uuid("id").primaryKey().defaultRandom(),
|
|
4573
|
+
accountId: uuid("account_id")
|
|
4574
|
+
.notNull()
|
|
4575
|
+
.references(() => managedAccounts.id, { onDelete: "cascade" }),
|
|
4576
|
+
workspaceId: uuid("workspace_id")
|
|
4577
|
+
.notNull()
|
|
4578
|
+
.references(() => workspaces.id, { onDelete: "cascade" }),
|
|
4579
|
+
sessionId: uuid("session_id").notNull(),
|
|
4580
|
+
turnId: uuid("turn_id").notNull(),
|
|
4581
|
+
turnAttemptId: uuid("turn_attempt_id"),
|
|
4582
|
+
sourceKey: text("source_key").notNull(),
|
|
4583
|
+
provider: text("provider").notNull(),
|
|
4584
|
+
providerApi: text("provider_api").notNull(),
|
|
4585
|
+
model: text("model").notNull(),
|
|
4586
|
+
billingPath: text("billing_path").notNull(),
|
|
4587
|
+
turnSource: text("turn_source"),
|
|
4588
|
+
initiatorKind: text("initiator_kind"),
|
|
4589
|
+
initiatorSubjectId: text("initiator_subject_id"),
|
|
4590
|
+
scheduledTaskId: uuid("scheduled_task_id"),
|
|
4591
|
+
inputTokens: bigint("input_tokens", { mode: "number" }),
|
|
4592
|
+
outputTokens: bigint("output_tokens", { mode: "number" }),
|
|
4593
|
+
cachedTokens: bigint("cached_tokens", { mode: "number" }),
|
|
4594
|
+
cacheWriteTokens: bigint("cache_write_tokens", { mode: "number" }),
|
|
4595
|
+
reasoningTokens: bigint("reasoning_tokens", { mode: "number" }),
|
|
4596
|
+
totalTokens: bigint("total_tokens", { mode: "number" }),
|
|
4597
|
+
pricedCostMicros: bigint("priced_cost_micros", { mode: "number" }).notNull().default(0),
|
|
4598
|
+
occurredAt: timestamp("occurred_at", { withTimezone: true }).notNull(),
|
|
4599
|
+
recordedAt: timestamp("recorded_at", { withTimezone: true }).notNull().defaultNow(),
|
|
4600
|
+
},
|
|
4601
|
+
(table) => ({
|
|
4602
|
+
workspaceTurnSource: uniqueIndex("model_call_facts_workspace_turn_source_uq").on(
|
|
4603
|
+
table.workspaceId,
|
|
4604
|
+
table.turnId,
|
|
4605
|
+
table.sourceKey,
|
|
4606
|
+
),
|
|
4607
|
+
workspaceOccurred: index("model_call_facts_workspace_occurred_idx").on(
|
|
4608
|
+
table.workspaceId,
|
|
4609
|
+
table.occurredAt,
|
|
4610
|
+
),
|
|
4611
|
+
workspaceProviderModelOccurred: index(
|
|
4612
|
+
"model_call_facts_workspace_provider_model_occurred_idx",
|
|
4613
|
+
).on(table.workspaceId, table.provider, table.model, table.occurredAt),
|
|
4614
|
+
workspaceSessionOccurred: index("model_call_facts_workspace_session_occurred_idx").on(
|
|
4615
|
+
table.workspaceId,
|
|
4616
|
+
table.sessionId,
|
|
4617
|
+
table.occurredAt,
|
|
4618
|
+
),
|
|
4619
|
+
workspaceScheduledTaskOccurred: index("model_call_facts_workspace_scheduled_task_occurred_idx")
|
|
4620
|
+
.on(table.workspaceId, table.scheduledTaskId, table.occurredAt)
|
|
4621
|
+
.where(sql`${table.scheduledTaskId} is not null`),
|
|
4622
|
+
workspaceAccount: foreignKey({
|
|
4623
|
+
name: "model_call_facts_workspace_account_fk",
|
|
4624
|
+
columns: [table.workspaceId, table.accountId],
|
|
4625
|
+
foreignColumns: [workspaces.id, workspaces.accountId],
|
|
4626
|
+
}).onDelete("cascade"),
|
|
4627
|
+
billingPathValid: check(
|
|
4628
|
+
"model_call_facts_billing_path_check",
|
|
4629
|
+
sql`${table.billingPath} in ('opengeni_credits', 'external')`,
|
|
4630
|
+
),
|
|
4631
|
+
pricedCostNonNegative: check(
|
|
4632
|
+
"model_call_facts_priced_cost_check",
|
|
4633
|
+
sql`${table.pricedCostMicros} >= 0`,
|
|
4634
|
+
),
|
|
4635
|
+
initiatorConsistent: check(
|
|
4636
|
+
"model_call_facts_initiator_check",
|
|
4637
|
+
sql`(${table.initiatorKind} is null and ${table.initiatorSubjectId} is null)
|
|
4638
|
+
or (${table.initiatorKind} in ('subject', 'service')
|
|
4639
|
+
and ${table.initiatorSubjectId} is not null
|
|
4640
|
+
and octet_length(${table.initiatorSubjectId}) between 1 and 1024)`,
|
|
4641
|
+
),
|
|
4642
|
+
sourceKeyBytes: check(
|
|
4643
|
+
"model_call_facts_source_key_bytes_check",
|
|
4644
|
+
sql`octet_length(${table.sourceKey}) between 1 and 1024`,
|
|
4645
|
+
),
|
|
4646
|
+
providerBytes: check(
|
|
4647
|
+
"model_call_facts_provider_bytes_check",
|
|
4648
|
+
sql`octet_length(${table.provider}) between 1 and 256`,
|
|
4649
|
+
),
|
|
4650
|
+
providerApiBytes: check(
|
|
4651
|
+
"model_call_facts_provider_api_bytes_check",
|
|
4652
|
+
sql`octet_length(${table.providerApi}) between 1 and 256`,
|
|
4653
|
+
),
|
|
4654
|
+
modelBytes: check(
|
|
4655
|
+
"model_call_facts_model_bytes_check",
|
|
4656
|
+
sql`octet_length(${table.model}) between 1 and 512`,
|
|
4657
|
+
),
|
|
4658
|
+
}),
|
|
4659
|
+
);
|
|
4660
|
+
|
|
3808
4661
|
/** Singleton, migration-installed gate. Standalone defaults keep both off. */
|
|
3809
4662
|
export const hostExportConfig = pgTable(
|
|
3810
4663
|
"host_export_config",
|
|
@@ -3854,7 +4707,9 @@ export const hostExportOutbox = pgTable(
|
|
|
3854
4707
|
payload: jsonb("payload").$type<unknown>().notNull(),
|
|
3855
4708
|
envelopeBytes: integer("envelope_bytes").notNull(),
|
|
3856
4709
|
occurredAt: timestamp("occurred_at", { withTimezone: true }).notNull(),
|
|
3857
|
-
sourceRecordedAt: timestamp("source_recorded_at", {
|
|
4710
|
+
sourceRecordedAt: timestamp("source_recorded_at", {
|
|
4711
|
+
withTimezone: true,
|
|
4712
|
+
}).notNull(),
|
|
3858
4713
|
enqueuedAt: timestamp("enqueued_at", { withTimezone: true }).notNull(),
|
|
3859
4714
|
},
|
|
3860
4715
|
(table) => ({
|
|
@@ -4439,3 +5294,4 @@ export const rigChanges = pgTable(
|
|
|
4439
5294
|
);
|
|
4440
5295
|
|
|
4441
5296
|
export * from "./workspace-instruction-policies-schema";
|
|
5297
|
+
export * from "./preference-registry-schema";
|