@opengeni/db 3.2.0-canary.0 → 3.4.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.
- package/dist/canonical-human-identities.js +3 -3
- package/dist/{chunk-SIBYBA2D.js → chunk-6DPJA36C.js} +30 -11
- package/dist/chunk-6DPJA36C.js.map +1 -0
- package/dist/{chunk-KRLPEMLH.js → chunk-C2AFP7SB.js} +184 -6
- package/dist/chunk-C2AFP7SB.js.map +1 -0
- package/dist/{chunk-AZHW7R5V.js → chunk-H7MXYG7R.js} +12 -8
- package/dist/chunk-H7MXYG7R.js.map +1 -0
- package/dist/{chunk-2PRS4J5Q.js → chunk-HY3F5Q4E.js} +3 -3
- package/dist/{chunk-NAB6FKFN.js → chunk-O6FTELKH.js} +3 -3
- package/dist/{chunk-UZNXG44K.js → chunk-PYMY3AJW.js} +324 -8
- package/dist/chunk-PYMY3AJW.js.map +1 -0
- package/dist/{chunk-6HMM2R5T.js → chunk-TRBOWUG3.js} +98 -4
- package/dist/chunk-TRBOWUG3.js.map +1 -0
- package/dist/{chunk-E6CLMKEE.js → chunk-V3TRUXFJ.js} +2 -2
- package/dist/{chunk-2EH4WRHL.js → chunk-ZWRIPCTR.js} +2 -2
- package/dist/editable-artifact-durable-export.js +2 -2
- package/dist/editable-artifacts.js +3 -3
- package/dist/governed-learning-activation.d.ts +16 -0
- package/dist/index.d.ts +108 -7
- package/dist/index.js +3605 -1417
- package/dist/index.js.map +1 -1
- package/dist/insights-model-bundle.d.ts +30 -0
- package/dist/insights-usage-bundle.d.ts +32 -0
- package/dist/insights.d.ts +10 -2
- package/dist/lossless-json.d.ts +1 -1
- package/dist/managed-user-setup.d.ts +82 -0
- package/dist/memory-domain.d.ts +2 -2
- package/dist/migrate.d.ts +3 -1
- package/dist/migrate.js +1 -1
- package/dist/new-session-drafts.d.ts +4 -4
- package/dist/organization-membership-lifecycle.d.ts +60 -1
- package/dist/pr-review.d.ts +44 -3
- package/dist/provision-roles.js +1 -1
- package/dist/runtime-posture.d.ts +12 -7
- package/dist/schema.d.ts +839 -101
- package/dist/schema.js +9 -1
- package/dist/session-background-commands.js +3 -3
- package/dist/session-tenancy.d.ts +12 -1
- package/dist/session-tenancy.js +3 -3
- package/dist/video-generation.js +3 -3
- package/drizzle/0348_named_signup_and_user_setup.sql +838 -0
- package/drizzle/0349_greenfield_session_tenancy_activation.sql +792 -0
- package/drizzle/0350_organization_shared_workspace_administration.sql +889 -0
- package/drizzle/0351_organization_user_setup_delivery.sql +978 -0
- package/drizzle/0352_session_variable_set_attachments.sql +1661 -0
- package/drizzle/0353_automatic_session_title_policy_fence.sql +476 -0
- package/drizzle/0354_automatic_session_title_quarantine_index.sql +9 -0
- package/drizzle/0355_automatic_session_title_quarantine.sql +92 -0
- package/drizzle/0356_set_based_insights_session_visibility.sql +237 -0
- package/drizzle/0357_rig_platform_base_only.sql +44 -0
- package/drizzle/0358_pr_review_managed_github_app.sql +108 -0
- package/drizzle/0359_insights_force_rls_read_capability.sql +936 -0
- package/drizzle/0360_organization_identity_confirmation_prompt.sql +103 -0
- package/drizzle/0361_remember_knowledge_memory_materialization.sql +249 -0
- package/package.json +6 -6
- package/src/database.ts +12 -8
- package/src/governed-learning-activation.ts +74 -2
- package/src/index.ts +879 -92
- package/src/insights-model-bundle.ts +681 -0
- package/src/insights-usage-bundle.ts +240 -0
- package/src/insights.ts +265 -152
- package/src/lossless-json.ts +2 -1
- package/src/managed-user-setup.ts +316 -0
- package/src/memory-domain.ts +3 -3
- package/src/migrate.ts +38 -14
- package/src/new-session-drafts.ts +22 -15
- package/src/organization-membership-lifecycle.ts +253 -1
- package/src/pr-review.ts +449 -6
- package/src/provision-roles.ts +92 -0
- package/src/runtime-posture.ts +247 -4
- package/src/schema.ts +210 -4
- package/src/session-tenancy.ts +120 -2
- package/dist/chunk-6HMM2R5T.js.map +0 -1
- package/dist/chunk-AZHW7R5V.js.map +0 -1
- package/dist/chunk-KRLPEMLH.js.map +0 -1
- package/dist/chunk-SIBYBA2D.js.map +0 -1
- package/dist/chunk-UZNXG44K.js.map +0 -1
- /package/dist/{chunk-2PRS4J5Q.js.map → chunk-HY3F5Q4E.js.map} +0 -0
- /package/dist/{chunk-NAB6FKFN.js.map → chunk-O6FTELKH.js.map} +0 -0
- /package/dist/{chunk-E6CLMKEE.js.map → chunk-V3TRUXFJ.js.map} +0 -0
- /package/dist/{chunk-2EH4WRHL.js.map → chunk-ZWRIPCTR.js.map} +0 -0
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
withWorkspaceRls,
|
|
6
6
|
withWorkspaceSubjectRls,
|
|
7
7
|
withWorkspaceSubjectSessionActivityRls
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-H7MXYG7R.js";
|
|
9
9
|
|
|
10
10
|
// src/session-tenancy.ts
|
|
11
11
|
import { createHash } from "crypto";
|
|
@@ -199,6 +199,18 @@ function canonicalSessionVisibilityTransitionHash(input) {
|
|
|
199
199
|
).digest("hex");
|
|
200
200
|
}
|
|
201
201
|
function canonicalSessionForkHash(input) {
|
|
202
|
+
if (input.runtimeRequest) {
|
|
203
|
+
return createHash("sha256").update(
|
|
204
|
+
JSON.stringify({
|
|
205
|
+
version: 3,
|
|
206
|
+
sourceSessionId: input.sourceSessionId,
|
|
207
|
+
destinationWorkspaceId: input.destinationWorkspaceId,
|
|
208
|
+
destinationVisibility: input.destinationVisibility,
|
|
209
|
+
workspaceSharedAcknowledged: input.workspaceSharedAcknowledged,
|
|
210
|
+
runtime: input.runtimeRequest
|
|
211
|
+
})
|
|
212
|
+
).digest("hex");
|
|
213
|
+
}
|
|
202
214
|
const legacyCompatiblePrivateRequest = input.destinationVisibility === "user_private" && !input.workspaceSharedAcknowledged;
|
|
203
215
|
return createHash("sha256").update(
|
|
204
216
|
JSON.stringify(
|
|
@@ -217,6 +229,9 @@ function canonicalSessionForkHash(input) {
|
|
|
217
229
|
)
|
|
218
230
|
).digest("hex");
|
|
219
231
|
}
|
|
232
|
+
function canonicalForkRuntimeConfigurationDigest(input) {
|
|
233
|
+
return createHash("sha256").update(JSON.stringify({ version: 1, ...input })).digest("hex");
|
|
234
|
+
}
|
|
220
235
|
async function transitionSessionVisibility(db, input) {
|
|
221
236
|
if (!Number.isSafeInteger(input.expectedAuthorityEpoch) || input.expectedAuthorityEpoch < 1) {
|
|
222
237
|
throw new Error("expectedAuthorityEpoch must be a positive safe integer");
|
|
@@ -275,6 +290,12 @@ async function forkSessionContent(db, input) {
|
|
|
275
290
|
if (input.destinationWorkspaceId !== input.sourceWorkspaceId) {
|
|
276
291
|
throw new Error("The first session fork contract is same-workspace only");
|
|
277
292
|
}
|
|
293
|
+
if (Boolean(input.runtimeRequest) !== Boolean(input.runtimeConfiguration)) {
|
|
294
|
+
throw new Error("A fresh session fork runtime request requires its resolved configuration");
|
|
295
|
+
}
|
|
296
|
+
if (input.runtimeRequest && (input.runtimeRequest.rigId !== input.runtimeConfiguration?.rigId || JSON.stringify(input.runtimeRequest.variableSetIds) !== JSON.stringify(input.runtimeConfiguration?.variableSetIds))) {
|
|
297
|
+
throw new Error("Resolved session fork runtime configuration does not match its request");
|
|
298
|
+
}
|
|
278
299
|
const { accountId } = await rlsContextForWorkspace(db, input.sourceWorkspaceId);
|
|
279
300
|
await assertSessionTenancyProductActivated(db, input.sourceWorkspaceId);
|
|
280
301
|
const requestHash = canonicalSessionForkHash(input);
|
|
@@ -284,6 +305,43 @@ async function forkSessionContent(db, input) {
|
|
|
284
305
|
input.sourceWorkspaceId,
|
|
285
306
|
input.actorSubjectId,
|
|
286
307
|
async (scopedDb) => {
|
|
308
|
+
if (input.runtimeRequest && input.runtimeConfiguration) {
|
|
309
|
+
const runtimeDigest = canonicalForkRuntimeConfigurationDigest(input.runtimeRequest);
|
|
310
|
+
const rows2 = await rawRows(
|
|
311
|
+
scopedDb,
|
|
312
|
+
sql`select
|
|
313
|
+
operation_id as "operationId",
|
|
314
|
+
event_id as "eventId",
|
|
315
|
+
event_sequence as "eventSequence",
|
|
316
|
+
session_id as "sessionId",
|
|
317
|
+
workspace_id as "workspaceId",
|
|
318
|
+
visibility,
|
|
319
|
+
authority_epoch as "authorityEpoch",
|
|
320
|
+
copied_history_item_count as "copiedHistoryItemCount",
|
|
321
|
+
replay,
|
|
322
|
+
runtime_event_id as "runtimeEventId",
|
|
323
|
+
runtime_event_sequence as "runtimeEventSequence"
|
|
324
|
+
from fork_session_content_with_runtime(
|
|
325
|
+
${accountId}::uuid,
|
|
326
|
+
${input.sourceWorkspaceId}::uuid,
|
|
327
|
+
${input.sourceSessionId}::uuid,
|
|
328
|
+
${input.actorSubjectId},
|
|
329
|
+
${input.destinationWorkspaceId}::uuid,
|
|
330
|
+
${input.destinationVisibility},
|
|
331
|
+
${input.workspaceSharedAcknowledged},
|
|
332
|
+
${input.operationKey},
|
|
333
|
+
${requestHash},
|
|
334
|
+
${SESSION_TENANCY_ACTIVATION_VERSION},
|
|
335
|
+
${JSON.stringify(input.runtimeConfiguration.variableSetIds)}::jsonb,
|
|
336
|
+
${input.runtimeConfiguration.rigId}::uuid,
|
|
337
|
+
${input.runtimeConfiguration.rigVersionId}::uuid,
|
|
338
|
+
${runtimeDigest}
|
|
339
|
+
)`
|
|
340
|
+
);
|
|
341
|
+
const result2 = rows2[0];
|
|
342
|
+
if (!result2) throw new Error("Session fork returned no result");
|
|
343
|
+
return result2;
|
|
344
|
+
}
|
|
287
345
|
const rows = await rawRows(
|
|
288
346
|
scopedDb,
|
|
289
347
|
sql`select
|
|
@@ -295,7 +353,9 @@ async function forkSessionContent(db, input) {
|
|
|
295
353
|
visibility,
|
|
296
354
|
authority_epoch as "authorityEpoch",
|
|
297
355
|
copied_history_item_count as "copiedHistoryItemCount",
|
|
298
|
-
replay
|
|
356
|
+
replay,
|
|
357
|
+
null::uuid as "runtimeEventId",
|
|
358
|
+
null::integer as "runtimeEventSequence"
|
|
299
359
|
from fork_session_content(
|
|
300
360
|
${accountId}::uuid,
|
|
301
361
|
${input.sourceWorkspaceId}::uuid,
|
|
@@ -337,6 +397,38 @@ async function replayAppliedSessionFork(db, input) {
|
|
|
337
397
|
input.sourceWorkspaceId,
|
|
338
398
|
input.actorSubjectId,
|
|
339
399
|
async (scopedDb) => {
|
|
400
|
+
if (input.runtimeRequest) {
|
|
401
|
+
const runtimeDigest = canonicalForkRuntimeConfigurationDigest(input.runtimeRequest);
|
|
402
|
+
const rows2 = await rawRows(
|
|
403
|
+
scopedDb,
|
|
404
|
+
sql`select
|
|
405
|
+
operation_id as "operationId",
|
|
406
|
+
event_id as "eventId",
|
|
407
|
+
event_sequence as "eventSequence",
|
|
408
|
+
session_id as "sessionId",
|
|
409
|
+
workspace_id as "workspaceId",
|
|
410
|
+
visibility,
|
|
411
|
+
authority_epoch as "authorityEpoch",
|
|
412
|
+
copied_history_item_count as "copiedHistoryItemCount",
|
|
413
|
+
replay,
|
|
414
|
+
runtime_event_id as "runtimeEventId",
|
|
415
|
+
runtime_event_sequence as "runtimeEventSequence"
|
|
416
|
+
from replay_applied_session_fork_with_runtime(
|
|
417
|
+
${accountId}::uuid,
|
|
418
|
+
${input.sourceWorkspaceId}::uuid,
|
|
419
|
+
${input.sourceSessionId}::uuid,
|
|
420
|
+
${input.actorSubjectId},
|
|
421
|
+
${input.destinationWorkspaceId}::uuid,
|
|
422
|
+
${input.destinationVisibility},
|
|
423
|
+
${input.workspaceSharedAcknowledged},
|
|
424
|
+
${input.operationKey},
|
|
425
|
+
${requestHash},
|
|
426
|
+
${SESSION_TENANCY_ACTIVATION_VERSION},
|
|
427
|
+
${runtimeDigest}
|
|
428
|
+
)`
|
|
429
|
+
);
|
|
430
|
+
return rows2[0] ?? null;
|
|
431
|
+
}
|
|
340
432
|
const rows = await rawRows(
|
|
341
433
|
scopedDb,
|
|
342
434
|
sql`select
|
|
@@ -348,7 +440,9 @@ async function replayAppliedSessionFork(db, input) {
|
|
|
348
440
|
visibility,
|
|
349
441
|
authority_epoch as "authorityEpoch",
|
|
350
442
|
copied_history_item_count as "copiedHistoryItemCount",
|
|
351
|
-
replay
|
|
443
|
+
replay,
|
|
444
|
+
null::uuid as "runtimeEventId",
|
|
445
|
+
null::integer as "runtimeEventSequence"
|
|
352
446
|
from replay_applied_session_fork(
|
|
353
447
|
${accountId}::uuid,
|
|
354
448
|
${input.sourceWorkspaceId}::uuid,
|
|
@@ -387,4 +481,4 @@ export {
|
|
|
387
481
|
forkSessionContent,
|
|
388
482
|
replayAppliedSessionFork
|
|
389
483
|
};
|
|
390
|
-
//# sourceMappingURL=chunk-
|
|
484
|
+
//# sourceMappingURL=chunk-TRBOWUG3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/session-tenancy.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport { sql } from \"drizzle-orm\";\nimport {\n SessionTenancyBlocker as SessionTenancyBlockerSchema,\n type SessionTenancyBlocker,\n} from \"@opengeni/contracts\";\nimport {\n rawRows,\n type Database,\n rlsContextForWorkspace,\n withWorkspaceRls,\n withWorkspaceSubjectRls,\n withWorkspaceSubjectSessionActivityRls,\n} from \"./database\";\nimport { nestedPostgresSqlState } from \"./persistence-errors\";\n\nconst SESSION_TENANCY_ACTIVATION_VERSION = 1;\n\nexport class SessionTenancyConflictError extends Error {\n readonly name = \"SessionTenancyConflictError\";\n constructor(\n readonly reason: \"not_quiescent\" | \"authority_epoch\" | \"operation_reuse\",\n readonly blocker: SessionTenancyBlocker | null = null,\n options?: ErrorOptions,\n ) {\n super(\n reason === \"not_quiescent\"\n ? \"Session must be fully quiescent before its tenancy can change\"\n : reason === \"authority_epoch\"\n ? \"Session authority changed before the operation committed\"\n : \"Session tenancy operation key was reused with different input\",\n options,\n );\n }\n}\n\nexport class SessionTenancyNotActivatedError extends Error {\n readonly name = \"SessionTenancyNotActivatedError\";\n constructor(options?: ErrorOptions) {\n super(\"Session tenancy product surface is not activated for this organization\", options);\n }\n}\n\nexport class SessionTenancyAccessError extends Error {\n readonly name = \"SessionTenancyAccessError\";\n constructor(options?: ErrorOptions) {\n super(\"Session tenancy target is unavailable\", options);\n }\n}\n\nexport class SessionTenancyInvalidRequestError extends Error {\n readonly name = \"SessionTenancyInvalidRequestError\";\n constructor(options?: ErrorOptions) {\n super(\"Session tenancy request is invalid\", options);\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value && typeof value === \"object\");\n}\n\n/** Extract only the fixed quiescence DETAIL vocabulary, never arbitrary driver detail. */\nexport function nestedSessionTenancyBlocker(error: unknown): SessionTenancyBlocker | null {\n const queue: unknown[] = [error];\n const seen = new Set<unknown>();\n while (queue.length > 0 && seen.size < 64) {\n const current = queue.shift();\n if (!isRecord(current) || seen.has(current)) continue;\n seen.add(current);\n for (const key of [\"detail\", \"detailMessage\"] as const) {\n const parsed = SessionTenancyBlockerSchema.safeParse(current[key]);\n if (parsed.success) return parsed.data;\n }\n for (const key of [\"cause\", \"original\", \"driverError\", \"error\", \"errors\"] as const) {\n const nested = current[key];\n if (Array.isArray(nested)) queue.push(...nested);\n else if (nested !== undefined) queue.push(nested);\n }\n }\n return null;\n}\n\nexport type SessionTenancyVisibility = \"user_private\" | \"workspace_shared\";\n\nexport type PrivateSessionCreatePolicy = {\n personalWorkspace: boolean;\n platformAvailable: boolean;\n organizationEnabled: boolean;\n};\n\nexport type TransitionSessionVisibilityInput = {\n workspaceId: string;\n sessionId: string;\n actorSubjectId: string;\n targetVisibility: SessionTenancyVisibility;\n expectedAuthorityEpoch: number;\n operationKey: string;\n};\n\nexport type TransitionSessionVisibilityResult = {\n operationId: string;\n eventId: string | null;\n eventSequence: number | null;\n visibility: SessionTenancyVisibility;\n authorityEpoch: number;\n ownerOrganizationMembershipId: string | null;\n changed: boolean;\n replay: boolean;\n interruptedAttemptCount: number;\n cancelledTurnCount: number;\n cancelledUpdateCount: number;\n pausedGoalCount: number;\n revokedGrantCount: number;\n};\n\nexport type ForkSessionContentInput = {\n sourceWorkspaceId: string;\n sourceSessionId: string;\n actorSubjectId: string;\n destinationWorkspaceId: string;\n destinationVisibility: SessionTenancyVisibility;\n workspaceSharedAcknowledged: boolean;\n operationKey: string;\n runtimeRequest?: ForkSessionRuntimeRequest;\n runtimeConfiguration?: ForkSessionRuntimeConfiguration;\n};\n\nexport type ForkSessionRuntimeRequest = {\n variableSetIds: string[];\n rigId: string | null;\n};\n\nexport type ForkSessionRuntimeConfiguration = ForkSessionRuntimeRequest & {\n rigVersionId: string | null;\n};\n\nexport type ForkSessionContentResult = {\n operationId: string;\n eventId: string;\n eventSequence: number;\n sessionId: string;\n workspaceId: string;\n visibility: SessionTenancyVisibility;\n authorityEpoch: number;\n copiedHistoryItemCount: number;\n replay: boolean;\n runtimeEventId: string | null;\n runtimeEventSequence: number | null;\n};\n\nexport async function sessionTenancyProductActivated(\n db: Database,\n workspaceId: string,\n): Promise<boolean> {\n const { accountId } = await rlsContextForWorkspace(db, workspaceId);\n return await withWorkspaceRls(db, workspaceId, async (scopedDb) => {\n const rows = await rawRows<{ activated: boolean }>(\n scopedDb,\n sql`select session_tenancy_product_activated(\n ${accountId}::uuid,\n ${SESSION_TENANCY_ACTIVATION_VERSION}\n ) as activated`,\n );\n return rows[0]?.activated === true;\n });\n}\n\nexport async function getPrivateSessionCreatePolicy(\n db: Database,\n input: { workspaceId: string; actorSubjectId: string },\n): Promise<PrivateSessionCreatePolicy> {\n const { accountId } = await rlsContextForWorkspace(db, input.workspaceId);\n return await withWorkspaceSubjectRls(\n db,\n input.workspaceId,\n input.actorSubjectId,\n async (scopedDb) => {\n const rows = await rawRows<{\n personalWorkspace: boolean;\n platformAvailable: boolean;\n organizationEnabled: boolean;\n }>(\n scopedDb,\n sql`select\n personal_workspace as \"personalWorkspace\",\n platform_available as \"platformAvailable\",\n organization_enabled as \"organizationEnabled\"\n from get_private_session_create_policy(\n ${accountId}::uuid,\n ${input.workspaceId}::uuid,\n ${input.actorSubjectId}\n )`,\n );\n const policy = rows[0];\n if (!policy) throw new SessionTenancyAccessError();\n return policy;\n },\n );\n}\n\n/** Open the exact transaction-local trigger capability used by atomic private create. */\nexport async function openPrivateSessionCreateCapability(\n db: Database,\n input: { accountId: string; workspaceId: string; sessionId: string; actorSubjectId: string },\n): Promise<{ capabilityId: string; ownerMembershipId: string }> {\n let rows: Array<{ capabilityId: string; ownerMembershipId: string }>;\n try {\n rows = await rawRows<{ capabilityId: string; ownerMembershipId: string }>(\n db,\n sql`select\n capability_id as \"capabilityId\",\n owner_membership_id as \"ownerMembershipId\"\n from open_private_session_create_capability(\n ${input.accountId}::uuid,\n ${input.workspaceId}::uuid,\n ${input.sessionId}::uuid,\n ${input.actorSubjectId}\n )`,\n );\n } catch (error) {\n // The definer raises 55000 only when the organization owner/admin setting\n // does not permit a new private session in this shared workspace; every\n // authority failure remains 42501 and propagates unchanged.\n if (nestedPostgresSqlState(error) === \"55000\") {\n throw new SessionTenancyNotActivatedError({ cause: error });\n }\n throw error;\n }\n const capabilityId = rows[0]?.capabilityId;\n const ownerMembershipId = rows[0]?.ownerMembershipId;\n if (!capabilityId || !ownerMembershipId) {\n throw new Error(\"Private session create capability was not returned\");\n }\n return { capabilityId, ownerMembershipId };\n}\n\n/** Open the exact transaction-local capability for one private child insert. */\nexport async function openPrivateChildSessionCreateCapability(\n db: Database,\n input: {\n accountId: string;\n workspaceId: string;\n sessionId: string;\n parentSessionId: string;\n actorTurnId: string;\n actorAttemptId: string;\n actorExecutionGeneration: number;\n },\n): Promise<{ capabilityId: string; ownerMembershipId: string; ownerSubjectId: string }> {\n const rows = await rawRows<{\n capabilityId: string;\n ownerMembershipId: string;\n ownerSubjectId: string;\n }>(\n db,\n sql`select\n capability_id as \"capabilityId\",\n owner_membership_id as \"ownerMembershipId\",\n owner_subject_id as \"ownerSubjectId\"\n from open_private_child_session_create_capability(\n ${input.accountId}::uuid,\n ${input.workspaceId}::uuid,\n ${input.sessionId}::uuid,\n ${input.parentSessionId}::uuid,\n ${input.actorTurnId}::uuid,\n ${input.actorAttemptId}::uuid,\n ${input.actorExecutionGeneration}::integer\n )`,\n );\n const capabilityId = rows[0]?.capabilityId;\n const ownerMembershipId = rows[0]?.ownerMembershipId;\n const ownerSubjectId = rows[0]?.ownerSubjectId;\n if (!capabilityId || !ownerMembershipId || !ownerSubjectId) {\n throw new Error(\"Private child session create capability was not returned\");\n }\n return { capabilityId, ownerMembershipId, ownerSubjectId };\n}\n\nexport async function closePrivateSessionCreateCapability(\n db: Database,\n capabilityId: string,\n): Promise<void> {\n await db.execute(sql`select close_private_session_create_capability(${capabilityId}::uuid)`);\n}\n\nasync function assertSessionTenancyProductActivated(\n db: Database,\n workspaceId: string,\n): Promise<void> {\n if (!(await sessionTenancyProductActivated(db, workspaceId))) {\n throw new SessionTenancyNotActivatedError();\n }\n}\n\nfunction mapSessionTenancyPersistenceError(\n error: unknown,\n options: { authorityEpochConflict: boolean },\n): never {\n const state = nestedPostgresSqlState(error);\n if (state === \"55P03\") {\n throw new SessionTenancyConflictError(\"not_quiescent\", nestedSessionTenancyBlocker(error), {\n cause: error,\n });\n }\n if (state === \"40001\" && options.authorityEpochConflict) {\n throw new SessionTenancyConflictError(\"authority_epoch\", null, { cause: error });\n }\n if (state === \"23505\") {\n throw new SessionTenancyConflictError(\"operation_reuse\", null, { cause: error });\n }\n if (state === \"55000\") {\n throw new SessionTenancyNotActivatedError({ cause: error });\n }\n if (state === \"42501\" || state === \"P0002\") {\n throw new SessionTenancyAccessError({ cause: error });\n }\n if (state === \"22023\") {\n throw new SessionTenancyInvalidRequestError({ cause: error });\n }\n throw error;\n}\n\nexport function canonicalSessionVisibilityTransitionHash(\n input: Pick<\n TransitionSessionVisibilityInput,\n \"sessionId\" | \"targetVisibility\" | \"expectedAuthorityEpoch\"\n >,\n): string {\n return createHash(\"sha256\")\n .update(\n JSON.stringify({\n version: 1,\n sessionId: input.sessionId,\n targetVisibility: input.targetVisibility,\n expectedAuthorityEpoch: input.expectedAuthorityEpoch,\n }),\n )\n .digest(\"hex\");\n}\n\nexport function canonicalSessionForkHash(\n input: Pick<\n ForkSessionContentInput,\n | \"sourceSessionId\"\n | \"destinationWorkspaceId\"\n | \"destinationVisibility\"\n | \"workspaceSharedAcknowledged\"\n | \"runtimeRequest\"\n >,\n): string {\n if (input.runtimeRequest) {\n return createHash(\"sha256\")\n .update(\n JSON.stringify({\n version: 3,\n sourceSessionId: input.sourceSessionId,\n destinationWorkspaceId: input.destinationWorkspaceId,\n destinationVisibility: input.destinationVisibility,\n workspaceSharedAcknowledged: input.workspaceSharedAcknowledged,\n runtime: input.runtimeRequest,\n }),\n )\n .digest(\"hex\");\n }\n const legacyCompatiblePrivateRequest =\n input.destinationVisibility === \"user_private\" && !input.workspaceSharedAcknowledged;\n return createHash(\"sha256\")\n .update(\n JSON.stringify(\n legacyCompatiblePrivateRequest\n ? {\n version: 1,\n sourceSessionId: input.sourceSessionId,\n destinationWorkspaceId: input.destinationWorkspaceId,\n destinationVisibility: input.destinationVisibility,\n }\n : {\n version: 2,\n sourceSessionId: input.sourceSessionId,\n destinationWorkspaceId: input.destinationWorkspaceId,\n destinationVisibility: input.destinationVisibility,\n workspaceSharedAcknowledged: input.workspaceSharedAcknowledged,\n },\n ),\n )\n .digest(\"hex\");\n}\n\nfunction canonicalForkRuntimeConfigurationDigest(input: ForkSessionRuntimeRequest): string {\n return createHash(\"sha256\")\n .update(JSON.stringify({ version: 1, ...input }))\n .digest(\"hex\");\n}\n\nexport async function transitionSessionVisibility(\n db: Database,\n input: TransitionSessionVisibilityInput,\n): Promise<TransitionSessionVisibilityResult> {\n if (!Number.isSafeInteger(input.expectedAuthorityEpoch) || input.expectedAuthorityEpoch < 1) {\n throw new Error(\"expectedAuthorityEpoch must be a positive safe integer\");\n }\n if (!input.operationKey.trim()) throw new Error(\"operationKey must not be empty\");\n const requestHash = canonicalSessionVisibilityTransitionHash(input);\n const { accountId } = await rlsContextForWorkspace(db, input.workspaceId);\n await assertSessionTenancyProductActivated(db, input.workspaceId);\n try {\n return await withWorkspaceSubjectSessionActivityRls(\n db,\n input.workspaceId,\n input.actorSubjectId,\n async (scopedDb) => {\n const rows = await rawRows<{\n operationId: string;\n eventId: string | null;\n eventSequence: number | null;\n visibility: SessionTenancyVisibility;\n authorityEpoch: number;\n ownerOrganizationMembershipId: string | null;\n changed: boolean;\n replay: boolean;\n interruptedAttemptCount: number;\n cancelledTurnCount: number;\n cancelledUpdateCount: number;\n pausedGoalCount: number;\n revokedGrantCount: number;\n }>(\n scopedDb,\n sql`select\n operation_id as \"operationId\",\n event_id as \"eventId\",\n event_sequence as \"eventSequence\",\n visibility,\n authority_epoch as \"authorityEpoch\",\n owner_organization_membership_id as \"ownerOrganizationMembershipId\",\n changed,\n replay,\n interrupted_attempt_count as \"interruptedAttemptCount\",\n cancelled_turn_count as \"cancelledTurnCount\",\n cancelled_update_count as \"cancelledUpdateCount\",\n paused_goal_count as \"pausedGoalCount\",\n revoked_grant_count as \"revokedGrantCount\"\n from transition_session_visibility(\n ${accountId}::uuid,\n ${input.workspaceId}::uuid,\n ${input.sessionId}::uuid,\n ${input.actorSubjectId},\n ${input.targetVisibility},\n ${input.expectedAuthorityEpoch},\n ${input.operationKey},\n ${requestHash},\n ${SESSION_TENANCY_ACTIVATION_VERSION}\n )`,\n );\n const result = rows[0];\n if (!result) throw new Error(\"Session visibility transition returned no result\");\n return result;\n },\n undefined,\n \"none\",\n );\n } catch (error) {\n mapSessionTenancyPersistenceError(error, { authorityEpochConflict: true });\n }\n}\n\nexport async function forkSessionContent(\n db: Database,\n input: ForkSessionContentInput,\n): Promise<ForkSessionContentResult> {\n if (!input.operationKey.trim()) throw new Error(\"operationKey must not be empty\");\n if (input.destinationWorkspaceId !== input.sourceWorkspaceId) {\n throw new Error(\"The first session fork contract is same-workspace only\");\n }\n if (Boolean(input.runtimeRequest) !== Boolean(input.runtimeConfiguration)) {\n throw new Error(\"A fresh session fork runtime request requires its resolved configuration\");\n }\n if (\n input.runtimeRequest &&\n (input.runtimeRequest.rigId !== input.runtimeConfiguration?.rigId ||\n JSON.stringify(input.runtimeRequest.variableSetIds) !==\n JSON.stringify(input.runtimeConfiguration?.variableSetIds))\n ) {\n throw new Error(\"Resolved session fork runtime configuration does not match its request\");\n }\n const { accountId } = await rlsContextForWorkspace(db, input.sourceWorkspaceId);\n await assertSessionTenancyProductActivated(db, input.sourceWorkspaceId);\n const requestHash = canonicalSessionForkHash(input);\n try {\n return await withWorkspaceSubjectRls(\n db,\n input.sourceWorkspaceId,\n input.actorSubjectId,\n async (scopedDb) => {\n if (input.runtimeRequest && input.runtimeConfiguration) {\n const runtimeDigest = canonicalForkRuntimeConfigurationDigest(input.runtimeRequest);\n const rows = await rawRows<ForkSessionContentResult>(\n scopedDb,\n sql`select\n operation_id as \"operationId\",\n event_id as \"eventId\",\n event_sequence as \"eventSequence\",\n session_id as \"sessionId\",\n workspace_id as \"workspaceId\",\n visibility,\n authority_epoch as \"authorityEpoch\",\n copied_history_item_count as \"copiedHistoryItemCount\",\n replay,\n runtime_event_id as \"runtimeEventId\",\n runtime_event_sequence as \"runtimeEventSequence\"\n from fork_session_content_with_runtime(\n ${accountId}::uuid,\n ${input.sourceWorkspaceId}::uuid,\n ${input.sourceSessionId}::uuid,\n ${input.actorSubjectId},\n ${input.destinationWorkspaceId}::uuid,\n ${input.destinationVisibility},\n ${input.workspaceSharedAcknowledged},\n ${input.operationKey},\n ${requestHash},\n ${SESSION_TENANCY_ACTIVATION_VERSION},\n ${JSON.stringify(input.runtimeConfiguration.variableSetIds)}::jsonb,\n ${input.runtimeConfiguration.rigId}::uuid,\n ${input.runtimeConfiguration.rigVersionId}::uuid,\n ${runtimeDigest}\n )`,\n );\n const result = rows[0];\n if (!result) throw new Error(\"Session fork returned no result\");\n return result;\n }\n const rows = await rawRows<ForkSessionContentResult>(\n scopedDb,\n sql`select\n operation_id as \"operationId\",\n event_id as \"eventId\",\n event_sequence as \"eventSequence\",\n session_id as \"sessionId\",\n workspace_id as \"workspaceId\",\n visibility,\n authority_epoch as \"authorityEpoch\",\n copied_history_item_count as \"copiedHistoryItemCount\",\n replay,\n null::uuid as \"runtimeEventId\",\n null::integer as \"runtimeEventSequence\"\n from fork_session_content(\n ${accountId}::uuid,\n ${input.sourceWorkspaceId}::uuid,\n ${input.sourceSessionId}::uuid,\n ${input.actorSubjectId},\n ${input.destinationWorkspaceId}::uuid,\n ${input.destinationVisibility},\n ${input.workspaceSharedAcknowledged},\n ${input.operationKey},\n ${requestHash},\n ${SESSION_TENANCY_ACTIVATION_VERSION}\n )`,\n );\n const result = rows[0];\n if (!result) throw new Error(\"Session fork returned no result\");\n return result;\n },\n undefined,\n \"none\",\n );\n } catch (error) {\n // A private destination inside a shared workspace carries the same\n // organization owner/admin product decision the create path enforces\n // (migration 0323), and the fork routine raises the same 55000. Surface it\n // as the not-activated product state rather than an opaque database error.\n if (nestedPostgresSqlState(error) === \"55000\") {\n throw new SessionTenancyNotActivatedError({ cause: error });\n }\n mapSessionTenancyPersistenceError(error, { authorityEpochConflict: false });\n }\n}\n\n/**\n * Recover one exact committed fork before mutable source-session authorization.\n *\n * The database capability requires the authenticated actor's active workspace\n * authority and matches the complete actor/workspace/source/key/request-hash\n * tuple. A fresh key returns null; changed intent raises the ordinary tenancy\n * idempotency conflict. This is receipt recovery, not session discovery.\n */\nexport async function replayAppliedSessionFork(\n db: Database,\n input: ForkSessionContentInput,\n): Promise<ForkSessionContentResult | null> {\n if (!input.operationKey.trim()) throw new Error(\"operationKey must not be empty\");\n if (input.destinationWorkspaceId !== input.sourceWorkspaceId) {\n throw new Error(\"The first session fork contract is same-workspace only\");\n }\n const { accountId } = await rlsContextForWorkspace(db, input.sourceWorkspaceId);\n await assertSessionTenancyProductActivated(db, input.sourceWorkspaceId);\n const requestHash = canonicalSessionForkHash(input);\n try {\n return await withWorkspaceSubjectRls(\n db,\n input.sourceWorkspaceId,\n input.actorSubjectId,\n async (scopedDb) => {\n if (input.runtimeRequest) {\n const runtimeDigest = canonicalForkRuntimeConfigurationDigest(input.runtimeRequest);\n const rows = await rawRows<ForkSessionContentResult>(\n scopedDb,\n sql`select\n operation_id as \"operationId\",\n event_id as \"eventId\",\n event_sequence as \"eventSequence\",\n session_id as \"sessionId\",\n workspace_id as \"workspaceId\",\n visibility,\n authority_epoch as \"authorityEpoch\",\n copied_history_item_count as \"copiedHistoryItemCount\",\n replay,\n runtime_event_id as \"runtimeEventId\",\n runtime_event_sequence as \"runtimeEventSequence\"\n from replay_applied_session_fork_with_runtime(\n ${accountId}::uuid,\n ${input.sourceWorkspaceId}::uuid,\n ${input.sourceSessionId}::uuid,\n ${input.actorSubjectId},\n ${input.destinationWorkspaceId}::uuid,\n ${input.destinationVisibility},\n ${input.workspaceSharedAcknowledged},\n ${input.operationKey},\n ${requestHash},\n ${SESSION_TENANCY_ACTIVATION_VERSION},\n ${runtimeDigest}\n )`,\n );\n return rows[0] ?? null;\n }\n const rows = await rawRows<ForkSessionContentResult>(\n scopedDb,\n sql`select\n operation_id as \"operationId\",\n event_id as \"eventId\",\n event_sequence as \"eventSequence\",\n session_id as \"sessionId\",\n workspace_id as \"workspaceId\",\n visibility,\n authority_epoch as \"authorityEpoch\",\n copied_history_item_count as \"copiedHistoryItemCount\",\n replay,\n null::uuid as \"runtimeEventId\",\n null::integer as \"runtimeEventSequence\"\n from replay_applied_session_fork(\n ${accountId}::uuid,\n ${input.sourceWorkspaceId}::uuid,\n ${input.sourceSessionId}::uuid,\n ${input.actorSubjectId},\n ${input.destinationWorkspaceId}::uuid,\n ${input.destinationVisibility},\n ${input.workspaceSharedAcknowledged},\n ${input.operationKey},\n ${requestHash},\n ${SESSION_TENANCY_ACTIVATION_VERSION}\n )`,\n );\n return rows[0] ?? null;\n },\n );\n } catch (error) {\n mapSessionTenancyPersistenceError(error, { authorityEpochConflict: false });\n }\n}\n"],"mappings":"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","names":["rows","result"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
nestedPostgresSqlState,
|
|
3
3
|
rawRows
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-H7MXYG7R.js";
|
|
5
5
|
|
|
6
6
|
// src/canonical-human-identities.ts
|
|
7
7
|
import { createHash } from "crypto";
|
|
@@ -256,4 +256,4 @@ export {
|
|
|
256
256
|
getCanonicalHumanIdentityProjection,
|
|
257
257
|
applyCanonicalHumanIdentityOperation
|
|
258
258
|
};
|
|
259
|
-
//# sourceMappingURL=chunk-
|
|
259
|
+
//# sourceMappingURL=chunk-V3TRUXFJ.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
rawRows,
|
|
3
3
|
withRlsContext
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-H7MXYG7R.js";
|
|
5
5
|
|
|
6
6
|
// src/editable-artifacts.ts
|
|
7
7
|
import { createHash } from "crypto";
|
|
@@ -3540,4 +3540,4 @@ export {
|
|
|
3540
3540
|
PostgresEditableArtifactStore,
|
|
3541
3541
|
PostgresEditableArtifactLiveReadStore
|
|
3542
3542
|
};
|
|
3543
|
-
//# sourceMappingURL=chunk-
|
|
3543
|
+
//# sourceMappingURL=chunk-ZWRIPCTR.js.map
|
|
@@ -8,9 +8,9 @@ import {
|
|
|
8
8
|
PostgresEditableArtifactStore,
|
|
9
9
|
listEditableArtifactIdsForSession,
|
|
10
10
|
touchEditableArtifactSessionLink
|
|
11
|
-
} from "./chunk-
|
|
12
|
-
import "./chunk-
|
|
13
|
-
import "./chunk-
|
|
11
|
+
} from "./chunk-ZWRIPCTR.js";
|
|
12
|
+
import "./chunk-H7MXYG7R.js";
|
|
13
|
+
import "./chunk-C2AFP7SB.js";
|
|
14
14
|
import "./chunk-PZ5AY32C.js";
|
|
15
15
|
export {
|
|
16
16
|
EDITABLE_ARTIFACT_INTENT_MAX_BYTES,
|
|
@@ -87,6 +87,22 @@ export declare function confirmRememberKnowledgeClaim(db: Database, raw: {
|
|
|
87
87
|
};
|
|
88
88
|
request: ConfirmRememberKnowledgeClaimRequestType;
|
|
89
89
|
}): Promise<RememberKnowledgeConfirmationReceiptType>;
|
|
90
|
+
export type RememberKnowledgeMemoryMaterialization = {
|
|
91
|
+
confirmationReceiptId: string;
|
|
92
|
+
accountId: string;
|
|
93
|
+
workspaceId: string;
|
|
94
|
+
sessionId: string;
|
|
95
|
+
memoryId: string;
|
|
96
|
+
taskNoteTextHash: string;
|
|
97
|
+
createdAt: string;
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* Materialize the exact approved Task-note text behind one completed remember
|
|
101
|
+
* confirmation. The database capability owns the insert and its immutable
|
|
102
|
+
* confirmation-to-Memory mapping, so generic deduplication cannot substitute a
|
|
103
|
+
* normalized lookalike and replay keeps the same Memory id after archival.
|
|
104
|
+
*/
|
|
105
|
+
export declare function materializeConfirmedRememberKnowledgeMemory(db: Database, receipt: RememberKnowledgeConfirmationReceiptType): Promise<RememberKnowledgeMemoryMaterialization>;
|
|
90
106
|
/**
|
|
91
107
|
* Read the initiating human bound to one workspace-scoped Knowledge claim under
|
|
92
108
|
* workspace RLS. Used by `remember_confirm` for the Knowledge lane; exposes no
|
package/dist/index.d.ts
CHANGED
|
@@ -37,6 +37,7 @@ export * from "./company-brain-context-selection.js";
|
|
|
37
37
|
export * from "./knowledge-source-sync.js";
|
|
38
38
|
export * from "./task-notes.js";
|
|
39
39
|
export * from "./managed-human-provisioning.js";
|
|
40
|
+
export * from "./managed-user-setup.js";
|
|
40
41
|
export * from "./organization-membership-backfill.js";
|
|
41
42
|
export * from "./connection-tenancy-backfill.js";
|
|
42
43
|
export * from "./generated-images.js";
|
|
@@ -57,6 +58,8 @@ export * from "./capability-integrations.js";
|
|
|
57
58
|
export * from "./integration-bindings.js";
|
|
58
59
|
export * from "./integration-facets.js";
|
|
59
60
|
export * from "./insights.js";
|
|
61
|
+
export * from "./insights-model-bundle.js";
|
|
62
|
+
export * from "./insights-usage-bundle.js";
|
|
60
63
|
export * from "./organization-membership-lifecycle.js";
|
|
61
64
|
export { rlsSubjectIdOrEmpty, subjectHasLiveWorkspaceAuthorityInScope, } from "./workspace-authority.js";
|
|
62
65
|
export { memoryTextForStorage } from "./memory-domain.js";
|
|
@@ -277,6 +280,7 @@ export declare function ensureManagedAccessForUser(db: Database, input: {
|
|
|
277
280
|
email: string;
|
|
278
281
|
name: string;
|
|
279
282
|
emailVerified?: boolean;
|
|
283
|
+
provisionFallbackOrganization?: boolean;
|
|
280
284
|
}): Promise<AccessContext>;
|
|
281
285
|
export type ManagedAccessProvisioningResult = {
|
|
282
286
|
accessContext: AccessContext;
|
|
@@ -287,6 +291,7 @@ export declare function ensureManagedAccessForUserWithOrganizationMemberships(db
|
|
|
287
291
|
email: string;
|
|
288
292
|
name: string;
|
|
289
293
|
emailVerified?: boolean;
|
|
294
|
+
provisionFallbackOrganization?: boolean;
|
|
290
295
|
}): Promise<ManagedAccessProvisioningResult>;
|
|
291
296
|
export declare function getWorkspace(db: Database, workspaceId: string): Promise<Workspace | null>;
|
|
292
297
|
export declare function getManagedAccount(db: Database, accountId: string): Promise<ManagedAccount | null>;
|
|
@@ -2823,7 +2828,11 @@ export declare class RigChangeAlreadyVerifyingError extends Error {
|
|
|
2823
2828
|
readonly changeId: string;
|
|
2824
2829
|
constructor(changeId: string);
|
|
2825
2830
|
}
|
|
2831
|
+
export declare class RigImageOverrideUnsupportedError extends Error {
|
|
2832
|
+
constructor();
|
|
2833
|
+
}
|
|
2826
2834
|
export type RigVersionContentInput = {
|
|
2835
|
+
/** @deprecated Rig versions always use the deployment platform sandbox image. */
|
|
2827
2836
|
image?: string | null;
|
|
2828
2837
|
setupScript?: string | null;
|
|
2829
2838
|
checks?: RigCheck[];
|
|
@@ -2874,6 +2883,10 @@ export declare class ChannelNameConflictError extends Error {
|
|
|
2874
2883
|
export declare class ChannelNotFoundError extends Error {
|
|
2875
2884
|
constructor(channelId: string);
|
|
2876
2885
|
}
|
|
2886
|
+
export declare class SessionVariableSetSelectionUnavailableError extends Error {
|
|
2887
|
+
readonly variableSetIds: string[];
|
|
2888
|
+
constructor(variableSetIds: string[], cause?: unknown);
|
|
2889
|
+
}
|
|
2877
2890
|
export declare function createChannel(db: Database, input: {
|
|
2878
2891
|
accountId: string;
|
|
2879
2892
|
workspaceId: string;
|
|
@@ -2900,6 +2913,37 @@ export declare function setSessionChannel(db: Database, input: {
|
|
|
2900
2913
|
sessionId: string;
|
|
2901
2914
|
channelId: string | null;
|
|
2902
2915
|
}): Promise<boolean>;
|
|
2916
|
+
export type UpdateSessionVariableSetsResult = {
|
|
2917
|
+
status: "updated";
|
|
2918
|
+
event: SessionEvent;
|
|
2919
|
+
} | {
|
|
2920
|
+
status: "unchanged";
|
|
2921
|
+
} | {
|
|
2922
|
+
status: "invalid_variable_sets";
|
|
2923
|
+
variableSetIds: string[];
|
|
2924
|
+
} | {
|
|
2925
|
+
status: "blocked";
|
|
2926
|
+
reason: "turn_in_flight" | "shared_sandbox_group" | "live_sandbox_holders";
|
|
2927
|
+
} | {
|
|
2928
|
+
status: "not_found";
|
|
2929
|
+
};
|
|
2930
|
+
/**
|
|
2931
|
+
* Replace the complete ordered session Variable Set selection at a quiescent
|
|
2932
|
+
* turn boundary. The session row + FK-backed attachment trigger + audit/event
|
|
2933
|
+
* evidence commit together. A live managed box is fenced for rotation so its
|
|
2934
|
+
* baked environment can never serve the next turn after a detach.
|
|
2935
|
+
*/
|
|
2936
|
+
export declare function updateSessionVariableSets(db: Database, input: {
|
|
2937
|
+
accountId: string;
|
|
2938
|
+
workspaceId: string;
|
|
2939
|
+
sessionId: string;
|
|
2940
|
+
subjectId: string;
|
|
2941
|
+
variableSets: Array<{
|
|
2942
|
+
id: string;
|
|
2943
|
+
name: string;
|
|
2944
|
+
scope: VariableSet["scope"];
|
|
2945
|
+
}>;
|
|
2946
|
+
}): Promise<UpdateSessionVariableSetsResult>;
|
|
2903
2947
|
export declare function countRigs(db: Database, access: string | RigAccessContext, scope?: Rig["scope"]): Promise<number>;
|
|
2904
2948
|
export declare function countSessionsUsingRig(db: Database, workspaceId: string, rigId: string): Promise<number>;
|
|
2905
2949
|
export declare function createRigVersion(db: Database, workspaceId: string, rigId: string, input: RigVersionContentInput, options?: {
|
|
@@ -2969,9 +3013,9 @@ export type RigProviderImageBuildClaim = {
|
|
|
2969
3013
|
};
|
|
2970
3014
|
/**
|
|
2971
3015
|
* Claim the one provider-image build slot for an existing immutable rig
|
|
2972
|
-
* version.
|
|
2973
|
-
*
|
|
2974
|
-
*
|
|
3016
|
+
* version. The setup hash fences definition drift. Deployment base-image and
|
|
3017
|
+
* provider-image protocol rotations may replace operational metadata for the
|
|
3018
|
+
* same setup; late finalizers remain fenced by the build request id.
|
|
2975
3019
|
*/
|
|
2976
3020
|
export declare function claimRigVersionProviderImageBuild(db: Database, input: {
|
|
2977
3021
|
workspaceId: string;
|
|
@@ -4532,6 +4576,7 @@ export type SessionCreateInput = {
|
|
|
4532
4576
|
reasoningEffort: ReasoningEffort;
|
|
4533
4577
|
latencyMode: LatencyMode;
|
|
4534
4578
|
sandboxBackend: SandboxBackend;
|
|
4579
|
+
variableSetIds?: string[];
|
|
4535
4580
|
variableSetId?: string | null;
|
|
4536
4581
|
rigId?: string | null;
|
|
4537
4582
|
rigVersionId?: string | null;
|
|
@@ -4652,6 +4697,8 @@ export declare function getAnySessionInGroup(db: Database, workspaceId: string,
|
|
|
4652
4697
|
* whose members carry mixed variableSetIds.
|
|
4653
4698
|
*/
|
|
4654
4699
|
export declare function listDistinctVariableSetIdsInGroup(db: Database, workspaceId: string, sandboxGroupId: string): Promise<Array<string | null>>;
|
|
4700
|
+
/** Ordered Variable Set selections across every member of a sandbox group. */
|
|
4701
|
+
export declare function listDistinctVariableSetSelectionsInGroup(db: Database, workspaceId: string, sandboxGroupId: string): Promise<string[][]>;
|
|
4655
4702
|
export declare function listDistinctRigVersionIdsInGroup(db: Database, workspaceId: string, sandboxGroupId: string): Promise<Array<string | null>>;
|
|
4656
4703
|
export declare function getWorkspaceDefaultRigId(db: Database, workspaceId: string): Promise<string | null>;
|
|
4657
4704
|
export type ListSessionsOptions = {
|
|
@@ -8346,10 +8393,21 @@ export declare function recordSessionGoalProgressWithEvent(db: Database, workspa
|
|
|
8346
8393
|
replay: boolean;
|
|
8347
8394
|
}>;
|
|
8348
8395
|
/**
|
|
8349
|
-
*
|
|
8350
|
-
*
|
|
8351
|
-
*
|
|
8352
|
-
*
|
|
8396
|
+
* Low-level row-only session-title update used by database-specific callers and
|
|
8397
|
+
* tests. Public product writers should use `updateSessionTitleWithEvent` so the
|
|
8398
|
+
* observable event commits atomically with this state transition. The clobber
|
|
8399
|
+
* guard lives entirely in this single atomic UPDATE: a user-set title is
|
|
8400
|
+
* permanent, so agent/auto writes
|
|
8401
|
+
* are first normalized through the shared short/sensitive-safe automatic-title
|
|
8402
|
+
* policy, then carry an `AND title_source IS DISTINCT FROM 'user'` guard
|
|
8403
|
+
* (NULL-safe in Postgres) while user writes are unconditional. Automatic
|
|
8404
|
+
* writes also bind the exact normalized candidate to a transaction-local
|
|
8405
|
+
* database capability, so a pre-policy binary cannot bypass normalization
|
|
8406
|
+
* during a rolling deployment. Never read-modify-write.
|
|
8407
|
+
*
|
|
8408
|
+
* `expectedCurrent`, when supplied, is an additional NULL-safe compare-and-set
|
|
8409
|
+
* fence. It is used by stale/retry-prone producers such as scheduled dispatch:
|
|
8410
|
+
* the write succeeds only if both the durable title and source still match.
|
|
8353
8411
|
* Re-applying the exact title is also a no-op so a confused agent cannot churn
|
|
8354
8412
|
* `updated_at` every turn. Returns `{ updated, title }`: `updated` is false when
|
|
8355
8413
|
* the value was unchanged or an agent write was skipped because a user title
|
|
@@ -8361,9 +8419,39 @@ export declare function updateSessionTitle(db: Database, input: {
|
|
|
8361
8419
|
sessionId: string;
|
|
8362
8420
|
title: string;
|
|
8363
8421
|
source: "user" | "agent";
|
|
8422
|
+
expectedCurrent?: {
|
|
8423
|
+
title: string | null;
|
|
8424
|
+
source: "user" | "agent" | null;
|
|
8425
|
+
};
|
|
8426
|
+
}): Promise<{
|
|
8427
|
+
updated: boolean;
|
|
8428
|
+
title: string | null;
|
|
8429
|
+
}>;
|
|
8430
|
+
/**
|
|
8431
|
+
* Atomically set a session title and append its public `session.title_set`
|
|
8432
|
+
* event under the canonical workspace/session event-write lock. The row CAS,
|
|
8433
|
+
* durable sequence, and event either all commit or all roll back, so a newer
|
|
8434
|
+
* title writer can never commit between the authoritative update and an older
|
|
8435
|
+
* event append.
|
|
8436
|
+
*
|
|
8437
|
+
* Exact retries are naturally idempotent: the unchanged-title predicate (and,
|
|
8438
|
+
* for stale producers, `expectedCurrent`) makes a committed retry a no-op with
|
|
8439
|
+
* no duplicate event. Automatic titles retain the rolling-deployment trigger's
|
|
8440
|
+
* exact transaction-local candidate capability.
|
|
8441
|
+
*/
|
|
8442
|
+
export declare function updateSessionTitleWithEvent(db: Database, input: {
|
|
8443
|
+
workspaceId: string;
|
|
8444
|
+
sessionId: string;
|
|
8445
|
+
title: string;
|
|
8446
|
+
source: "user" | "agent";
|
|
8447
|
+
expectedCurrent?: {
|
|
8448
|
+
title: string | null;
|
|
8449
|
+
source: "user" | "agent" | null;
|
|
8450
|
+
};
|
|
8364
8451
|
}): Promise<{
|
|
8365
8452
|
updated: boolean;
|
|
8366
8453
|
title: string | null;
|
|
8454
|
+
events: SessionEvent[];
|
|
8367
8455
|
}>;
|
|
8368
8456
|
/**
|
|
8369
8457
|
* Status transition helper. Idempotent: requesting the current status returns
|
|
@@ -9074,6 +9162,19 @@ export declare function getSessionSystemUpdateOutboxByDedupeKey(db: Database, in
|
|
|
9074
9162
|
dedupeKey: string;
|
|
9075
9163
|
}): Promise<SessionSystemUpdateOutboxDelivery | null>;
|
|
9076
9164
|
export declare function claimPendingSessionSystemUpdateOutbox(db: Database, limit?: number): Promise<SessionSystemUpdateOutboxDelivery[]>;
|
|
9165
|
+
export type AutomaticSessionTitleFanoutDelivery = {
|
|
9166
|
+
outboxId: string;
|
|
9167
|
+
event: SessionEvent;
|
|
9168
|
+
};
|
|
9169
|
+
/**
|
|
9170
|
+
* Claim migration-created title events for deployment-wide NATS fanout. The
|
|
9171
|
+
* function is SECURITY DEFINER because one control worker drains obligations
|
|
9172
|
+
* across workspaces; callers receive only the exact already-public event
|
|
9173
|
+
* projection, never arbitrary session rows.
|
|
9174
|
+
*/
|
|
9175
|
+
export declare function claimAutomaticSessionTitleFanout(db: Database, limit?: number): Promise<AutomaticSessionTitleFanoutDelivery[]>;
|
|
9176
|
+
export declare function markAutomaticSessionTitleFanoutDelivered(db: Database, delivery: AutomaticSessionTitleFanoutDelivery): Promise<boolean>;
|
|
9177
|
+
export declare function markAutomaticSessionTitleFanoutFailed(db: Database, delivery: AutomaticSessionTitleFanoutDelivery, error: string): Promise<boolean>;
|
|
9077
9178
|
export type SessionWorkflowWake = {
|
|
9078
9179
|
accountId: string;
|
|
9079
9180
|
workspaceId: string;
|