@opengeni/db 0.10.7 → 0.12.0
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-P6PKXY5W.js → chunk-VUKRIBO5.js} +485 -12
- package/dist/chunk-VUKRIBO5.js.map +1 -0
- package/dist/{chunk-KW526IJA.js → chunk-Y5WZZVQK.js} +80 -4
- package/dist/chunk-Y5WZZVQK.js.map +1 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.js +5114 -2085
- package/dist/index.js.map +1 -1
- package/dist/migrate.d.ts +6 -3
- package/dist/migrate.js +1 -1
- package/dist/provision-roles.d.ts +720 -63
- package/dist/{schema-CqkzrBRS.d.ts → schema-CnpD6BcX.d.ts} +4684 -2913
- package/dist/schema.d.ts +1 -1
- package/dist/schema.js +17 -1
- package/drizzle/0109_nested_agent_depth_expand.sql +42 -0
- package/drizzle/0110_nested_agent_depth_boundary.sql +480 -0
- package/drizzle/0111_nested_agent_depth_backfill.sql +49 -0
- package/drizzle/0112_nested_agent_depth_contract.sql +38 -0
- package/drizzle/0113_nested_agent_depth_validate.sql +13 -0
- package/drizzle/0114_nested_agent_depth_contract.sql +49 -0
- package/drizzle/0115_nested_agent_depth_validate.sql +11 -0
- package/drizzle/0116_nested_agent_depth_index.sql +4 -0
- package/drizzle/0117_sandbox_recovery_generations.sql +699 -0
- package/drizzle/0118_new_session_drafts.sql +59 -0
- package/drizzle/0119_pending_tool_output_policy.sql +5 -0
- package/drizzle/0120_durable_goal_wake.sql +360 -0
- package/drizzle/0121_goal_update_idempotency.sql +11 -0
- package/package.json +3 -3
- package/src/index.ts +5961 -1240
- package/src/migrate.ts +131 -2
- package/src/new-session-drafts.ts +144 -0
- package/src/schema.ts +519 -15
- package/src/session-control.ts +42 -18
- package/src/session-tool-call-settlement.ts +6 -1
- package/dist/chunk-KW526IJA.js.map +0 -1
- package/dist/chunk-P6PKXY5W.js.map +0 -1
package/src/schema.ts
CHANGED
|
@@ -81,6 +81,34 @@ export const workspaces = pgTable(
|
|
|
81
81
|
}),
|
|
82
82
|
);
|
|
83
83
|
|
|
84
|
+
// One target-schema-local deployment fallback. The migration runner reconciles
|
|
85
|
+
// this singleton from OPENGENI_MAX_NESTED_AGENT_DEPTH; session admission locks
|
|
86
|
+
// and reads it through the SECURITY DEFINER capability installed by the
|
|
87
|
+
// boundary migration so the application role cannot mutate policy authority.
|
|
88
|
+
export const nestedAgentDepthConfiguration = pgTable(
|
|
89
|
+
"nested_agent_depth_configuration",
|
|
90
|
+
{
|
|
91
|
+
singleton: boolean("singleton").primaryKey().notNull().default(true),
|
|
92
|
+
maxNestedAgentDepth: integer("max_nested_agent_depth").notNull(),
|
|
93
|
+
policySource: text("policy_source").$type<"deployment" | "default">().notNull(),
|
|
94
|
+
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
|
|
95
|
+
},
|
|
96
|
+
(table) => ({
|
|
97
|
+
singletonOnly: check(
|
|
98
|
+
"nested_agent_depth_configuration_singleton_check",
|
|
99
|
+
sql`${table.singleton}`,
|
|
100
|
+
),
|
|
101
|
+
maxValid: check(
|
|
102
|
+
"nested_agent_depth_configuration_max_check",
|
|
103
|
+
sql`${table.maxNestedAgentDepth} >= 0`,
|
|
104
|
+
),
|
|
105
|
+
sourceValid: check(
|
|
106
|
+
"nested_agent_depth_configuration_source_check",
|
|
107
|
+
sql`${table.policySource} in ('deployment', 'default')`,
|
|
108
|
+
),
|
|
109
|
+
}),
|
|
110
|
+
);
|
|
111
|
+
|
|
84
112
|
// One mandatory workspace-wide admission barrier. Every inference-admitting
|
|
85
113
|
// transaction locks this row before it touches a session; Pause/Resume and
|
|
86
114
|
// foreground Send/Steer advance its monotonic revision under FOR UPDATE.
|
|
@@ -741,6 +769,15 @@ export const sessions = pgTable(
|
|
|
741
769
|
// workspace to a single session row — the dedup that closes the
|
|
742
770
|
// double-submit/double-dispatch stuck-queued bug.
|
|
743
771
|
createIdempotencyKey: text("create_idempotency_key"),
|
|
772
|
+
// Immutable creation-time hierarchy and policy snapshot. These values are
|
|
773
|
+
// populated by the database admission boundary and never re-derived from
|
|
774
|
+
// a live workspace setting for an existing session.
|
|
775
|
+
rootSessionId: uuid("root_session_id").notNull(),
|
|
776
|
+
nestedAgentDepth: integer("nested_agent_depth").notNull(),
|
|
777
|
+
maxNestedAgentDepthOverride: integer("max_nested_agent_depth_override"),
|
|
778
|
+
effectiveMaxNestedAgentDepth: integer("effective_max_nested_agent_depth").notNull(),
|
|
779
|
+
nestedAgentDepthPolicySource: text("nested_agent_depth_policy_source").notNull(),
|
|
780
|
+
nestedAgentDepthPolicySessionId: uuid("nested_agent_depth_policy_session_id"),
|
|
744
781
|
temporalWorkflowId: text("temporal_workflow_id"),
|
|
745
782
|
activeTurnId: uuid("active_turn_id"),
|
|
746
783
|
// Actual input tokens reported for the last model call of the most recent
|
|
@@ -823,12 +860,64 @@ export const sessions = pgTable(
|
|
|
823
860
|
// point and enumerate all sessions in a group for attribution/disclosure.
|
|
824
861
|
sandboxGroup: index("sessions_sandbox_group_idx").on(table.workspaceId, table.sandboxGroupId),
|
|
825
862
|
// Partial unique index: one session per (workspace, create_idempotency_key)
|
|
826
|
-
// when a key is present.
|
|
827
|
-
//
|
|
828
|
-
// the
|
|
863
|
+
// when a key is present. The boundary trigger reserves the cross-outcome
|
|
864
|
+
// winner before this source row commits; a losing source insert is
|
|
865
|
+
// suppressed and the domain layer replays the durable winner.
|
|
829
866
|
createIdempotency: uniqueIndex("sessions_workspace_create_idempotency_idx")
|
|
830
867
|
.on(table.workspaceId, table.createIdempotencyKey)
|
|
831
868
|
.where(sql`${table.createIdempotencyKey} is not null`),
|
|
869
|
+
rootDepth: index("sessions_workspace_root_depth_idx").on(
|
|
870
|
+
table.workspaceId,
|
|
871
|
+
table.rootSessionId,
|
|
872
|
+
table.nestedAgentDepth,
|
|
873
|
+
),
|
|
874
|
+
}),
|
|
875
|
+
);
|
|
876
|
+
|
|
877
|
+
// A denied session create is durable evidence, not a mutable session/resource
|
|
878
|
+
// artifact. It has its own workspace-scoped idempotency key so retries replay
|
|
879
|
+
// the same denial without creating a session or billing/run rows.
|
|
880
|
+
export const sessionSpawnDenials = pgTable(
|
|
881
|
+
"session_spawn_denials",
|
|
882
|
+
{
|
|
883
|
+
id: uuid("id").primaryKey().defaultRandom(),
|
|
884
|
+
accountId: uuid("account_id").notNull(),
|
|
885
|
+
workspaceId: uuid("workspace_id").notNull(),
|
|
886
|
+
parentSessionId: uuid("parent_session_id"),
|
|
887
|
+
rootSessionId: uuid("root_session_id"),
|
|
888
|
+
currentDepth: integer("current_depth").notNull(),
|
|
889
|
+
attemptedDepth: bigint("attempted_depth", { mode: "number" }).notNull(),
|
|
890
|
+
effectiveMaxNestedAgentDepth: integer("effective_max_nested_agent_depth").notNull(),
|
|
891
|
+
requestedMaxNestedAgentDepthOverride: integer("requested_max_nested_agent_depth_override"),
|
|
892
|
+
policySource: text("policy_source").notNull(),
|
|
893
|
+
policySessionId: uuid("policy_session_id"),
|
|
894
|
+
subjectId: text("subject_id"),
|
|
895
|
+
code: text("code").notNull(),
|
|
896
|
+
idempotencyKey: text("idempotency_key"),
|
|
897
|
+
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
898
|
+
},
|
|
899
|
+
(table) => ({
|
|
900
|
+
workspaceIdentity: uniqueIndex("session_spawn_denials_workspace_id_uq").on(
|
|
901
|
+
table.workspaceId,
|
|
902
|
+
table.id,
|
|
903
|
+
),
|
|
904
|
+
workspaceCreated: index("session_spawn_denials_workspace_created_idx").on(
|
|
905
|
+
table.workspaceId,
|
|
906
|
+
table.createdAt,
|
|
907
|
+
),
|
|
908
|
+
parent: index("session_spawn_denials_parent_idx").on(
|
|
909
|
+
table.workspaceId,
|
|
910
|
+
table.parentSessionId,
|
|
911
|
+
table.createdAt,
|
|
912
|
+
),
|
|
913
|
+
idempotency: uniqueIndex("session_spawn_denials_workspace_idempotency_idx")
|
|
914
|
+
.on(table.workspaceId, table.idempotencyKey)
|
|
915
|
+
.where(sql`${table.idempotencyKey} is not null`),
|
|
916
|
+
workspaceAccount: foreignKey({
|
|
917
|
+
name: "session_spawn_denials_workspace_account_fk",
|
|
918
|
+
columns: [table.workspaceId, table.accountId],
|
|
919
|
+
foreignColumns: [workspaces.id, workspaces.accountId],
|
|
920
|
+
}).onDelete("cascade"),
|
|
832
921
|
}),
|
|
833
922
|
);
|
|
834
923
|
|
|
@@ -1464,6 +1553,9 @@ export const sessionCommandReceipts = pgTable(
|
|
|
1464
1553
|
table.targetSessionId,
|
|
1465
1554
|
table.createdAt,
|
|
1466
1555
|
),
|
|
1556
|
+
goalUpdateOperation: uniqueIndex("session_command_receipts_goal_update_operation_uq")
|
|
1557
|
+
.on(table.workspaceId, table.action, table.targetSessionId, table.operationKey)
|
|
1558
|
+
.where(sql`${table.action} = 'goal.update'`),
|
|
1467
1559
|
actorValid: check(
|
|
1468
1560
|
"session_command_receipts_actor_check",
|
|
1469
1561
|
sql`(
|
|
@@ -1640,6 +1732,43 @@ export const composerDrafts = pgTable(
|
|
|
1640
1732
|
}),
|
|
1641
1733
|
);
|
|
1642
1734
|
|
|
1735
|
+
// Private pre-session composer truth. It is separate from composerDrafts so
|
|
1736
|
+
// the established-session table keeps its mandatory session foreign key.
|
|
1737
|
+
export const newSessionDrafts = pgTable(
|
|
1738
|
+
"new_session_drafts",
|
|
1739
|
+
{
|
|
1740
|
+
id: uuid("id").primaryKey().defaultRandom(),
|
|
1741
|
+
accountId: uuid("account_id").notNull(),
|
|
1742
|
+
workspaceId: uuid("workspace_id").notNull(),
|
|
1743
|
+
subjectId: text("subject_id").notNull(),
|
|
1744
|
+
revision: bigint("revision", { mode: "number" }).notNull().default(1),
|
|
1745
|
+
text: text("text").notNull().default(""),
|
|
1746
|
+
resources: jsonb("resources").$type<unknown[]>().notNull().default([]),
|
|
1747
|
+
tools: jsonb("tools").$type<unknown[]>().notNull().default([]),
|
|
1748
|
+
model: text("model").notNull(),
|
|
1749
|
+
reasoningEffort: text("reasoning_effort").notNull(),
|
|
1750
|
+
sessionOptions: jsonb("session_options").$type<Record<string, unknown>>().notNull().default({}),
|
|
1751
|
+
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
1752
|
+
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
|
|
1753
|
+
},
|
|
1754
|
+
(table) => ({
|
|
1755
|
+
workspaceAccount: foreignKey({
|
|
1756
|
+
name: "new_session_drafts_workspace_account_fk",
|
|
1757
|
+
columns: [table.workspaceId, table.accountId],
|
|
1758
|
+
foreignColumns: [workspaces.id, workspaces.accountId],
|
|
1759
|
+
}).onDelete("cascade"),
|
|
1760
|
+
subjectWorkspace: uniqueIndex("new_session_drafts_subject_workspace_uq").on(
|
|
1761
|
+
table.workspaceId,
|
|
1762
|
+
table.subjectId,
|
|
1763
|
+
),
|
|
1764
|
+
subjectValid: check(
|
|
1765
|
+
"new_session_drafts_subject_check",
|
|
1766
|
+
sql`length(btrim(${table.subjectId})) > 0`,
|
|
1767
|
+
),
|
|
1768
|
+
revisionValid: check("new_session_drafts_revision_check", sql`${table.revision} >= 1`),
|
|
1769
|
+
}),
|
|
1770
|
+
);
|
|
1771
|
+
|
|
1643
1772
|
export const sessionSystemUpdates = pgTable(
|
|
1644
1773
|
"session_system_updates",
|
|
1645
1774
|
{
|
|
@@ -1779,6 +1908,10 @@ export const sessionWorkflowWakeOutbox = pgTable(
|
|
|
1779
1908
|
"session_workflow_wake_outbox_revision_check",
|
|
1780
1909
|
sql`${table.wakeRevision} > 0 and ${table.deliveredRevision} >= 0 and ${table.deliveredRevision} <= ${table.wakeRevision}`,
|
|
1781
1910
|
),
|
|
1911
|
+
revisionSafe: check(
|
|
1912
|
+
"session_workflow_wake_outbox_revision_safe_check",
|
|
1913
|
+
sql`${table.wakeRevision} <= 9007199254740991 and ${table.deliveredRevision} <= 9007199254740991`,
|
|
1914
|
+
),
|
|
1782
1915
|
workspaceAccount: foreignKey({
|
|
1783
1916
|
name: "session_workflow_wake_outbox_workspace_account_fk",
|
|
1784
1917
|
columns: [table.workspaceId, table.accountId],
|
|
@@ -1825,6 +1958,18 @@ export const sessionGoals = pgTable(
|
|
|
1825
1958
|
maxAutoContinuations: integer("max_auto_continuations"), // per-goal override; a configured settings cap (if any) remains the hard ceiling
|
|
1826
1959
|
lastContinuationTurnId: uuid("last_continuation_turn_id"),
|
|
1827
1960
|
versionAtLastContinuation: integer("version_at_last_continuation"),
|
|
1961
|
+
// Postgres owns the continuation obligation. Terminal settlement advances
|
|
1962
|
+
// wakeRevision in the same transaction that makes the session idle;
|
|
1963
|
+
// materialization advances observedRevision only alongside the one typed
|
|
1964
|
+
// update, timeline events, usage row, and workflow-wake outbox row.
|
|
1965
|
+
// Temporal signals and workflow history are replaceable nudges over these
|
|
1966
|
+
// monotonic revisions.
|
|
1967
|
+
continuationWakeRevision: bigint("continuation_wake_revision", { mode: "number" })
|
|
1968
|
+
.notNull()
|
|
1969
|
+
.default(0),
|
|
1970
|
+
continuationObservedRevision: bigint("continuation_observed_revision", { mode: "number" })
|
|
1971
|
+
.notNull()
|
|
1972
|
+
.default(0),
|
|
1828
1973
|
metadata: jsonb("metadata").$type<Record<string, unknown>>().notNull().default({}),
|
|
1829
1974
|
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
1830
1975
|
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
|
|
@@ -1839,6 +1984,10 @@ export const sessionGoals = pgTable(
|
|
|
1839
1984
|
table.sessionId,
|
|
1840
1985
|
),
|
|
1841
1986
|
status: index("session_goals_workspace_status_idx").on(table.workspaceId, table.status),
|
|
1987
|
+
continuationRevisionValid: check(
|
|
1988
|
+
"session_goals_continuation_revision_check",
|
|
1989
|
+
sql`${table.continuationWakeRevision} >= 0 and ${table.continuationObservedRevision} >= 0 and ${table.continuationObservedRevision} <= ${table.continuationWakeRevision} and ${table.continuationWakeRevision} <= 9007199254740991 and ${table.continuationObservedRevision} <= 9007199254740991`,
|
|
1990
|
+
),
|
|
1842
1991
|
}),
|
|
1843
1992
|
);
|
|
1844
1993
|
|
|
@@ -2198,6 +2347,7 @@ export const sessionPendingToolCalls = pgTable(
|
|
|
2198
2347
|
callId: text("call_id").notNull(),
|
|
2199
2348
|
callType: text("call_type").notNull(),
|
|
2200
2349
|
callItem: jsonb("call_item").$type<Record<string, unknown>>().notNull(),
|
|
2350
|
+
modelToolOutputTruncationTokens: integer("model_tool_output_truncation_tokens"),
|
|
2201
2351
|
resultItem: jsonb("result_item").$type<Record<string, unknown>>(),
|
|
2202
2352
|
resultRecordedAt: timestamp("result_recorded_at", { withTimezone: true }),
|
|
2203
2353
|
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
@@ -2310,6 +2460,14 @@ export const sandboxLeases = pgTable(
|
|
|
2310
2460
|
// Epochs never approach 2^31, so the narrower type loses nothing.
|
|
2311
2461
|
leaseEpoch: integer("lease_epoch").notNull().default(0),
|
|
2312
2462
|
|
|
2463
|
+
// Monotonic mutation intent for the live workspace. Every acknowledged
|
|
2464
|
+
// filesystem-writing operation advances this under the exact lease epoch +
|
|
2465
|
+
// provider-instance fence BEFORE it reaches the provider. A verified
|
|
2466
|
+
// archive fold copies the exact captured value into archive_generation in
|
|
2467
|
+
// the same row update; equality is the only durable completeness proof.
|
|
2468
|
+
workspaceGeneration: integer("workspace_generation").notNull().default(0),
|
|
2469
|
+
archiveGeneration: integer("archive_generation"),
|
|
2470
|
+
|
|
2313
2471
|
// The group box-envelope (the "envelope split" Critical): the small recovery
|
|
2314
2472
|
// descriptor to resume()-by-id the group's box without a per-session join.
|
|
2315
2473
|
resumeBackendId: text("resume_backend_id"),
|
|
@@ -2327,9 +2485,30 @@ export const sandboxLeases = pgTable(
|
|
|
2327
2485
|
},
|
|
2328
2486
|
(table) => ({
|
|
2329
2487
|
groupIdx: uniqueIndex("sandbox_leases_group_idx").on(table.workspaceId, table.sandboxGroupId),
|
|
2488
|
+
scopedId: uniqueIndex("sandbox_leases_scoped_id_uq").on(
|
|
2489
|
+
table.accountId,
|
|
2490
|
+
table.workspaceId,
|
|
2491
|
+
table.sandboxGroupId,
|
|
2492
|
+
table.id,
|
|
2493
|
+
),
|
|
2494
|
+
accountWorkspaceId: uniqueIndex("sandbox_leases_account_workspace_id_uq").on(
|
|
2495
|
+
table.accountId,
|
|
2496
|
+
table.workspaceId,
|
|
2497
|
+
table.id,
|
|
2498
|
+
),
|
|
2330
2499
|
reaperIdx: index("sandbox_leases_reaper_idx")
|
|
2331
2500
|
.on(table.expiresAt)
|
|
2332
2501
|
.where(sql`${table.liveness} in ('warming','warm','draining')`),
|
|
2502
|
+
workspaceGenerationValid: check(
|
|
2503
|
+
"sandbox_leases_workspace_generation_check",
|
|
2504
|
+
sql`${table.workspaceGeneration} >= 0`,
|
|
2505
|
+
),
|
|
2506
|
+
archiveGenerationValid: check(
|
|
2507
|
+
"sandbox_leases_archive_generation_check",
|
|
2508
|
+
sql`${table.archiveGeneration} is null
|
|
2509
|
+
or (${table.archiveGeneration} >= 0
|
|
2510
|
+
and ${table.archiveGeneration} <= ${table.workspaceGeneration})`,
|
|
2511
|
+
),
|
|
2333
2512
|
}),
|
|
2334
2513
|
);
|
|
2335
2514
|
|
|
@@ -2348,7 +2527,7 @@ export const sandboxLeaseHolders = pgTable(
|
|
|
2348
2527
|
leaseId: uuid("lease_id")
|
|
2349
2528
|
.notNull()
|
|
2350
2529
|
.references(() => sandboxLeases.id, { onDelete: "cascade" }),
|
|
2351
|
-
kind: text("kind", { enum: ["turn", "viewer"] }).notNull(),
|
|
2530
|
+
kind: text("kind", { enum: ["turn", "viewer", "direct", "process"] }).notNull(),
|
|
2352
2531
|
holderId: text("holder_id").notNull(),
|
|
2353
2532
|
// The attributing session within the (possibly shared) group.
|
|
2354
2533
|
subjectId: uuid("subject_id"),
|
|
@@ -2356,6 +2535,11 @@ export const sandboxLeaseHolders = pgTable(
|
|
|
2356
2535
|
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
2357
2536
|
},
|
|
2358
2537
|
(table) => ({
|
|
2538
|
+
leaseScope: foreignKey({
|
|
2539
|
+
name: "sandbox_lease_holders_lease_scope_fk",
|
|
2540
|
+
columns: [table.accountId, table.workspaceId, table.leaseId],
|
|
2541
|
+
foreignColumns: [sandboxLeases.accountId, sandboxLeases.workspaceId, sandboxLeases.id],
|
|
2542
|
+
}).onDelete("cascade"),
|
|
2359
2543
|
holderIdx: uniqueIndex("sandbox_lease_holders_holder_idx").on(
|
|
2360
2544
|
table.leaseId,
|
|
2361
2545
|
table.kind,
|
|
@@ -2366,6 +2550,283 @@ export const sandboxLeaseHolders = pgTable(
|
|
|
2366
2550
|
}),
|
|
2367
2551
|
);
|
|
2368
2552
|
|
|
2553
|
+
export const sandboxWorkspaceMutationActorKindValues = ["turn", "direct", "process"] as const;
|
|
2554
|
+
export const sandboxWorkspaceMutationHolderKindValues = ["turn", "direct", "process"] as const;
|
|
2555
|
+
|
|
2556
|
+
// Durable admission ledger for every provider operation that may mutate a
|
|
2557
|
+
// persistable /workspace. The row is inserted atomically with the lease's
|
|
2558
|
+
// workspace_generation increment before the provider is invoked, then marked
|
|
2559
|
+
// physically settled after the provider promise resolves OR rejects. Capture
|
|
2560
|
+
// remains blocked by an unsettled direct/process row. A turn row may cease
|
|
2561
|
+
// blocking only after its exact attempt carries the authoritative quiesced_at
|
|
2562
|
+
// receipt. Yielded provider processes remain retained/unsettled until exact
|
|
2563
|
+
// exit or loss proof settles their parent admission.
|
|
2564
|
+
export const sandboxWorkspaceMutationAdmissions = pgTable(
|
|
2565
|
+
"sandbox_workspace_mutation_admissions",
|
|
2566
|
+
{
|
|
2567
|
+
id: uuid("id").primaryKey().defaultRandom(),
|
|
2568
|
+
accountId: uuid("account_id").notNull(),
|
|
2569
|
+
workspaceId: uuid("workspace_id").notNull(),
|
|
2570
|
+
leaseId: uuid("lease_id")
|
|
2571
|
+
.notNull()
|
|
2572
|
+
.references(() => sandboxLeases.id, { onDelete: "cascade" }),
|
|
2573
|
+
sandboxGroupId: uuid("sandbox_group_id").notNull(),
|
|
2574
|
+
sessionId: uuid("session_id").notNull(),
|
|
2575
|
+
actorKind: text("actor_kind", { enum: sandboxWorkspaceMutationActorKindValues }).notNull(),
|
|
2576
|
+
actorId: uuid("actor_id").notNull(),
|
|
2577
|
+
// Exact turn authority is present only for actor_kind='turn'. Direct HTTP
|
|
2578
|
+
// requests and retained processes never invent a turn or quiescence owner.
|
|
2579
|
+
turnId: uuid("turn_id"),
|
|
2580
|
+
attemptId: uuid("attempt_id"),
|
|
2581
|
+
executionGeneration: integer("execution_generation"),
|
|
2582
|
+
holderKind: text("holder_kind", {
|
|
2583
|
+
enum: sandboxWorkspaceMutationHolderKindValues,
|
|
2584
|
+
}).notNull(),
|
|
2585
|
+
holderId: text("holder_id").notNull(),
|
|
2586
|
+
leaseEpoch: integer("lease_epoch").notNull(),
|
|
2587
|
+
providerBackend: text("provider_backend").notNull(),
|
|
2588
|
+
providerInstanceId: text("provider_instance_id").notNull(),
|
|
2589
|
+
routeKind: text("route_kind", { enum: ["home", "active"] }).notNull(),
|
|
2590
|
+
// null route target means the persistable home/group provider. A non-null
|
|
2591
|
+
// target is pinned together with the active pointer epoch observed when the
|
|
2592
|
+
// operation was admitted.
|
|
2593
|
+
routeTargetId: uuid("route_target_id"),
|
|
2594
|
+
routeEpoch: integer("route_epoch").notNull(),
|
|
2595
|
+
workspaceGeneration: integer("workspace_generation").notNull(),
|
|
2596
|
+
operation: text("operation").notNull(),
|
|
2597
|
+
providerOutcome: text("provider_outcome", {
|
|
2598
|
+
enum: ["resolved", "rejected", "retained"],
|
|
2599
|
+
}),
|
|
2600
|
+
admittedAt: timestamp("admitted_at", { withTimezone: true }).notNull().defaultNow(),
|
|
2601
|
+
settledAt: timestamp("settled_at", { withTimezone: true }),
|
|
2602
|
+
},
|
|
2603
|
+
(table) => ({
|
|
2604
|
+
workspaceAccount: foreignKey({
|
|
2605
|
+
name: "sandbox_workspace_mutation_admissions_workspace_account_fk",
|
|
2606
|
+
columns: [table.workspaceId, table.accountId],
|
|
2607
|
+
foreignColumns: [workspaces.id, workspaces.accountId],
|
|
2608
|
+
}).onDelete("cascade"),
|
|
2609
|
+
workspaceSession: foreignKey({
|
|
2610
|
+
name: "sandbox_workspace_mutation_admissions_workspace_session_fk",
|
|
2611
|
+
columns: [table.workspaceId, table.sessionId],
|
|
2612
|
+
foreignColumns: [sessions.workspaceId, sessions.id],
|
|
2613
|
+
}).onDelete("restrict"),
|
|
2614
|
+
workspaceTurn: foreignKey({
|
|
2615
|
+
name: "sandbox_workspace_mutation_admissions_workspace_turn_fk",
|
|
2616
|
+
columns: [table.workspaceId, table.turnId],
|
|
2617
|
+
foreignColumns: [sessionTurns.workspaceId, sessionTurns.id],
|
|
2618
|
+
}).onDelete("restrict"),
|
|
2619
|
+
workspaceAttempt: foreignKey({
|
|
2620
|
+
name: "sandbox_workspace_mutation_admissions_workspace_attempt_fk",
|
|
2621
|
+
columns: [table.workspaceId, table.attemptId],
|
|
2622
|
+
foreignColumns: [sessionTurnAttempts.workspaceId, sessionTurnAttempts.id],
|
|
2623
|
+
}).onDelete("restrict"),
|
|
2624
|
+
leaseGeneration: uniqueIndex("sandbox_workspace_mutation_admissions_lease_generation_uq").on(
|
|
2625
|
+
table.leaseId,
|
|
2626
|
+
table.workspaceGeneration,
|
|
2627
|
+
),
|
|
2628
|
+
scopedId: uniqueIndex("sandbox_workspace_mutation_admissions_scoped_id_uq").on(
|
|
2629
|
+
table.accountId,
|
|
2630
|
+
table.workspaceId,
|
|
2631
|
+
table.sessionId,
|
|
2632
|
+
table.leaseId,
|
|
2633
|
+
table.id,
|
|
2634
|
+
),
|
|
2635
|
+
blocking: index("sandbox_workspace_mutation_admissions_blocking_idx")
|
|
2636
|
+
.on(table.leaseId, table.workspaceGeneration)
|
|
2637
|
+
.where(sql`${table.settledAt} is null`),
|
|
2638
|
+
attempt: index("sandbox_workspace_mutation_admissions_attempt_idx").on(
|
|
2639
|
+
table.workspaceId,
|
|
2640
|
+
table.attemptId,
|
|
2641
|
+
),
|
|
2642
|
+
actor: index("sandbox_workspace_mutation_admissions_actor_idx").on(
|
|
2643
|
+
table.workspaceId,
|
|
2644
|
+
table.actorKind,
|
|
2645
|
+
table.actorId,
|
|
2646
|
+
),
|
|
2647
|
+
generationValid: check(
|
|
2648
|
+
"sandbox_workspace_mutation_admissions_generation_check",
|
|
2649
|
+
sql`${table.workspaceGeneration} > 0
|
|
2650
|
+
and ${table.leaseEpoch} >= 0
|
|
2651
|
+
and ${table.routeEpoch} >= 0
|
|
2652
|
+
and (${table.executionGeneration} is null or ${table.executionGeneration} > 0)`,
|
|
2653
|
+
),
|
|
2654
|
+
actorValid: check(
|
|
2655
|
+
"sandbox_workspace_mutation_admissions_actor_check",
|
|
2656
|
+
sql`(
|
|
2657
|
+
${table.actorKind} = 'turn'
|
|
2658
|
+
and ${table.actorId} = ${table.attemptId}
|
|
2659
|
+
and ${table.turnId} is not null
|
|
2660
|
+
and ${table.attemptId} is not null
|
|
2661
|
+
and ${table.executionGeneration} is not null
|
|
2662
|
+
and ${table.holderKind} = 'turn'
|
|
2663
|
+
) or (
|
|
2664
|
+
${table.actorKind} = 'direct'
|
|
2665
|
+
and ${table.turnId} is null
|
|
2666
|
+
and ${table.attemptId} is null
|
|
2667
|
+
and ${table.executionGeneration} is null
|
|
2668
|
+
and ${table.holderKind} = 'direct'
|
|
2669
|
+
) or (
|
|
2670
|
+
${table.actorKind} = 'process'
|
|
2671
|
+
and ${table.turnId} is null
|
|
2672
|
+
and ${table.attemptId} is null
|
|
2673
|
+
and ${table.executionGeneration} is null
|
|
2674
|
+
and ${table.holderKind} = 'process'
|
|
2675
|
+
)`,
|
|
2676
|
+
),
|
|
2677
|
+
routeValid: check(
|
|
2678
|
+
"sandbox_workspace_mutation_admissions_route_check",
|
|
2679
|
+
sql`${table.actorKind} in ('turn', 'direct', 'process')
|
|
2680
|
+
and ${table.holderKind} in ('turn', 'direct', 'process')
|
|
2681
|
+
and octet_length(${table.holderId}) between 1 and 256
|
|
2682
|
+
and octet_length(${table.providerBackend}) between 1 and 64
|
|
2683
|
+
and octet_length(${table.providerInstanceId}) between 1 and 512
|
|
2684
|
+
and ${table.routeKind} in ('home', 'active')
|
|
2685
|
+
and (${table.routeKind} = 'active' or ${table.routeTargetId} is null)`,
|
|
2686
|
+
),
|
|
2687
|
+
operationValid: check(
|
|
2688
|
+
"sandbox_workspace_mutation_admissions_operation_check",
|
|
2689
|
+
sql`octet_length(${table.operation}) between 1 and 128`,
|
|
2690
|
+
),
|
|
2691
|
+
outcomeValid: check(
|
|
2692
|
+
"sandbox_workspace_mutation_admissions_outcome_check",
|
|
2693
|
+
sql`${table.providerOutcome} is null or ${table.providerOutcome} in ('resolved', 'rejected', 'retained')`,
|
|
2694
|
+
),
|
|
2695
|
+
settlementConsistent: check(
|
|
2696
|
+
"sandbox_workspace_mutation_admissions_settlement_check",
|
|
2697
|
+
sql`(${table.providerOutcome} is null and ${table.settledAt} is null)
|
|
2698
|
+
or (${table.providerOutcome} = 'retained' and ${table.settledAt} is null)
|
|
2699
|
+
or (${table.providerOutcome} in ('resolved', 'rejected') and ${table.settledAt} is not null)`,
|
|
2700
|
+
),
|
|
2701
|
+
}),
|
|
2702
|
+
);
|
|
2703
|
+
|
|
2704
|
+
export const sandboxRetainedProcessStateValues = ["active", "exited", "lost"] as const;
|
|
2705
|
+
|
|
2706
|
+
// A yielded exec is not merely a numeric provider session id: it is a durable
|
|
2707
|
+
// continuation of the exact admitted mutation and owns a non-TTL process lease
|
|
2708
|
+
// holder until exit/loss is proven. Every later model-facing stdin write gets a
|
|
2709
|
+
// distinct actor_kind='process' admission tied back to this identity. Control
|
|
2710
|
+
// polling may use the pinned provider route without creating a new generation.
|
|
2711
|
+
export const sandboxRetainedProcesses = pgTable(
|
|
2712
|
+
"sandbox_retained_processes",
|
|
2713
|
+
{
|
|
2714
|
+
id: uuid("id").primaryKey().defaultRandom(),
|
|
2715
|
+
accountId: uuid("account_id").notNull(),
|
|
2716
|
+
workspaceId: uuid("workspace_id").notNull(),
|
|
2717
|
+
sessionId: uuid("session_id").notNull(),
|
|
2718
|
+
leaseId: uuid("lease_id").notNull(),
|
|
2719
|
+
sandboxGroupId: uuid("sandbox_group_id").notNull(),
|
|
2720
|
+
parentAdmissionId: uuid("parent_admission_id").notNull(),
|
|
2721
|
+
holderId: text("holder_id").notNull(),
|
|
2722
|
+
ownerActorKind: text("owner_actor_kind", { enum: ["turn", "direct"] }).notNull(),
|
|
2723
|
+
ownerActorId: uuid("owner_actor_id").notNull(),
|
|
2724
|
+
ownerTurnId: uuid("owner_turn_id"),
|
|
2725
|
+
ownerAttemptId: uuid("owner_attempt_id"),
|
|
2726
|
+
ownerExecutionGeneration: integer("owner_execution_generation"),
|
|
2727
|
+
leaseEpoch: integer("lease_epoch").notNull(),
|
|
2728
|
+
providerBackend: text("provider_backend").notNull(),
|
|
2729
|
+
providerInstanceId: text("provider_instance_id").notNull(),
|
|
2730
|
+
routeKind: text("route_kind", { enum: ["home", "active"] }).notNull(),
|
|
2731
|
+
routeTargetId: uuid("route_target_id"),
|
|
2732
|
+
routeEpoch: integer("route_epoch").notNull(),
|
|
2733
|
+
providerSessionId: integer("provider_session_id").notNull(),
|
|
2734
|
+
state: text("state", { enum: sandboxRetainedProcessStateValues }).notNull().default("active"),
|
|
2735
|
+
exitCode: integer("exit_code"),
|
|
2736
|
+
settlementReason: text("settlement_reason"),
|
|
2737
|
+
startedAt: timestamp("started_at", { withTimezone: true }).notNull().defaultNow(),
|
|
2738
|
+
settledAt: timestamp("settled_at", { withTimezone: true }),
|
|
2739
|
+
},
|
|
2740
|
+
(table) => ({
|
|
2741
|
+
workspaceAccount: foreignKey({
|
|
2742
|
+
name: "sandbox_retained_processes_workspace_account_fk",
|
|
2743
|
+
columns: [table.workspaceId, table.accountId],
|
|
2744
|
+
foreignColumns: [workspaces.id, workspaces.accountId],
|
|
2745
|
+
}).onDelete("cascade"),
|
|
2746
|
+
workspaceSession: foreignKey({
|
|
2747
|
+
name: "sandbox_retained_processes_workspace_session_fk",
|
|
2748
|
+
columns: [table.workspaceId, table.sessionId],
|
|
2749
|
+
foreignColumns: [sessions.workspaceId, sessions.id],
|
|
2750
|
+
}).onDelete("restrict"),
|
|
2751
|
+
parentAdmissionScope: foreignKey({
|
|
2752
|
+
name: "sandbox_retained_processes_parent_admission_scope_fk",
|
|
2753
|
+
columns: [
|
|
2754
|
+
table.accountId,
|
|
2755
|
+
table.workspaceId,
|
|
2756
|
+
table.sessionId,
|
|
2757
|
+
table.leaseId,
|
|
2758
|
+
table.parentAdmissionId,
|
|
2759
|
+
],
|
|
2760
|
+
foreignColumns: [
|
|
2761
|
+
sandboxWorkspaceMutationAdmissions.accountId,
|
|
2762
|
+
sandboxWorkspaceMutationAdmissions.workspaceId,
|
|
2763
|
+
sandboxWorkspaceMutationAdmissions.sessionId,
|
|
2764
|
+
sandboxWorkspaceMutationAdmissions.leaseId,
|
|
2765
|
+
sandboxWorkspaceMutationAdmissions.id,
|
|
2766
|
+
],
|
|
2767
|
+
}).onDelete("restrict"),
|
|
2768
|
+
scopedId: uniqueIndex("sandbox_retained_processes_scoped_id_uq").on(
|
|
2769
|
+
table.accountId,
|
|
2770
|
+
table.workspaceId,
|
|
2771
|
+
table.sessionId,
|
|
2772
|
+
table.leaseId,
|
|
2773
|
+
table.id,
|
|
2774
|
+
),
|
|
2775
|
+
parentAdmission: uniqueIndex("sandbox_retained_processes_parent_admission_uq").on(
|
|
2776
|
+
table.parentAdmissionId,
|
|
2777
|
+
),
|
|
2778
|
+
liveProviderSession: uniqueIndex("sandbox_retained_processes_live_provider_session_uq")
|
|
2779
|
+
.on(
|
|
2780
|
+
table.leaseId,
|
|
2781
|
+
table.leaseEpoch,
|
|
2782
|
+
table.providerInstanceId,
|
|
2783
|
+
table.routeEpoch,
|
|
2784
|
+
table.providerSessionId,
|
|
2785
|
+
)
|
|
2786
|
+
.where(sql`${table.state} = 'active'`),
|
|
2787
|
+
holder: uniqueIndex("sandbox_retained_processes_holder_uq").on(table.leaseId, table.holderId),
|
|
2788
|
+
active: index("sandbox_retained_processes_active_idx")
|
|
2789
|
+
.on(table.workspaceId, table.sessionId, table.startedAt)
|
|
2790
|
+
.where(sql`${table.state} = 'active'`),
|
|
2791
|
+
identityValid: check(
|
|
2792
|
+
"sandbox_retained_processes_identity_check",
|
|
2793
|
+
sql`${table.leaseEpoch} >= 0
|
|
2794
|
+
and ${table.routeEpoch} >= 0
|
|
2795
|
+
and ${table.providerSessionId} > 0
|
|
2796
|
+
and octet_length(${table.holderId}) between 1 and 256
|
|
2797
|
+
and octet_length(${table.providerBackend}) between 1 and 64
|
|
2798
|
+
and octet_length(${table.providerInstanceId}) between 1 and 512
|
|
2799
|
+
and (${table.routeKind} = 'active' or ${table.routeTargetId} is null)`,
|
|
2800
|
+
),
|
|
2801
|
+
ownerValid: check(
|
|
2802
|
+
"sandbox_retained_processes_owner_check",
|
|
2803
|
+
sql`(
|
|
2804
|
+
${table.ownerActorKind} = 'turn'
|
|
2805
|
+
and ${table.ownerActorId} = ${table.ownerAttemptId}
|
|
2806
|
+
and ${table.ownerTurnId} is not null
|
|
2807
|
+
and ${table.ownerAttemptId} is not null
|
|
2808
|
+
and ${table.ownerExecutionGeneration} > 0
|
|
2809
|
+
) or (
|
|
2810
|
+
${table.ownerActorKind} = 'direct'
|
|
2811
|
+
and ${table.ownerTurnId} is null
|
|
2812
|
+
and ${table.ownerAttemptId} is null
|
|
2813
|
+
and ${table.ownerExecutionGeneration} is null
|
|
2814
|
+
)`,
|
|
2815
|
+
),
|
|
2816
|
+
settlementValid: check(
|
|
2817
|
+
"sandbox_retained_processes_settlement_check",
|
|
2818
|
+
sql`(${table.state} = 'active' and ${table.settledAt} is null and ${table.exitCode} is null)
|
|
2819
|
+
or (${table.state} = 'exited' and ${table.settledAt} is not null)
|
|
2820
|
+
or (${table.state} = 'lost' and ${table.settledAt} is not null and ${table.exitCode} is null)`,
|
|
2821
|
+
),
|
|
2822
|
+
reasonValid: check(
|
|
2823
|
+
"sandbox_retained_processes_reason_check",
|
|
2824
|
+
sql`${table.settlementReason} is null
|
|
2825
|
+
or octet_length(${table.settlementReason}) between 1 and 512`,
|
|
2826
|
+
),
|
|
2827
|
+
}),
|
|
2828
|
+
);
|
|
2829
|
+
|
|
2369
2830
|
// The recording lifecycle states (P4.3). Exported so the activity + the query
|
|
2370
2831
|
// layer share one source of truth for the §3.1 state machine.
|
|
2371
2832
|
export const sessionRecordingStateValues = [
|
|
@@ -2486,14 +2947,12 @@ export const workspaceCaptures = pgTable(
|
|
|
2486
2947
|
}),
|
|
2487
2948
|
);
|
|
2488
2949
|
|
|
2489
|
-
// Interactive PTY sessions.
|
|
2490
|
-
//
|
|
2491
|
-
//
|
|
2492
|
-
//
|
|
2493
|
-
//
|
|
2494
|
-
//
|
|
2495
|
-
// a last_input_at heartbeat so the reaper can kill idle/orphaned PTYs. Mirrors
|
|
2496
|
-
// the account/workspace/session FK chain of sandboxSessionEnvelopes.
|
|
2950
|
+
// Interactive PTY sessions. An OPEN PTY adopts one exact retained process; the
|
|
2951
|
+
// provider's numeric exec-session id is only a copied locator and never authority
|
|
2952
|
+
// on its own. Provider/lease/route/admission identity is copied onto the row so a
|
|
2953
|
+
// stale pointer or box epoch cannot redirect control to a rival process. Legacy
|
|
2954
|
+
// numeric-only rows are closed by the maintenance cutover and may retain null
|
|
2955
|
+
// identity columns only in that terminal state.
|
|
2497
2956
|
export const sandboxPtySessions = pgTable(
|
|
2498
2957
|
"sandbox_pty_sessions",
|
|
2499
2958
|
{
|
|
@@ -2507,10 +2966,18 @@ export const sandboxPtySessions = pgTable(
|
|
|
2507
2966
|
sessionId: uuid("session_id")
|
|
2508
2967
|
.notNull()
|
|
2509
2968
|
.references(() => sessions.id, { onDelete: "cascade" }),
|
|
2510
|
-
|
|
2511
|
-
|
|
2969
|
+
leaseId: uuid("lease_id"),
|
|
2970
|
+
sandboxGroupId: uuid("sandbox_group_id"),
|
|
2971
|
+
retainedProcessId: uuid("retained_process_id"),
|
|
2972
|
+
openAdmissionId: uuid("open_admission_id"),
|
|
2973
|
+
// Copied provider locator for the adopted retained process.
|
|
2512
2974
|
execSessionId: integer("exec_session_id"),
|
|
2513
|
-
leaseEpoch: integer("lease_epoch").notNull(),
|
|
2975
|
+
leaseEpoch: integer("lease_epoch").notNull(),
|
|
2976
|
+
providerBackend: text("provider_backend"),
|
|
2977
|
+
providerInstanceId: text("provider_instance_id"),
|
|
2978
|
+
routeKind: text("route_kind", { enum: ["home", "active"] }),
|
|
2979
|
+
routeTargetId: uuid("route_target_id"),
|
|
2980
|
+
routeEpoch: integer("route_epoch"),
|
|
2514
2981
|
cols: integer("cols").notNull(),
|
|
2515
2982
|
rows: integer("rows").notNull(),
|
|
2516
2983
|
shell: text("shell").notNull(),
|
|
@@ -2524,9 +2991,46 @@ export const sandboxPtySessions = pgTable(
|
|
|
2524
2991
|
closedAt: timestamp("closed_at", { withTimezone: true }),
|
|
2525
2992
|
},
|
|
2526
2993
|
(table) => ({
|
|
2994
|
+
retainedProcessScope: foreignKey({
|
|
2995
|
+
name: "sandbox_pty_sessions_retained_process_scope_fk",
|
|
2996
|
+
columns: [
|
|
2997
|
+
table.accountId,
|
|
2998
|
+
table.workspaceId,
|
|
2999
|
+
table.sessionId,
|
|
3000
|
+
table.leaseId,
|
|
3001
|
+
table.retainedProcessId,
|
|
3002
|
+
],
|
|
3003
|
+
foreignColumns: [
|
|
3004
|
+
sandboxRetainedProcesses.accountId,
|
|
3005
|
+
sandboxRetainedProcesses.workspaceId,
|
|
3006
|
+
sandboxRetainedProcesses.sessionId,
|
|
3007
|
+
sandboxRetainedProcesses.leaseId,
|
|
3008
|
+
sandboxRetainedProcesses.id,
|
|
3009
|
+
],
|
|
3010
|
+
}).onDelete("restrict"),
|
|
2527
3011
|
openIdx: index("sandbox_pty_sessions_session_idx")
|
|
2528
3012
|
.on(table.workspaceId, table.sessionId)
|
|
2529
3013
|
.where(sql`${table.status} = 'open'`),
|
|
3014
|
+
processIdx: uniqueIndex("sandbox_pty_sessions_open_process_uq")
|
|
3015
|
+
.on(table.retainedProcessId)
|
|
3016
|
+
.where(sql`${table.status} = 'open'`),
|
|
3017
|
+
openIdentityValid: check(
|
|
3018
|
+
"sandbox_pty_sessions_open_identity_check",
|
|
3019
|
+
sql`${table.status} <> 'open' or (
|
|
3020
|
+
${table.leaseId} is not null
|
|
3021
|
+
and ${table.sandboxGroupId} is not null
|
|
3022
|
+
and ${table.retainedProcessId} is not null
|
|
3023
|
+
and ${table.openAdmissionId} is not null
|
|
3024
|
+
and ${table.execSessionId} > 0
|
|
3025
|
+
and octet_length(${table.providerBackend}) between 1 and 64
|
|
3026
|
+
and octet_length(${table.providerInstanceId}) between 1 and 512
|
|
3027
|
+
and ${table.routeKind} in ('home', 'active')
|
|
3028
|
+
and (${table.routeKind} = 'active' or ${table.routeTargetId} is null)
|
|
3029
|
+
and ${table.routeEpoch} is not null
|
|
3030
|
+
and ${table.leaseEpoch} >= 0
|
|
3031
|
+
and ${table.routeEpoch} >= 0
|
|
3032
|
+
)`,
|
|
3033
|
+
),
|
|
2530
3034
|
}),
|
|
2531
3035
|
);
|
|
2532
3036
|
|