@opengeni/db 4.2.2 → 4.3.0-canary.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.
Files changed (102) hide show
  1. package/dist/canonical-human-identities.js +3 -3
  2. package/dist/{chunk-6GAPAYZR.js → chunk-7JPLGBSA.js} +562 -86
  3. package/dist/chunk-7JPLGBSA.js.map +1 -0
  4. package/dist/{chunk-SNLIKELL.js → chunk-IHADTE7C.js} +2 -2
  5. package/dist/{chunk-7WX3R3YL.js → chunk-ILKJKDII.js} +7 -2
  6. package/dist/chunk-ILKJKDII.js.map +1 -0
  7. package/dist/{chunk-MGVOYVPS.js → chunk-NCSPNCQK.js} +3 -3
  8. package/dist/{chunk-B2KR3TEM.js → chunk-SGJDIF2D.js} +2 -2
  9. package/dist/{chunk-S4Y42VSX.js → chunk-Y5XFVJJM.js} +207 -3
  10. package/dist/chunk-Y5XFVJJM.js.map +1 -0
  11. package/dist/{chunk-FPTI4NP4.js → chunk-YGBOVXC7.js} +2 -2
  12. package/dist/{chunk-6Y7ZDVJ5.js → chunk-YGRT6VZO.js} +2 -2
  13. package/dist/{chunk-6IQ4X35Y.js → chunk-YVYBAWBU.js} +46 -1
  14. package/dist/chunk-YVYBAWBU.js.map +1 -0
  15. package/dist/connect-attempts.d.ts +60 -0
  16. package/dist/connection-setup-authority.d.ts +10 -0
  17. package/dist/connection-token-resolver.d.ts +11 -2
  18. package/dist/editable-artifact-durable-export.js +2 -2
  19. package/dist/editable-artifacts.js +3 -3
  20. package/dist/external-identities.d.ts +16 -0
  21. package/dist/external-identity-links.d.ts +74 -0
  22. package/dist/external-link-work.d.ts +51 -0
  23. package/dist/host-mcp-binding-match.d.ts +5 -0
  24. package/dist/host-mcp-bindings.d.ts +73 -0
  25. package/dist/host-mcp-task-authority.d.ts +47 -0
  26. package/dist/host-selection-identity.d.ts +6 -0
  27. package/dist/index.d.ts +51 -35
  28. package/dist/index.js +15171 -13775
  29. package/dist/index.js.map +1 -1
  30. package/dist/live-session-attempt.d.ts +275 -0
  31. package/dist/managed-auth-session-sets.js +3 -3
  32. package/dist/memory-domain.d.ts +3 -3
  33. package/dist/provision-roles.js +1 -1
  34. package/dist/retained-provider-commands.js +2 -2
  35. package/dist/runtime-posture.d.ts +6 -6
  36. package/dist/scheduled-task-revision-authority.d.ts +11 -0
  37. package/dist/schema.d.ts +1279 -9
  38. package/dist/schema.js +11 -1
  39. package/dist/session-background-commands.js +4 -4
  40. package/dist/session-command-output.js +4 -4
  41. package/dist/session-event-slices.js +2 -2
  42. package/dist/session-queue-commands.d.ts +7 -0
  43. package/dist/session-tenancy.d.ts +2 -0
  44. package/dist/session-tenancy.js +3 -3
  45. package/dist/video-generation.js +3 -3
  46. package/dist/workspace-authority.d.ts +4 -4
  47. package/dist/workspace-tool-defaults.js +4 -4
  48. package/drizzle/0437_organization_scoped_external_workspaces.sql +71 -0
  49. package/drizzle/0438_durable_connect_attempts.sql +95 -0
  50. package/drizzle/0439_external_identity_provisioning.sql +128 -0
  51. package/drizzle/0440_external_workspace_member_removal.sql +59 -0
  52. package/drizzle/0441_external_identity_membership_lifecycle.sql +163 -0
  53. package/drizzle/0442_external_owning_user_authority.sql +81 -0
  54. package/drizzle/0443_host_mcp_binding_registry.sql +93 -0
  55. package/drizzle/0444_host_mcp_delegations.sql +129 -0
  56. package/drizzle/0445_host_mcp_turn_authorities.sql +145 -0
  57. package/drizzle/0446_host_mcp_causal_continuation.sql +126 -0
  58. package/drizzle/0447_host_mcp_task_authorities.sql +264 -0
  59. package/drizzle/0448_host_mcp_child_authority.sql +115 -0
  60. package/drizzle/0449_external_identity_link_lifecycle.sql +107 -0
  61. package/drizzle/0450_external_identity_link_work.sql +179 -0
  62. package/drizzle/0451_external_link_preview_and_permission_ceiling.sql +82 -0
  63. package/drizzle/0452_external_link_scheduled_origin.sql +34 -0
  64. package/drizzle/0453_host_mcp_native_owner.sql +35 -0
  65. package/drizzle/0454_connect_origin_authority.sql +42 -0
  66. package/drizzle/0455_external_link_inventory_labels.sql +44 -0
  67. package/drizzle/0456_social_connection_versions.sql +14 -0
  68. package/drizzle/0457_canonical_session_scope_subject.sql +46 -0
  69. package/drizzle/0458_skill_review_wire_compatibility.sql +36 -0
  70. package/package.json +6 -6
  71. package/src/connect-attempts.ts +317 -0
  72. package/src/connection-authority.ts +9 -0
  73. package/src/connection-setup-authority.ts +35 -0
  74. package/src/connection-token-resolver.ts +177 -48
  75. package/src/external-identities.ts +70 -0
  76. package/src/external-identity-links.ts +364 -0
  77. package/src/external-link-work.ts +228 -0
  78. package/src/host-mcp-binding-match.ts +33 -0
  79. package/src/host-mcp-bindings.ts +741 -0
  80. package/src/host-mcp-task-authority.ts +383 -0
  81. package/src/host-selection-identity.ts +29 -0
  82. package/src/index.ts +398 -147
  83. package/src/live-session-attempt.ts +85 -0
  84. package/src/managed-human-provisioning.ts +6 -1
  85. package/src/memory-domain.ts +6 -11
  86. package/src/provision-roles.ts +3 -0
  87. package/src/runtime-posture.ts +47 -0
  88. package/src/scheduled-task-revision-authority.ts +30 -0
  89. package/src/schema.ts +228 -3
  90. package/src/session-control.ts +14 -0
  91. package/src/session-queue-commands.ts +11 -0
  92. package/src/session-tenancy.ts +7 -0
  93. package/src/workspace-authority.ts +5 -5
  94. package/dist/chunk-6GAPAYZR.js.map +0 -1
  95. package/dist/chunk-6IQ4X35Y.js.map +0 -1
  96. package/dist/chunk-7WX3R3YL.js.map +0 -1
  97. package/dist/chunk-S4Y42VSX.js.map +0 -1
  98. /package/dist/{chunk-SNLIKELL.js.map → chunk-IHADTE7C.js.map} +0 -0
  99. /package/dist/{chunk-MGVOYVPS.js.map → chunk-NCSPNCQK.js.map} +0 -0
  100. /package/dist/{chunk-B2KR3TEM.js.map → chunk-SGJDIF2D.js.map} +0 -0
  101. /package/dist/{chunk-FPTI4NP4.js.map → chunk-YGBOVXC7.js.map} +0 -0
  102. /package/dist/{chunk-6Y7ZDVJ5.js.map → chunk-YGRT6VZO.js.map} +0 -0
@@ -1,11 +1,16 @@
1
1
  import {
2
2
  cancelUnacceptedVideoGenerationsForToolCallsInTransaction
3
- } from "./chunk-MGVOYVPS.js";
3
+ } from "./chunk-NCSPNCQK.js";
4
4
  import {
5
5
  nestedPostgresSqlState,
6
+ rawRows,
7
+ setSubjectRlsContext,
8
+ withAccountRls,
6
9
  withRlsContext,
7
- withSessionActivityRlsContext
8
- } from "./chunk-B2KR3TEM.js";
10
+ withSessionActivityRlsContext,
11
+ withWorkspaceRls,
12
+ withWorkspaceSubjectRls
13
+ } from "./chunk-SGJDIF2D.js";
9
14
  import {
10
15
  LOSSLESS_CONTENT_CODEC_VERSION,
11
16
  auditEvents,
@@ -32,22 +37,460 @@ import {
32
37
  workspaceControlEvents,
33
38
  workspaceInferenceControls,
34
39
  workspaces
35
- } from "./chunk-S4Y42VSX.js";
40
+ } from "./chunk-Y5XFVJJM.js";
36
41
 
37
42
  // src/session-background-commands.ts
38
43
  import { SessionCommandFailure } from "@opengeni/contracts";
39
44
  import { isDeepStrictEqual } from "util";
40
- import { and as and4, asc as asc2, desc as desc2, eq as eq4, getTableColumns, gte, inArray as inArray3, sql as sql4 } from "drizzle-orm";
45
+ import { and as and4, asc as asc2, desc as desc2, eq as eq4, getTableColumns, gte, inArray as inArray3, sql as sql7 } from "drizzle-orm";
41
46
 
42
47
  // src/session-control.ts
43
- import { createHash as createHash2 } from "crypto";
48
+ import { createHash as createHash3 } from "crypto";
44
49
  import {
45
50
  boundWorkspaceControlEvent,
46
51
  childPausedClassification,
47
52
  McpPersonalConnectionDelegations,
48
53
  workspaceControlUtf8Bytes
49
54
  } from "@opengeni/contracts";
50
- import { and as and3, eq as eq3, inArray as inArray2, sql as sql3 } from "drizzle-orm";
55
+ import { and as and3, eq as eq3, inArray as inArray2, sql as sql6 } from "drizzle-orm";
56
+
57
+ // src/external-link-work.ts
58
+ import { sql as sql3 } from "drizzle-orm";
59
+ import { stableJson } from "@opengeni/contracts";
60
+ import { ExternalLinkWorkSnapshot } from "@opengeni/contracts/external-identities";
61
+
62
+ // src/external-identities.ts
63
+ import { sql } from "drizzle-orm";
64
+ import { Permission } from "@opengeni/contracts";
65
+ import {
66
+ ExternalIdentity,
67
+ ExternalIdentityReference
68
+ } from "@opengeni/contracts/external-identities";
69
+ async function lockActiveExternalOrganizationKey(tx, accountId, keyId) {
70
+ return withAccountRls(tx, accountId, async (scoped) => {
71
+ const [row] = await rawRows(
72
+ scoped,
73
+ sql`select permissions from api_keys
74
+ where account_id = ${accountId}::uuid and id = ${keyId}::uuid
75
+ and workspace_id is null and credential_kind = 'organization'
76
+ and revoked_at is null and (expires_at is null or expires_at > clock_timestamp()) for share`
77
+ );
78
+ return row ? Permission.array().parse(row.permissions) : null;
79
+ });
80
+ }
81
+ async function lockExternalWorkspaceMembershipLifecycle(tx, accountId) {
82
+ await tx.execute(
83
+ sql`select pg_advisory_xact_lock(hashtextextended(${`organization-membership:${accountId}`}, 0))`
84
+ );
85
+ }
86
+ async function ensureExternalIdentity(db, input) {
87
+ const accountId = input.accountId;
88
+ const reference = ExternalIdentityReference.parse({
89
+ externalId: input.externalId,
90
+ source: input.source
91
+ });
92
+ return withAccountRls(db, accountId, async (tx) => {
93
+ const [row] = await rawRows(
94
+ tx,
95
+ sql`select ensure_external_identity(
96
+ ${accountId}::uuid, ${reference.source}, ${reference.externalId}) as result`
97
+ );
98
+ const result = ExternalIdentity.parse(row?.result);
99
+ if (result.accountId !== accountId || result.source !== reference.source || result.externalId !== reference.externalId) {
100
+ throw new Error("External identity scope mismatch");
101
+ }
102
+ return result;
103
+ });
104
+ }
105
+
106
+ // src/external-identity-links.ts
107
+ import { createHash, randomBytes, randomUUID } from "crypto";
108
+ import { sql as sql2 } from "drizzle-orm";
109
+ import {
110
+ BeginExternalIdentityLinkRequest,
111
+ BeginExternalIdentityLinkResponse,
112
+ ConfirmExternalIdentityLinkRequest,
113
+ ExternalIdentityLink,
114
+ ExternalIdentityLinkPage,
115
+ ExternalIdentityReference as ExternalIdentityReference2
116
+ } from "@opengeni/contracts/external-identities";
117
+ var ExternalIdentityLinkConflictError = class extends Error {
118
+ name = "ExternalIdentityLinkConflictError";
119
+ constructor() {
120
+ super("Identity link changed or is unavailable");
121
+ }
122
+ };
123
+ var digest = (value) => createHash("sha256").update(value).digest("hex");
124
+ var iso = (value) => new Date(value).toISOString();
125
+ function project(row) {
126
+ const expiry = row.status === "pending" ? row.confirm_before : row.expires_at;
127
+ return ExternalIdentityLink.parse({
128
+ id: row.id,
129
+ accountId: row.account_id,
130
+ externalIdentityId: row.external_identity_id,
131
+ nativeSubjectId: row.native_subject_id,
132
+ status: row.status !== "revoked" && expiry !== null && new Date(expiry).getTime() <= Date.now() ? "expired" : row.status,
133
+ revision: Number(row.revision),
134
+ permissions: row.permissions,
135
+ expiresAt: row.expires_at === null ? null : iso(row.expires_at)
136
+ });
137
+ }
138
+ async function activeMembership(tx, accountId, subjectId) {
139
+ const [prior] = await rawRows(
140
+ tx,
141
+ sql2`select coalesce(current_setting('opengeni.subject_id', true), '') as subject`
142
+ );
143
+ let succeeded = false;
144
+ let row;
145
+ try {
146
+ await setSubjectRlsContext(tx, subjectId);
147
+ [row] = await rawRows(
148
+ tx,
149
+ sql2`select value as membership from jsonb_array_elements(list_self_organization_memberships(${subjectId}))
150
+ where value ->> 'organizationId' = ${accountId} and value ->> 'status' = 'active'`
151
+ );
152
+ succeeded = true;
153
+ } finally {
154
+ const restore = tx.execute(
155
+ sql2`select set_config('opengeni.subject_id', ${prior?.subject ?? ""}, true)`
156
+ );
157
+ if (succeeded) await restore;
158
+ else await restore.catch(() => void 0);
159
+ }
160
+ if (!row) throw new ExternalIdentityLinkConflictError();
161
+ return row.membership;
162
+ }
163
+ async function beginExternalIdentityLink(db, identity, raw) {
164
+ const input = BeginExternalIdentityLinkRequest.parse(raw);
165
+ return withAccountRls(db, identity.accountId, async (tx) => {
166
+ await lockExternalWorkspaceMembershipLifecycle(tx, identity.accountId);
167
+ const membership = await activeMembership(tx, identity.accountId, identity.subjectId);
168
+ if (membership.id !== identity.organizationMembershipId || Number(membership.authorizationRevision) !== identity.authorizationRevision || identity.status !== "active")
169
+ throw new ExternalIdentityLinkConflictError();
170
+ const [quota] = await rawRows(
171
+ tx,
172
+ sql2`select count(*) as count
173
+ from external_identity_links where account_id = ${identity.accountId}::uuid
174
+ and external_identity_id = ${identity.id}::uuid and status = 'pending'
175
+ and confirm_before > clock_timestamp()`
176
+ );
177
+ if (Number(quota?.count ?? 0) >= 32) throw new ExternalIdentityLinkConflictError();
178
+ const challenge = randomBytes(32).toString("base64url");
179
+ const permissions = [...new Set(input.permissions)].sort();
180
+ const [row] = await rawRows(
181
+ tx,
182
+ sql2`insert into external_identity_links
183
+ (id, account_id, external_identity_id, external_subject_id, external_authorization_revision,
184
+ permissions, challenge_digest, confirm_before, expires_at)
185
+ values (${randomUUID()}::uuid, ${identity.accountId}::uuid, ${identity.id}::uuid,
186
+ ${identity.subjectId}, ${identity.authorizationRevision}, ${JSON.stringify(permissions)}::jsonb,
187
+ ${digest(challenge)}, clock_timestamp() + interval '10 minutes', ${input.expiresAt}::timestamptz)
188
+ returning *`
189
+ );
190
+ if (!row) throw new Error("Identity link insert returned no row");
191
+ return BeginExternalIdentityLinkResponse.parse({
192
+ link: project(row),
193
+ challenge,
194
+ confirmBefore: iso(row.confirm_before)
195
+ });
196
+ });
197
+ }
198
+ async function getExternalIdentityLink(db, input) {
199
+ return withAccountRls(db, input.accountId, async (tx) => {
200
+ const [row] = await rawRows(
201
+ tx,
202
+ sql2`select * from external_identity_links
203
+ where account_id = ${input.accountId}::uuid and id = ${input.linkId}::uuid
204
+ and (external_subject_id = ${input.subjectId} or native_subject_id = ${input.subjectId})`
205
+ );
206
+ return row ? project(row) : null;
207
+ });
208
+ }
209
+ async function listExternalIdentityLinks(db, input) {
210
+ return withAccountRls(db, input.accountId, async (tx) => {
211
+ const rows = await rawRows(
212
+ tx,
213
+ sql2`
214
+ select * from external_identity_links
215
+ where account_id = ${input.accountId}::uuid
216
+ and (external_subject_id = ${input.subjectId} or native_subject_id = ${input.subjectId})
217
+ ${input.cursor ? sql2`and id > ${input.cursor}::uuid` : sql2``}
218
+ order by id limit 51`
219
+ );
220
+ const links = rows.slice(0, 50).map(project);
221
+ await setSubjectRlsContext(tx, input.subjectId);
222
+ const [labels] = links.length ? await rawRows(
223
+ tx,
224
+ sql2`select get_external_identity_link_inventory_references(${input.accountId}::uuid, ARRAY[${sql2.join(
225
+ links.map((link) => sql2`${link.id}::uuid`),
226
+ sql2`, `
227
+ )}]) as references`
228
+ ) : [];
229
+ return ExternalIdentityLinkPage.parse({
230
+ links: links.map((link) => ({
231
+ ...link,
232
+ ...labels?.references[link.id] ? { externalIdentity: ExternalIdentityReference2.parse(labels.references[link.id]) } : {}
233
+ })),
234
+ nextCursor: rows.length > 50 ? links.at(-1).id : null
235
+ });
236
+ });
237
+ }
238
+ async function previewExternalIdentityLink(db, input) {
239
+ return withAccountRls(db, input.accountId, async (tx) => {
240
+ const [row] = await rawRows(
241
+ tx,
242
+ sql2`select * from external_identity_links
243
+ where account_id = ${input.accountId}::uuid and id = ${input.linkId}::uuid
244
+ and challenge_digest = ${digest(input.challenge)} and status = 'pending'
245
+ and confirm_before > clock_timestamp()
246
+ and (expires_at is null or expires_at > clock_timestamp())`
247
+ );
248
+ if (!row) return null;
249
+ const [identity] = await rawRows(
250
+ tx,
251
+ sql2`select get_external_identity_link_reference(${input.accountId}::uuid, ${input.linkId}::uuid, ${digest(input.challenge)}) as reference`
252
+ );
253
+ return identity?.reference ? {
254
+ link: project(row),
255
+ externalIdentity: ExternalIdentityReference2.parse(identity.reference)
256
+ } : null;
257
+ });
258
+ }
259
+ async function confirmExternalIdentityLink(db, input) {
260
+ const request = ConfirmExternalIdentityLinkRequest.parse(input.request);
261
+ if (!/^user:[^\r\n]+$/.test(input.nativeSubjectId)) throw new ExternalIdentityLinkConflictError();
262
+ return withAccountRls(db, input.accountId, async (tx) => {
263
+ await lockExternalWorkspaceMembershipLifecycle(tx, input.accountId);
264
+ const [row] = await rawRows(
265
+ tx,
266
+ sql2`select * from external_identity_links
267
+ where account_id = ${input.accountId}::uuid and id = ${input.linkId}::uuid
268
+ and challenge_digest = ${digest(request.challenge)} for update`
269
+ );
270
+ if (!row) throw new ExternalIdentityLinkConflictError();
271
+ const external = await activeMembership(tx, input.accountId, row.external_subject_id);
272
+ const native = await activeMembership(tx, input.accountId, input.nativeSubjectId);
273
+ if (Number(external.authorizationRevision) !== Number(row.external_authorization_revision))
274
+ throw new ExternalIdentityLinkConflictError();
275
+ const permissions = [...new Set(request.permissions)].sort();
276
+ if (row.status === "active" && Number(row.revision) === request.expectedRevision + 1 && row.native_subject_id === input.nativeSubjectId && row.native_membership_id === native.id && Number(row.native_authorization_revision) === Number(native.authorizationRevision) && JSON.stringify(row.permissions) === JSON.stringify(permissions) && project(row).status === "active")
277
+ return project(row);
278
+ if (row.status !== "pending" || Number(row.revision) !== request.expectedRevision || project(row).status !== "pending" || permissions.some((permission) => !row.permissions.includes(permission)))
279
+ throw new ExternalIdentityLinkConflictError();
280
+ const [confirmed] = await rawRows(
281
+ tx,
282
+ sql2`update external_identity_links set
283
+ status = 'active', revision = revision + 1, native_subject_id = ${input.nativeSubjectId},
284
+ native_membership_id = ${native.id}::uuid, native_authorization_revision = ${Number(native.authorizationRevision)},
285
+ permissions = ${JSON.stringify(permissions)}::jsonb, confirmed_at = clock_timestamp()
286
+ where id = ${row.id}::uuid returning *`
287
+ );
288
+ if (!confirmed) throw new ExternalIdentityLinkConflictError();
289
+ return project(confirmed);
290
+ });
291
+ }
292
+ async function revokeExternalIdentityLink(db, input) {
293
+ return withAccountRls(db, input.accountId, async (tx) => {
294
+ await lockExternalWorkspaceMembershipLifecycle(tx, input.accountId);
295
+ const [row] = await rawRows(
296
+ tx,
297
+ sql2`select * from external_identity_links
298
+ where account_id = ${input.accountId}::uuid and id = ${input.linkId}::uuid
299
+ and (external_subject_id = ${input.subjectId} or native_subject_id = ${input.subjectId}) for update`
300
+ );
301
+ if (!row) throw new ExternalIdentityLinkConflictError();
302
+ if (row.status === "revoked" && Number(row.revision) === input.expectedRevision + 1)
303
+ return project(row);
304
+ if (row.status === "revoked" || Number(row.revision) !== input.expectedRevision)
305
+ throw new ExternalIdentityLinkConflictError();
306
+ const [revoked] = await rawRows(
307
+ tx,
308
+ sql2`update external_identity_links
309
+ set status = 'revoked', revision = revision + 1, revoked_at = clock_timestamp()
310
+ where id = ${row.id}::uuid returning *`
311
+ );
312
+ if (!revoked) throw new ExternalIdentityLinkConflictError();
313
+ return project(revoked);
314
+ });
315
+ }
316
+ async function resolveExternalIdentityLink(db, input) {
317
+ return withAccountRls(db, input.identity.accountId, async (tx) => {
318
+ await lockExternalWorkspaceMembershipLifecycle(tx, input.identity.accountId);
319
+ const [row] = await rawRows(
320
+ tx,
321
+ sql2`select * from external_identity_links
322
+ where id = ${input.linkId}::uuid and account_id = ${input.identity.accountId}::uuid
323
+ and external_identity_id = ${input.identity.id}::uuid for share`
324
+ );
325
+ if (!row || row.status !== "active" || !row.native_subject_id || Number(row.revision) !== input.expectedRevision || Number(row.external_authorization_revision) !== input.identity.authorizationRevision || input.identity.status !== "active" || project(row).status !== "active")
326
+ return null;
327
+ try {
328
+ const external = await activeMembership(
329
+ tx,
330
+ input.identity.accountId,
331
+ input.identity.subjectId
332
+ );
333
+ const native = await activeMembership(tx, input.identity.accountId, row.native_subject_id);
334
+ if (external.id !== input.identity.organizationMembershipId || Number(external.authorizationRevision) !== input.identity.authorizationRevision || native.id !== row.native_membership_id || Number(native.authorizationRevision) !== Number(row.native_authorization_revision))
335
+ return null;
336
+ return { link: project(row), personalWorkspaceId: native.personalWorkspaceId };
337
+ } catch (error) {
338
+ if (error instanceof ExternalIdentityLinkConflictError) return null;
339
+ throw error;
340
+ }
341
+ });
342
+ }
343
+
344
+ // src/external-link-work.ts
345
+ async function externalLinkWorkSnapshotIsLive(db, raw) {
346
+ const snapshot = ExternalLinkWorkSnapshot.parse(raw);
347
+ try {
348
+ const identity = await ensureExternalIdentity(db, {
349
+ accountId: snapshot.actor.accountId,
350
+ ...snapshot.identity
351
+ });
352
+ if (identity.id !== snapshot.actor.externalIdentityId || identity.subjectId !== snapshot.actor.externalSubjectId || identity.authorizationRevision !== snapshot.actor.externalAuthorizationRevision)
353
+ return false;
354
+ const resolved = await resolveExternalIdentityLink(db, {
355
+ identity,
356
+ linkId: snapshot.actor.linkId,
357
+ expectedRevision: snapshot.actor.linkRevision
358
+ });
359
+ return resolved !== null && resolved.link.nativeSubjectId === snapshot.actor.effectiveSubjectId && snapshot.permissions.every(
360
+ (permission) => resolved.link.permissions.includes(permission) || permission !== "secrets:read" && resolved.link.permissions.includes("workspace:admin")
361
+ );
362
+ } catch (error) {
363
+ if (nestedPostgresSqlState(error) === "42501") return false;
364
+ throw error;
365
+ }
366
+ }
367
+ async function getExternalLinkTurnSnapshot(db, scope, turnId) {
368
+ return withWorkspaceRls(db, scope.workspaceId, async (tx) => {
369
+ const [row] = await rawRows(
370
+ tx,
371
+ sql3`select canonical_snapshot
372
+ from external_link_turn_authorities where account_id = ${scope.accountId}::uuid
373
+ and workspace_id = ${scope.workspaceId}::uuid and turn_id = ${turnId}::uuid`
374
+ );
375
+ return row ? ExternalLinkWorkSnapshot.parse(row.canonical_snapshot) : null;
376
+ });
377
+ }
378
+ async function getExternalLinkTurnAuthorization(db, scope, turnId) {
379
+ const snapshot = await getExternalLinkTurnSnapshot(db, scope, turnId);
380
+ if (!snapshot) return null;
381
+ return {
382
+ authorized: await externalLinkWorkSnapshotIsLive(db, snapshot),
383
+ permissions: snapshot.permissions
384
+ };
385
+ }
386
+ async function captureExternalLinkTurnAuthority(db, input) {
387
+ const snapshot = ExternalLinkWorkSnapshot.parse(input.snapshot);
388
+ const source = input.source ?? { kind: "direct" };
389
+ if (snapshot.actor.accountId !== input.accountId)
390
+ throw new Error("Linked turn organization mismatch");
391
+ if (source.kind === "direct" && !await externalLinkWorkSnapshotIsLive(db, snapshot))
392
+ throw new Error("Linked turn authority revoked");
393
+ await withWorkspaceSubjectRls(
394
+ db,
395
+ input.workspaceId,
396
+ snapshot.actor.effectiveSubjectId,
397
+ async (tx) => {
398
+ const existing = await getExternalLinkTurnSnapshot(tx, input, input.turnId);
399
+ if (existing) {
400
+ if (stableJson(existing) !== stableJson(snapshot))
401
+ throw new Error("Linked turn replay changed authority");
402
+ return;
403
+ }
404
+ await tx.execute(sql3`insert into external_link_turn_authorities
405
+ (turn_id, account_id, workspace_id, session_id, link_id, link_revision, canonical_snapshot,
406
+ source_kind, source_turn_id, source_task_id, source_task_revision)
407
+ values (${input.turnId}::uuid, ${input.accountId}::uuid, ${input.workspaceId}::uuid, ${input.sessionId}::uuid,
408
+ ${snapshot.actor.linkId}::uuid, ${snapshot.actor.linkRevision}, ${JSON.stringify(snapshot)}::jsonb, ${source.kind},
409
+ ${source.kind === "causal" || source.kind === "child" ? source.turnId : null}::uuid,
410
+ ${source.kind === "scheduled" ? source.taskId : null}::uuid,
411
+ ${source.kind === "scheduled" ? source.taskRevision : null})`);
412
+ }
413
+ );
414
+ }
415
+ async function inheritExternalLinkTurnAuthority(db, input) {
416
+ const snapshot = await getExternalLinkTurnSnapshot(db, input, input.sourceTurnId);
417
+ if (!snapshot) return;
418
+ await captureExternalLinkTurnAuthority(db, {
419
+ ...input,
420
+ snapshot,
421
+ source: { kind: input.kind, turnId: input.sourceTurnId }
422
+ });
423
+ }
424
+ async function getExternalLinkTaskSnapshot(db, input) {
425
+ return withWorkspaceRls(db, input.workspaceId, async (tx) => {
426
+ const [row] = await rawRows(
427
+ tx,
428
+ sql3`select canonical_snapshot
429
+ from external_link_task_authorities where account_id = ${input.accountId}::uuid
430
+ and workspace_id = ${input.workspaceId}::uuid and task_id = ${input.taskId}::uuid and task_revision = ${input.taskRevision}`
431
+ );
432
+ return row ? ExternalLinkWorkSnapshot.parse(row.canonical_snapshot) : null;
433
+ });
434
+ }
435
+ async function captureExternalLinkTaskAuthority(db, task, raw) {
436
+ const snapshot = ExternalLinkWorkSnapshot.parse(raw);
437
+ if (task.accountId !== snapshot.actor.accountId)
438
+ throw new Error("Linked task organization mismatch");
439
+ await withWorkspaceSubjectRls(
440
+ db,
441
+ task.workspaceId,
442
+ snapshot.actor.effectiveSubjectId,
443
+ async (tx) => {
444
+ const existing = await getExternalLinkTaskSnapshot(tx, {
445
+ ...task,
446
+ taskId: task.id,
447
+ taskRevision: task.authorityRevision
448
+ });
449
+ if (existing) {
450
+ if (stableJson(existing) !== stableJson(snapshot))
451
+ throw new Error("Linked task replay changed authority");
452
+ return;
453
+ }
454
+ await tx.execute(sql3`insert into external_link_task_authorities
455
+ (task_id, task_revision, account_id, workspace_id, link_id, link_revision, canonical_snapshot)
456
+ values (${task.id}::uuid, ${task.authorityRevision}, ${task.accountId}::uuid, ${task.workspaceId}::uuid,
457
+ ${snapshot.actor.linkId}::uuid, ${snapshot.actor.linkRevision}, ${JSON.stringify(snapshot)}::jsonb)`);
458
+ }
459
+ );
460
+ }
461
+ async function cloneExternalLinkTaskAuthority(db, task, sourceRevision) {
462
+ if (task.authorityRevision === sourceRevision) return;
463
+ const snapshot = await getExternalLinkTaskSnapshot(db, {
464
+ ...task,
465
+ taskId: task.id,
466
+ taskRevision: sourceRevision
467
+ });
468
+ if (snapshot) await captureExternalLinkTaskAuthority(db, task, snapshot);
469
+ }
470
+ async function captureScheduledExternalLinkTurnAuthority(db, input) {
471
+ const run = await withWorkspaceRls(db, input.workspaceId, async (tx) => {
472
+ const [row] = await rawRows(
473
+ tx,
474
+ sql3`select task_id, task_authority_revision from scheduled_task_runs
475
+ where account_id = ${input.accountId}::uuid and workspace_id = ${input.workspaceId}::uuid
476
+ and session_id = ${input.sessionId}::uuid and id = ${input.runId}::uuid`
477
+ );
478
+ return row;
479
+ });
480
+ if (!run) throw new Error("Linked schedule run unavailable");
481
+ const taskRevision = Number(run.task_authority_revision);
482
+ const snapshot = await getExternalLinkTaskSnapshot(db, {
483
+ ...input,
484
+ taskId: run.task_id,
485
+ taskRevision
486
+ });
487
+ if (snapshot)
488
+ await captureExternalLinkTurnAuthority(db, {
489
+ ...input,
490
+ snapshot,
491
+ source: { kind: "scheduled", taskId: run.task_id, taskRevision }
492
+ });
493
+ }
51
494
 
52
495
  // src/child-lifecycle-notices.ts
53
496
  import {
@@ -194,7 +637,7 @@ function boundedChildProgressNote(note) {
194
637
 
195
638
  // src/session-tool-call-settlement.ts
196
639
  import { canonicalizePersistedHistoryItem, omitOutputOnlyHistoryItemFields } from "@opengeni/codex";
197
- import { and, asc, eq, inArray, sql } from "drizzle-orm";
640
+ import { and, asc, eq, inArray, sql as sql4 } from "drizzle-orm";
198
641
  var TOOL_RESULT_TYPE_BY_CALL_TYPE = {
199
642
  function_call: "function_call_result",
200
643
  computer_call: "computer_call_result",
@@ -313,13 +756,13 @@ async function closePendingSessionToolCallsInTransaction(tx, input) {
313
756
  ...row,
314
757
  item: fromPostgresLosslessJson(row.item, row.itemCodecVersion)
315
758
  }));
316
- const [{ maxPosition } = { maxPosition: -1 }] = await tx.select({ maxPosition: sql`coalesce(max(${sessionHistoryItems.position}), -1)` }).from(sessionHistoryItems).where(
759
+ const [{ maxPosition } = { maxPosition: -1 }] = await tx.select({ maxPosition: sql4`coalesce(max(${sessionHistoryItems.position}), -1)` }).from(sessionHistoryItems).where(
317
760
  and(
318
761
  eq(sessionHistoryItems.workspaceId, input.workspaceId),
319
762
  eq(sessionHistoryItems.sessionId, input.sessionId)
320
763
  )
321
764
  );
322
- const existingOutputEvents = await tx.select({ callId: sql`${sessionEvents.payload} ->> 'id'` }).from(sessionEvents).where(
765
+ const existingOutputEvents = await tx.select({ callId: sql4`${sessionEvents.payload} ->> 'id'` }).from(sessionEvents).where(
323
766
  and(
324
767
  eq(sessionEvents.workspaceId, input.workspaceId),
325
768
  eq(sessionEvents.sessionId, input.sessionId),
@@ -460,13 +903,13 @@ async function closePendingSessionToolCallsInTransaction(tx, input) {
460
903
  }
461
904
 
462
905
  // src/session-realtime-mirror.ts
463
- import { createHash } from "crypto";
464
- import { and as and2, desc, eq as eq2, gt, sql as sql2 } from "drizzle-orm";
906
+ import { createHash as createHash2 } from "crypto";
907
+ import { and as and2, desc, eq as eq2, gt, sql as sql5 } from "drizzle-orm";
465
908
  var SESSION_REALTIME_MIRROR_MAX_TEXT_BYTES = 131072;
466
909
  var SESSION_REALTIME_MIRROR_MAX_PAYLOAD_BYTES = 131072;
467
910
  var TRUNCATION_MARKER = "\n\u2026realtime context truncated\u2026";
468
911
  function deterministicUuid(seed) {
469
- const bytes = createHash("sha256").update(seed, "utf8").digest().subarray(0, 16);
912
+ const bytes = createHash2("sha256").update(seed, "utf8").digest().subarray(0, 16);
470
913
  bytes[6] = (bytes[6] ?? 0) & 15 | 80;
471
914
  bytes[8] = (bytes[8] ?? 0) & 63 | 128;
472
915
  const hex = bytes.toString("hex");
@@ -517,7 +960,7 @@ async function mirrorSessionRealtimeContextInTransaction(db, input) {
517
960
  )
518
961
  ).limit(1);
519
962
  if (existing) return { entry: existing, replay: true };
520
- const [sequenceRow] = await db.select({ next: sql2`coalesce(max(${sessionRealtimeEntries.sequence}), 0) + 1` }).from(sessionRealtimeEntries).where(eq2(sessionRealtimeEntries.realtimeId, mode.id));
963
+ const [sequenceRow] = await db.select({ next: sql5`coalesce(max(${sessionRealtimeEntries.sequence}), 0) + 1` }).from(sessionRealtimeEntries).where(eq2(sessionRealtimeEntries.realtimeId, mode.id));
521
964
  const payload = boundedPayload({
522
965
  ...input.payload ?? {},
523
966
  source: input.sourceKind,
@@ -718,7 +1161,7 @@ async function assertAgentCommandAuthorityInTransaction(db, input) {
718
1161
  if (!targetSession) {
719
1162
  throw new SessionControlInvariantError(`Target session not found: ${input.targetSessionId}`);
720
1163
  }
721
- const rows = await db.execute(sql3`
1164
+ const rows = await db.execute(sql6`
722
1165
  select
723
1166
  attempt.id as "attemptId",
724
1167
  attempt.state as "attemptState",
@@ -756,6 +1199,19 @@ async function assertAgentCommandAuthorityInTransaction(db, input) {
756
1199
  "The calling agent attempt is being interrupted"
757
1200
  );
758
1201
  }
1202
+ const linked = await getExternalLinkTurnAuthorization(
1203
+ db,
1204
+ {
1205
+ accountId: callerSession.accountId,
1206
+ workspaceId: input.workspaceId
1207
+ },
1208
+ input.actor.turnId
1209
+ );
1210
+ if (linked && !linked.authorized)
1211
+ throw new AgentCommandAuthorityError(
1212
+ "CALLER_STALE",
1213
+ "The calling agent's native identity link is no longer active"
1214
+ );
759
1215
  if (input.action === "steer" && input.targetSessionId === input.actor.sessionId) {
760
1216
  throw new AgentCommandAuthorityError("SELF_STEER", "An agent cannot steer its own session");
761
1217
  }
@@ -782,14 +1238,14 @@ function canonicalize(value) {
782
1238
  return value;
783
1239
  }
784
1240
  function canonicalSessionCommandHash(value) {
785
- return createHash2("sha256").update(JSON.stringify(canonicalize(value))).digest("hex");
1241
+ return createHash3("sha256").update(JSON.stringify(canonicalize(value))).digest("hex");
786
1242
  }
787
1243
  function controlEtag(value) {
788
1244
  return `sc1:${canonicalSessionCommandHash(value)}`;
789
1245
  }
790
1246
  function lockClause(mode) {
791
- if (mode === "none") return sql3.empty();
792
- return mode === "update" ? sql3.raw("for update") : sql3.raw("for share");
1247
+ if (mode === "none") return sql6.empty();
1248
+ return mode === "update" ? sql6.raw("for update") : sql6.raw("for share");
793
1249
  }
794
1250
  var WORKSPACE_CONTROL_REQUEST_LOCK_TIMEOUT_MS = 2e4;
795
1251
  var configuredRequestLockTimeoutMs = WORKSPACE_CONTROL_REQUEST_LOCK_TIMEOUT_MS;
@@ -819,7 +1275,7 @@ function workspaceControlLockBudget(lockTimeoutMs) {
819
1275
  return { totalMs, deadlineAt: Date.now() + totalMs };
820
1276
  }
821
1277
  function advisoryLockFunction(mode) {
822
- return mode === "update" ? sql3.raw("pg_advisory_xact_lock") : sql3.raw("pg_advisory_xact_lock_shared");
1278
+ return mode === "update" ? sql6.raw("pg_advisory_xact_lock") : sql6.raw("pg_advisory_xact_lock_shared");
823
1279
  }
824
1280
  function lockBudgetFor(options) {
825
1281
  if (options.budget) return options.budget;
@@ -831,7 +1287,7 @@ async function boundedLockStep(db, workspaceId, budget, step) {
831
1287
  const remainingMs = budget.deadlineAt - Date.now();
832
1288
  if (remainingMs <= 0) throw new WorkspaceControlBusyError(workspaceId, budget.totalMs);
833
1289
  await db.execute(
834
- sql3`select set_config('lock_timeout', ${`${Math.max(1, Math.floor(remainingMs))}ms`}, true)`
1290
+ sql6`select set_config('lock_timeout', ${`${Math.max(1, Math.floor(remainingMs))}ms`}, true)`
835
1291
  );
836
1292
  try {
837
1293
  return await step();
@@ -844,14 +1300,14 @@ async function boundedLockStep(db, workspaceId, budget, step) {
844
1300
  }
845
1301
  async function lockWorkspaceInferenceControl(db, workspaceId, mode, options = {}) {
846
1302
  const budget = lockBudgetFor(options);
847
- const [prior] = budget ? await db.execute(sql3`select current_setting('lock_timeout') as value`) : [];
1303
+ const [prior] = budget ? await db.execute(sql6`select current_setting('lock_timeout') as value`) : [];
848
1304
  if (mode !== "none") {
849
1305
  await boundedLockStep(
850
1306
  db,
851
1307
  workspaceId,
852
1308
  budget,
853
1309
  () => db.execute(
854
- sql3`select ${advisoryLockFunction(mode)}(hashtextextended(${`workspace-control:${workspaceId}`}, 0))`
1310
+ sql6`select ${advisoryLockFunction(mode)}(hashtextextended(${`workspace-control:${workspaceId}`}, 0))`
855
1311
  )
856
1312
  );
857
1313
  }
@@ -859,7 +1315,7 @@ async function lockWorkspaceInferenceControl(db, workspaceId, mode, options = {}
859
1315
  db,
860
1316
  workspaceId,
861
1317
  budget,
862
- () => db.execute(sql3`
1318
+ () => db.execute(sql6`
863
1319
  select
864
1320
  workspace_id as "workspaceId",
865
1321
  account_id as "accountId",
@@ -878,7 +1334,7 @@ async function lockWorkspaceInferenceControl(db, workspaceId, mode, options = {}
878
1334
  `)
879
1335
  );
880
1336
  if (budget) {
881
- await db.execute(sql3`select set_config('lock_timeout', ${prior?.value ?? "0"}, true)`);
1337
+ await db.execute(sql6`select set_config('lock_timeout', ${prior?.value ?? "0"}, true)`);
882
1338
  }
883
1339
  const row = rows[0];
884
1340
  if (!row) {
@@ -891,21 +1347,21 @@ async function lockWorkspaceInferenceControl(db, workspaceId, mode, options = {}
891
1347
  var WORKSPACE_CONTROL_ADMISSION_SAVEPOINT = "opengeni_workspace_control_admission";
892
1348
  async function lockWorkspaceInferenceControlForAdmission(db, input) {
893
1349
  const lockOptions = input.lockTimeoutMs === void 0 ? {} : { budget: workspaceControlLockBudget(input.lockTimeoutMs) };
894
- await db.execute(sql3.raw(`savepoint ${WORKSPACE_CONTROL_ADMISSION_SAVEPOINT}`));
1350
+ await db.execute(sql6.raw(`savepoint ${WORKSPACE_CONTROL_ADMISSION_SAVEPOINT}`));
895
1351
  const shared = await lockWorkspaceInferenceControl(db, input.workspaceId, "share", lockOptions);
896
1352
  if (!input.resumePausedBranch) {
897
- await db.execute(sql3.raw(`release savepoint ${WORKSPACE_CONTROL_ADMISSION_SAVEPOINT}`));
1353
+ await db.execute(sql6.raw(`release savepoint ${WORKSPACE_CONTROL_ADMISSION_SAVEPOINT}`));
898
1354
  return { control: shared, mode: "share" };
899
1355
  }
900
1356
  const effective = await evaluateSessionControl(db, input.workspaceId, input.sessionId, {
901
1357
  workspaceControl: shared
902
1358
  });
903
1359
  if (effective.state === "active") {
904
- await db.execute(sql3.raw(`release savepoint ${WORKSPACE_CONTROL_ADMISSION_SAVEPOINT}`));
1360
+ await db.execute(sql6.raw(`release savepoint ${WORKSPACE_CONTROL_ADMISSION_SAVEPOINT}`));
905
1361
  return { control: shared, mode: "share" };
906
1362
  }
907
- await db.execute(sql3.raw(`rollback to savepoint ${WORKSPACE_CONTROL_ADMISSION_SAVEPOINT}`));
908
- await db.execute(sql3.raw(`release savepoint ${WORKSPACE_CONTROL_ADMISSION_SAVEPOINT}`));
1363
+ await db.execute(sql6.raw(`rollback to savepoint ${WORKSPACE_CONTROL_ADMISSION_SAVEPOINT}`));
1364
+ await db.execute(sql6.raw(`release savepoint ${WORKSPACE_CONTROL_ADMISSION_SAVEPOINT}`));
909
1365
  return {
910
1366
  control: await lockWorkspaceInferenceControl(db, input.workspaceId, "update", lockOptions),
911
1367
  mode: "update"
@@ -1068,7 +1524,7 @@ async function closeSessionTurnAttemptInTransaction(db, input) {
1068
1524
  and3(
1069
1525
  eq3(sessionTurnAttempts.workspaceId, input.workspaceId),
1070
1526
  eq3(sessionTurnAttempts.id, input.id),
1071
- sql3`${sessionTurnAttempts.state} in ('claimed', 'running')`
1527
+ sql6`${sessionTurnAttempts.state} in ('claimed', 'running')`
1072
1528
  )
1073
1529
  ).returning({ id: sessionTurnAttempts.id });
1074
1530
  if (!closed) {
@@ -1080,14 +1536,14 @@ function targetValues(sessionIds) {
1080
1536
  if (sessionIds.length === 0) {
1081
1537
  throw new SessionControlInvariantError("At least one target session is required");
1082
1538
  }
1083
- return sql3.join(
1084
- sessionIds.map((id) => sql3`(${id}::uuid)`),
1085
- sql3`, `
1539
+ return sql6.join(
1540
+ sessionIds.map((id) => sql6`(${id}::uuid)`),
1541
+ sql6`, `
1086
1542
  );
1087
1543
  }
1088
1544
  var TARGET_PATH_PROJECTION_LIMIT = 128;
1089
1545
  async function loadTargetAncestryRows(db, workspaceId, sessionIds) {
1090
- return await db.execute(sql3`
1546
+ return await db.execute(sql6`
1091
1547
  with recursive targets(id) as (values ${targetValues(sessionIds)}),
1092
1548
  ancestry as (
1093
1549
  select
@@ -1150,7 +1606,7 @@ async function loadTargetAncestryRows(db, workspaceId, sessionIds) {
1150
1606
  `);
1151
1607
  }
1152
1608
  async function loadAncestryNodes(db, workspaceId, sessionIds) {
1153
- const rows = await db.execute(sql3`
1609
+ const rows = await db.execute(sql6`
1154
1610
  with recursive targets(id) as (values ${targetValues(sessionIds)}),
1155
1611
  ancestry_ids(id) as (
1156
1612
  select session.id
@@ -1344,7 +1800,7 @@ function projectEffectiveControl(workspace, targetId, rows, settlementAttempts,
1344
1800
  };
1345
1801
  }
1346
1802
  async function stoppingBackgroundCommandCounts(db, workspaceId, sessionIds) {
1347
- const rows = await db.execute(sql3`
1803
+ const rows = await db.execute(sql6`
1348
1804
  with recursive targets(id) as (values ${targetValues(sessionIds)}),
1349
1805
  descendants(target_id, session_id, depth, path) as (
1350
1806
  select target.id, target.id, 0::integer, array[target.id]::uuid[] from targets target
@@ -1370,7 +1826,7 @@ async function stoppingBackgroundCommandCounts(db, workspaceId, sessionIds) {
1370
1826
  );
1371
1827
  }
1372
1828
  async function settlementAttemptCounts(db, workspaceId, sessionIds) {
1373
- const rows = await db.execute(sql3`
1829
+ const rows = await db.execute(sql6`
1374
1830
  with recursive targets(id) as (values ${targetValues(sessionIds)}),
1375
1831
  descendant_sessions(target_id, session_id, depth, path) as (
1376
1832
  select target.id, target.id, 0::integer, array[target.id]::uuid[]
@@ -1524,7 +1980,7 @@ async function evaluateSessionDiscoveryControls(db, workspaceId, sessionIds) {
1524
1980
  if (workspace.workspaceState === "paused" && workspacePauseRevision === null) {
1525
1981
  throw new SessionControlInvariantError("Paused workspace is missing its pause revision");
1526
1982
  }
1527
- const rows = await db.execute(sql3`
1983
+ const rows = await db.execute(sql6`
1528
1984
  with recursive targets(id) as (values ${targetValues(uniqueIds)}),
1529
1985
  ancestry as (
1530
1986
  select
@@ -1696,16 +2152,16 @@ async function findCommandReceipt(db, input) {
1696
2152
  eq3(sessionCommandReceipts.actorType, "agent_attempt"),
1697
2153
  eq3(sessionCommandReceipts.action, input.action),
1698
2154
  eq3(sessionCommandReceipts.targetSessionId, input.targetSessionId),
1699
- sql3`${sessionCommandReceipts.targetTurnId} is null`,
2155
+ sql6`${sessionCommandReceipts.targetTurnId} is null`,
1700
2156
  eq3(sessionCommandReceipts.operationKey, input.operationKey)
1701
2157
  ) : and3(
1702
2158
  eq3(sessionCommandReceipts.workspaceId, input.workspaceId),
1703
2159
  eq3(sessionCommandReceipts.actorType, input.actor.type),
1704
- sql3`${sessionCommandReceipts.actorSubjectId} is not distinct from ${actorSubjectId}`,
1705
- sql3`${sessionCommandReceipts.actorAttemptId} is not distinct from ${actorAttemptId}::uuid`,
2160
+ sql6`${sessionCommandReceipts.actorSubjectId} is not distinct from ${actorSubjectId}`,
2161
+ sql6`${sessionCommandReceipts.actorAttemptId} is not distinct from ${actorAttemptId}::uuid`,
1706
2162
  eq3(sessionCommandReceipts.action, input.action),
1707
- sql3`${sessionCommandReceipts.targetSessionId} is not distinct from ${input.targetSessionId}::uuid`,
1708
- sql3`${sessionCommandReceipts.targetTurnId} is not distinct from ${input.targetTurnId}::uuid`,
2163
+ sql6`${sessionCommandReceipts.targetSessionId} is not distinct from ${input.targetSessionId}::uuid`,
2164
+ sql6`${sessionCommandReceipts.targetTurnId} is not distinct from ${input.targetTurnId}::uuid`,
1709
2165
  eq3(sessionCommandReceipts.operationKey, input.operationKey)
1710
2166
  );
1711
2167
  const rows = await db.select().from(sessionCommandReceipts).where(identity).for("update");
@@ -1718,8 +2174,8 @@ async function findPromptCommandReceipts(db, input) {
1718
2174
  and3(
1719
2175
  eq3(sessionCommandReceipts.workspaceId, input.workspaceId),
1720
2176
  eq3(sessionCommandReceipts.actorType, input.actor.type),
1721
- sql3`${sessionCommandReceipts.actorSubjectId} is not distinct from ${actorSubjectId}`,
1722
- sql3`${sessionCommandReceipts.actorAttemptId} is not distinct from ${actorAttemptId}::uuid`,
2177
+ sql6`${sessionCommandReceipts.actorSubjectId} is not distinct from ${actorSubjectId}`,
2178
+ sql6`${sessionCommandReceipts.actorAttemptId} is not distinct from ${actorAttemptId}::uuid`,
1723
2179
  inArray2(sessionCommandReceipts.action, ["prompt.send", "prompt.steer"]),
1724
2180
  eq3(sessionCommandReceipts.operationKey, input.operationKey)
1725
2181
  )
@@ -1780,7 +2236,7 @@ async function reserveSessionPromptCommandReceipt(db, input) {
1780
2236
  async function lockSessionPromptCommandOperation(db, input) {
1781
2237
  const actorIdentity = input.actor.type === "agent_attempt" ? `attempt:${input.actor.attemptId}` : `${input.actor.type}:${input.actor.subjectId}`;
1782
2238
  await db.execute(
1783
- sql3`select pg_advisory_xact_lock(hashtextextended(${`session-prompt:${input.workspaceId}:${actorIdentity}:${input.operationKey}`}, 0))`
2239
+ sql6`select pg_advisory_xact_lock(hashtextextended(${`session-prompt:${input.workspaceId}:${actorIdentity}:${input.operationKey}`}, 0))`
1784
2240
  );
1785
2241
  }
1786
2242
  async function getCompletedSessionPromptCommandReceipt(db, input) {
@@ -1857,7 +2313,7 @@ async function advanceWorkspaceRevision(db, workspaceId, revision) {
1857
2313
  }
1858
2314
  }
1859
2315
  async function registerContinuableWakes(db, input) {
1860
- const rows = await db.execute(sql3`
2316
+ const rows = await db.execute(sql6`
1861
2317
  with eligible as (
1862
2318
  select *
1863
2319
  from opengeni_private.list_continuable_sessions(
@@ -1899,7 +2355,7 @@ async function registerWorkspaceWakes(db, input) {
1899
2355
  });
1900
2356
  }
1901
2357
  async function registerInterruptionWakes(db, input) {
1902
- const rows = await db.execute(sql3`
2358
+ const rows = await db.execute(sql6`
1903
2359
  with eligible as (
1904
2360
  select distinct
1905
2361
  session.id as session_id,
@@ -1935,11 +2391,11 @@ async function registerInterruptionWakes(db, input) {
1935
2391
  }
1936
2392
  async function registerCancellationWakes(db, input) {
1937
2393
  if (input.sessionIds.length === 0) return 0;
1938
- const sessionIds = sql3.join(
1939
- input.sessionIds.map((id) => sql3`${id}::uuid`),
1940
- sql3`, `
2394
+ const sessionIds = sql6.join(
2395
+ input.sessionIds.map((id) => sql6`${id}::uuid`),
2396
+ sql6`, `
1941
2397
  );
1942
- const rows = await db.execute(sql3`
2398
+ const rows = await db.execute(sql6`
1943
2399
  with eligible as (
1944
2400
  select
1945
2401
  session.id as session_id,
@@ -1983,8 +2439,8 @@ async function registerSessionWorkflowWakeInTransaction(db, input) {
1983
2439
  target: sessionWorkflowWakeOutbox.sessionId,
1984
2440
  set: {
1985
2441
  temporalWorkflowId: input.temporalWorkflowId,
1986
- wakeRevision: sql3`${sessionWorkflowWakeOutbox.wakeRevision} + 1`,
1987
- controlRevision: input.controlRequested ? sql3`${sessionWorkflowWakeOutbox.wakeRevision} + 1` : sql3`${sessionWorkflowWakeOutbox.controlRevision}`,
2442
+ wakeRevision: sql6`${sessionWorkflowWakeOutbox.wakeRevision} + 1`,
2443
+ controlRevision: input.controlRequested ? sql6`${sessionWorkflowWakeOutbox.wakeRevision} + 1` : sql6`${sessionWorkflowWakeOutbox.controlRevision}`,
1988
2444
  reason: input.reason,
1989
2445
  attempts: 0,
1990
2446
  nextAttemptAt: /* @__PURE__ */ new Date(),
@@ -2023,7 +2479,7 @@ async function registerInternalUpdateWakeInTransaction(db, input) {
2023
2479
  };
2024
2480
  }
2025
2481
  async function interruptDescendantAttempts(db, input) {
2026
- const rows = await db.execute(sql3`
2482
+ const rows = await db.execute(sql6`
2027
2483
  with recursive live_attempts as (
2028
2484
  select attempt.id, attempt.account_id, attempt.workspace_id, attempt.session_id
2029
2485
  from ${sessionTurnAttempts} attempt
@@ -2071,7 +2527,7 @@ async function interruptDescendantAttempts(db, input) {
2071
2527
  return Number(rows[0]?.count ?? 0);
2072
2528
  }
2073
2529
  async function interruptWorkspaceAttempts(db, input) {
2074
- const rows = await db.execute(sql3`
2530
+ const rows = await db.execute(sql6`
2075
2531
  with inserted as (
2076
2532
  insert into ${sessionAttemptInterruptions} (
2077
2533
  account_id, workspace_id, session_id, operation_id, attempt_id,
@@ -2127,7 +2583,7 @@ async function pendingSessionControlWorkflowWake(db, workspaceId, sessionId, wak
2127
2583
  };
2128
2584
  }
2129
2585
  async function sessionPauseEffectsNeeded(db, input) {
2130
- const rows = await db.execute(sql3`
2586
+ const rows = await db.execute(sql6`
2131
2587
  with recursive subtree(id, path, cycle) as (
2132
2588
  select session.id, array[session.id]::uuid[], false
2133
2589
  from ${sessions} session
@@ -2178,7 +2634,7 @@ async function sessionPauseEffectsNeeded(db, input) {
2178
2634
  return rows[0]?.needed ?? false;
2179
2635
  }
2180
2636
  async function workspacePauseEffectsNeeded(db, input) {
2181
- const rows = await db.execute(sql3`
2637
+ const rows = await db.execute(sql6`
2182
2638
  select exists (
2183
2639
  select 1
2184
2640
  from ${sessions} session
@@ -2207,7 +2663,7 @@ async function workspacePauseEffectsNeeded(db, input) {
2207
2663
  return rows[0]?.needed ?? false;
2208
2664
  }
2209
2665
  async function continuableWakeRepairNeeded(db, input) {
2210
- const rows = await db.execute(sql3`
2666
+ const rows = await db.execute(sql6`
2211
2667
  select exists (
2212
2668
  select 1
2213
2669
  from opengeni_private.list_continuable_sessions(
@@ -2224,7 +2680,7 @@ async function continuableWakeRepairNeeded(db, input) {
2224
2680
  return rows[0]?.needed ?? false;
2225
2681
  }
2226
2682
  async function loadSessionSubtreeIds(db, workspaceId, rootSessionId) {
2227
- const rows = await db.execute(sql3`
2683
+ const rows = await db.execute(sql6`
2228
2684
  with recursive subtree(id, root_parent_session_id, depth, path, cycle) as (
2229
2685
  select session.id, session.parent_session_id, 0::integer, array[session.id]::uuid[], false
2230
2686
  from ${sessions} session
@@ -2418,7 +2874,7 @@ async function enqueueCancelledChildRequiresActionResolvedOutboxInTransaction(db
2418
2874
  }
2419
2875
  }
2420
2876
  async function assertSessionBranchIsNotCancelled(db, workspaceId, sessionId) {
2421
- const rows = await db.execute(sql3`
2877
+ const rows = await db.execute(sql6`
2422
2878
  with recursive ancestry(id, parent_id, status, depth, path, cycle) as (
2423
2879
  select session.id, session.parent_session_id, session.status, 0::integer,
2424
2880
  array[session.id]::uuid[], false
@@ -2493,7 +2949,7 @@ async function cancelSessionSubtreeInTransaction(db, input) {
2493
2949
  activeAttemptId: null,
2494
2950
  cancelledBy: input.actor,
2495
2951
  cancelReason: input.reason ?? "session_cancelled",
2496
- version: sql3`${sessionTurns.version} + 1`,
2952
+ version: sql6`${sessionTurns.version} + 1`,
2497
2953
  finishedAt: now,
2498
2954
  updatedAt: now
2499
2955
  }).where(inArray2(sessionTurns.id, immediatelyCancelledTurnIds));
@@ -2677,7 +3133,7 @@ async function cancelSessionSubtreeInTransaction(db, input) {
2677
3133
  await db.update(sessions).set({
2678
3134
  status: "cancelled",
2679
3135
  activeTurnId: liveTurnId,
2680
- queueVersion: sql3`${sessions.queueVersion} + 1`,
3136
+ queueVersion: sql6`${sessions.queueVersion} + 1`,
2681
3137
  queueHeadPosition: 0,
2682
3138
  queueTailPosition: 0,
2683
3139
  lastSequence: sequence,
@@ -2826,7 +3282,7 @@ async function mutateSessionControlInTransaction(db, input) {
2826
3282
  rootSessionId: input.sessionId
2827
3283
  });
2828
3284
  if (!changed) {
2829
- const [quiescence] = input.action === "pause" ? await db.execute(sql3`
3285
+ const [quiescence] = input.action === "pause" ? await db.execute(sql6`
2830
3286
  select exists (
2831
3287
  select 1 from ${sessionTurnAttempts} attempt
2832
3288
  where attempt.workspace_id = ${input.workspaceId}
@@ -3372,7 +3828,7 @@ async function setWorkspacePauseTimerInTransaction(db, input) {
3372
3828
  }
3373
3829
  }
3374
3830
  const hasTimer = input.action === "set" && delay > 0;
3375
- const [clock] = await db.execute(sql3`select clock_timestamp() as now`);
3831
+ const [clock] = await db.execute(sql6`select clock_timestamp() as now`);
3376
3832
  const revision = nextRevision(workspace);
3377
3833
  await db.update(workspaceInferenceControls).set({
3378
3834
  ...clearWorkspaceTimerFields,
@@ -3407,7 +3863,7 @@ async function fireWorkspacePauseTimerInTransaction(db, input) {
3407
3863
  const workspace = await lockWorkspaceInferenceControl(db, input.workspaceId, "update", {
3408
3864
  lockTimeoutMs: 1e3
3409
3865
  });
3410
- const [clock] = await db.execute(sql3`select clock_timestamp() as now`);
3866
+ const [clock] = await db.execute(sql6`select clock_timestamp() as now`);
3411
3867
  if (workspace.timerId !== input.timerId || !workspace.timerDueAt || new Date(workspace.timerDueAt).getTime() > new Date(clock.now).getTime())
3412
3868
  return null;
3413
3869
  const action = workspace.timerAction;
@@ -3423,7 +3879,7 @@ async function fireWorkspacePauseTimerInTransaction(db, input) {
3423
3879
  action,
3424
3880
  timerExecution: true
3425
3881
  });
3426
- const [applied] = await db.execute(sql3`select clock_timestamp() as now`);
3882
+ const [applied] = await db.execute(sql6`select clock_timestamp() as now`);
3427
3883
  await db.update(workspaceInferenceControls).set({
3428
3884
  ...clearWorkspaceTimerFields,
3429
3885
  ...action === "pause" && workspace.timerPauseForSeconds !== null ? {
@@ -3457,7 +3913,7 @@ function commandPreview(value) {
3457
3913
  const normalized = value.replace(/\s+/g, " ").trim();
3458
3914
  return Array.from(normalized).slice(0, 512).join("");
3459
3915
  }
3460
- var commandObservationUnavailable = sql4`
3916
+ var commandObservationUnavailable = sql7`
3461
3917
  ${sessionBackgroundCommands.state} in ('running','stopping') and exists (
3462
3918
  select 1 from sandbox_retained_processes process
3463
3919
  where process.id = ${sessionBackgroundCommands.retainedProcessId}
@@ -3510,9 +3966,9 @@ async function backgroundCommandActivityForSessions(db, input) {
3510
3966
  async (scopedDb) => {
3511
3967
  const rows = await scopedDb.select({
3512
3968
  sessionId: sessionBackgroundCommands.sessionId,
3513
- count: sql4`count(*)::int`,
3514
- stoppingCount: sql4`count(*) filter (where ${sessionBackgroundCommands.state} = 'stopping')::int`,
3515
- unavailableCount: sql4`count(*) filter (where ${commandObservationUnavailable})::int`
3969
+ count: sql7`count(*)::int`,
3970
+ stoppingCount: sql7`count(*) filter (where ${sessionBackgroundCommands.state} = 'stopping')::int`,
3971
+ unavailableCount: sql7`count(*) filter (where ${commandObservationUnavailable})::int`
3516
3972
  }).from(sessionBackgroundCommands).where(
3517
3973
  and4(
3518
3974
  eq4(sessionBackgroundCommands.workspaceId, input.workspaceId),
@@ -3581,7 +4037,7 @@ async function insertManagedSessionBackgroundCommandInTransaction(db, input) {
3581
4037
  launchExecutionGeneration: input.executionGeneration ?? null
3582
4038
  }).onConflictDoUpdate({
3583
4039
  target: sessionBackgroundCommands.retainedProcessId,
3584
- targetWhere: sql4`${sessionBackgroundCommands.retainedProcessId} is not null`,
4040
+ targetWhere: sql7`${sessionBackgroundCommands.retainedProcessId} is not null`,
3585
4041
  set: { updatedAt: /* @__PURE__ */ new Date() }
3586
4042
  }).returning();
3587
4043
  if (!row) throw new Error("Managed background command adoption returned no row");
@@ -3614,7 +4070,7 @@ async function insertConnectedMachineSessionBackgroundCommandInTransaction(db, i
3614
4070
  sessionBackgroundCommands.connectionInstanceId,
3615
4071
  sessionBackgroundCommands.opId
3616
4072
  ],
3617
- targetWhere: sql4`${sessionBackgroundCommands.provider} = 'connected_machine'`,
4073
+ targetWhere: sql7`${sessionBackgroundCommands.provider} = 'connected_machine'`,
3618
4074
  set: { updatedAt: /* @__PURE__ */ new Date() }
3619
4075
  }).returning();
3620
4076
  if (!row) throw new Error("Connected Machine background command adoption returned no row");
@@ -3632,7 +4088,7 @@ async function claimConnectedMachineSessionBackgroundCommands(db, input) {
3632
4088
  if (!Number.isSafeInteger(input.claimTtlMs) || input.claimTtlMs < 0 || input.claimTtlMs > 36e5) {
3633
4089
  throw new Error("Connected command reconciliation claim TTL is invalid");
3634
4090
  }
3635
- const rows = await db.execute(sql4`
4091
+ const rows = await db.execute(sql7`
3636
4092
  select account_id as "accountId",
3637
4093
  workspace_id as "workspaceId",
3638
4094
  session_id as "sessionId",
@@ -3767,7 +4223,7 @@ async function settleClaimedConnectedMachineBackgroundCommandWithMutation(db, in
3767
4223
  { accountId: input.claim.accountId, workspaceId: input.claim.workspaceId },
3768
4224
  async (tx) => {
3769
4225
  await mutateTerminal.prepare(tx);
3770
- const rows = await tx.execute(sql4`
4226
+ const rows = await tx.execute(sql7`
3771
4227
  update ${sessionBackgroundCommands} command set
3772
4228
  state = command.reconcile_proof_outcome,
3773
4229
  exit_code = case
@@ -3834,7 +4290,7 @@ async function requestSessionBackgroundCommandCancellation(db, input) {
3834
4290
  and4(
3835
4291
  eq4(sandboxRetainedProcesses.id, current.retainedProcessId),
3836
4292
  eq4(sandboxRetainedProcesses.state, "active"),
3837
- sql4`${sandboxRetainedProcesses.reconcileClaimId} is null`
4293
+ sql7`${sandboxRetainedProcesses.reconcileClaimId} is null`
3838
4294
  )
3839
4295
  );
3840
4296
  }
@@ -3845,11 +4301,11 @@ async function requestSessionBackgroundCommandCancellation(db, input) {
3845
4301
  async function requestSessionBackgroundCommandCancellationsInTransaction(db, input) {
3846
4302
  const rootSessionIds = [...new Set(input.rootSessionIds)];
3847
4303
  if (rootSessionIds.length === 0) return 0;
3848
- const rows = await db.execute(sql4`
4304
+ const rows = await db.execute(sql7`
3849
4305
  with recursive roots(id) as (
3850
- values ${sql4.join(
3851
- rootSessionIds.map((sessionId) => sql4`(${sessionId}::uuid)`),
3852
- sql4`, `
4306
+ values ${sql7.join(
4307
+ rootSessionIds.map((sessionId) => sql7`(${sessionId}::uuid)`),
4308
+ sql7`, `
3853
4309
  )}
3854
4310
  ), subtree(id, path, cycle) as (
3855
4311
  select session.id, array[session.id]::uuid[], false
@@ -3896,7 +4352,7 @@ async function requestSessionBackgroundCommandCancellationsInTransaction(db, inp
3896
4352
  return Number(rows[0]?.commandCount ?? 0);
3897
4353
  }
3898
4354
  async function requestWorkspaceBackgroundCommandCancellationsInTransaction(db, input) {
3899
- const rows = await db.execute(sql4`
4355
+ const rows = await db.execute(sql7`
3900
4356
  with stopped as (
3901
4357
  update ${sessionBackgroundCommands} command set
3902
4358
  state = 'stopping',
@@ -3968,7 +4424,7 @@ async function settleSessionBackgroundCommandForRetainedProcessInTransaction(tx,
3968
4424
  eq4(sessionEvents.workspaceId, input.workspaceId),
3969
4425
  eq4(sessionEvents.sessionId, input.sessionId),
3970
4426
  eq4(sessionEvents.type, "session.command.finished"),
3971
- sql4`${sessionEvents.payload} ->> 'commandId' = ${current.id}`
4427
+ sql7`${sessionEvents.payload} ->> 'commandId' = ${current.id}`
3972
4428
  )
3973
4429
  ).limit(1);
3974
4430
  if (existingEvent) return mapCommand(current);
@@ -4024,7 +4480,7 @@ async function settleConnectedMachineSessionBackgroundCommandWithMutation(db, in
4024
4480
  eq4(sessionBackgroundCommands.opId, input.opId),
4025
4481
  // A fast owner settlement cannot erase or replace metadata already
4026
4482
  // checkpointed by the reconciler under the exact command identity.
4027
- sql4`(${sessionBackgroundCommands.runnerFailure} is null or
4483
+ sql7`(${sessionBackgroundCommands.runnerFailure} is null or
4028
4484
  ${sessionBackgroundCommands.runnerFailure} = ${failure ? JSON.stringify(failure) : null}::jsonb)`,
4029
4485
  inArray3(sessionBackgroundCommands.state, ["running", "stopping"])
4030
4486
  )
@@ -4173,7 +4629,7 @@ async function readSessionBackgroundCommandOutput(db, input) {
4173
4629
  // Bound legacy payloads in SQL too: LIMIT alone cannot bound one old event.
4174
4630
  // Oversized historical rows carry explicit loss rather than allocating an
4175
4631
  // unbounded JSON value in the API process.
4176
- payload: sql4`case when octet_length(${sessionEvents.payload}::text) <= 262144
4632
+ payload: sql7`case when octet_length(${sessionEvents.payload}::text) <= 262144
4177
4633
  then ${sessionEvents.payload}
4178
4634
  else jsonb_build_object('commandReadProjectionGap', true) end`,
4179
4635
  payloadCodecVersion: sessionEvents.payloadCodecVersion
@@ -4182,7 +4638,7 @@ async function readSessionBackgroundCommandOutput(db, input) {
4182
4638
  eq4(sessionEvents.workspaceId, input.workspaceId),
4183
4639
  eq4(sessionEvents.sessionId, input.sessionId),
4184
4640
  eq4(sessionEvents.type, "sandbox.command.output.delta"),
4185
- sql4`${sessionEvents.payload} ->> 'commandId' = ${input.commandId}`,
4641
+ sql7`${sessionEvents.payload} ->> 'commandId' = ${input.commandId}`,
4186
4642
  gte(sessionEvents.sequence, cursor.sequence)
4187
4643
  )
4188
4644
  ).orderBy(asc2(sessionEvents.sequence)).limit(COMMAND_OUTPUT_PAGE_ROWS + 1)
@@ -4203,6 +4659,26 @@ async function readSessionBackgroundCommandOutput(db, input) {
4203
4659
  }
4204
4660
 
4205
4661
  export {
4662
+ lockActiveExternalOrganizationKey,
4663
+ lockExternalWorkspaceMembershipLifecycle,
4664
+ ensureExternalIdentity,
4665
+ ExternalIdentityLinkConflictError,
4666
+ beginExternalIdentityLink,
4667
+ getExternalIdentityLink,
4668
+ listExternalIdentityLinks,
4669
+ previewExternalIdentityLink,
4670
+ confirmExternalIdentityLink,
4671
+ revokeExternalIdentityLink,
4672
+ resolveExternalIdentityLink,
4673
+ externalLinkWorkSnapshotIsLive,
4674
+ getExternalLinkTurnSnapshot,
4675
+ getExternalLinkTurnAuthorization,
4676
+ captureExternalLinkTurnAuthority,
4677
+ inheritExternalLinkTurnAuthority,
4678
+ getExternalLinkTaskSnapshot,
4679
+ captureExternalLinkTaskAuthority,
4680
+ cloneExternalLinkTaskAuthority,
4681
+ captureScheduledExternalLinkTurnAuthority,
4206
4682
  configureChildLifecycleNotices,
4207
4683
  childLifecycleNoticesEnabled,
4208
4684
  boundedChildNoticeText,
@@ -4293,4 +4769,4 @@ export {
4293
4769
  setWorkspacePauseTimerInTransaction,
4294
4770
  fireWorkspacePauseTimerInTransaction
4295
4771
  };
4296
- //# sourceMappingURL=chunk-6GAPAYZR.js.map
4772
+ //# sourceMappingURL=chunk-7JPLGBSA.js.map