@opengeni/db 0.28.9 → 0.36.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/attached-browser-devices.d.ts +42 -0
- package/dist/attempt-tool-catalogs.d.ts +16 -0
- package/dist/browser-auth.d.ts +299 -0
- package/dist/browser-downloads.d.ts +51 -0
- package/dist/browser-identities.d.ts +137 -0
- package/dist/browser-sessions.d.ts +354 -0
- package/dist/browser-state-artifacts.d.ts +91 -0
- package/dist/canonical-human-identities.d.ts +48 -0
- package/dist/canonical-human-identities.js +28 -0
- package/dist/canonical-human-identities.js.map +1 -0
- package/dist/capability-components.d.ts +37 -0
- package/dist/capability-integrations.d.ts +194 -0
- package/dist/chunk-5KTIEDX7.js +13200 -0
- package/dist/chunk-5KTIEDX7.js.map +1 -0
- package/dist/chunk-CQZ4QSP5.js +995 -0
- package/dist/chunk-CQZ4QSP5.js.map +1 -0
- package/dist/chunk-F32YT7MP.js +117 -0
- package/dist/chunk-F32YT7MP.js.map +1 -0
- package/dist/chunk-JC5QPLUM.js +666 -0
- package/dist/chunk-JC5QPLUM.js.map +1 -0
- package/dist/chunk-P3RE4D2B.js +3535 -0
- package/dist/chunk-P3RE4D2B.js.map +1 -0
- package/dist/chunk-TAUTWOS5.js +259 -0
- package/dist/chunk-TAUTWOS5.js.map +1 -0
- package/dist/chunk-VKLB2ZGI.js +2389 -0
- package/dist/chunk-VKLB2ZGI.js.map +1 -0
- package/dist/codemode-operations.d.ts +117 -0
- package/dist/codex-token-resolver.d.ts +2 -2
- package/dist/company-profile-schema.d.ts +798 -0
- package/dist/company-profile.d.ts +268 -0
- package/dist/computer-sessions.d.ts +109 -0
- package/dist/connection-token-resolver.d.ts +9 -4
- package/dist/database.d.ts +57 -3
- package/dist/editable-artifact-durable-export.d.ts +153 -0
- package/dist/editable-artifact-durable-export.js +788 -0
- package/dist/editable-artifact-durable-export.js.map +1 -0
- package/dist/editable-artifact-materialization.d.ts +123 -0
- package/dist/editable-artifacts-schema.d.ts +4152 -0
- package/dist/editable-artifacts.d.ts +610 -0
- package/dist/editable-artifacts.js +26 -0
- package/dist/editable-artifacts.js.map +1 -0
- package/dist/generated-images.d.ts +139 -0
- package/dist/index.d.ts +1122 -126
- package/dist/index.js +42329 -18407
- package/dist/index.js.map +1 -1
- package/dist/insights.d.ts +73 -10
- package/dist/integration-bindings.d.ts +70 -0
- package/dist/integration-facets.d.ts +99 -0
- package/dist/interaction-revisions.d.ts +14 -0
- package/dist/interaction-schema.d.ts +6036 -0
- package/dist/knowledge-source-sync-schema.d.ts +1679 -0
- package/dist/knowledge-source-sync.d.ts +274 -0
- package/dist/memory-governance.d.ts +2 -2
- package/dist/memory-slack-delivery.d.ts +101 -0
- package/dist/new-session-drafts.d.ts +2 -2
- package/dist/pack-components.d.ts +76 -0
- package/dist/pack-installations.d.ts +86 -0
- package/dist/persistence-errors.d.ts +3 -3
- package/dist/plugin-packages.d.ts +126 -0
- package/dist/preference-registry.d.ts +1 -1
- package/dist/provision-roles.d.ts +9 -1
- package/dist/provision-roles.js +1 -1
- package/dist/runtime-posture.d.ts +19 -6
- package/dist/schema.d.ts +22654 -9359
- package/dist/schema.js +209 -3
- package/dist/scoped-knowledge.d.ts +97 -1
- package/dist/session-control.d.ts +33 -7
- package/dist/session-queue-commands.d.ts +19 -11
- package/dist/session-realtime-context.d.ts +2 -2
- package/dist/session-realtime-ledger.d.ts +4 -4
- package/dist/session-realtime-mirror.d.ts +2 -2
- package/dist/session-realtime-state.d.ts +1 -1
- package/dist/session-realtime-terminal.d.ts +1 -1
- package/dist/session-realtime.d.ts +7 -7
- package/dist/session-tenancy.d.ts +44 -0
- package/dist/session-tenancy.js +16 -0
- package/dist/session-tenancy.js.map +1 -0
- package/dist/session-tool-call-settlement.d.ts +1 -1
- package/dist/slack-task-policy-schema.d.ts +847 -0
- package/dist/slack-task-policy.d.ts +65 -0
- package/dist/slack-user-link-access.d.ts +54 -0
- package/dist/task-notes-schema.d.ts +924 -0
- package/dist/task-notes.d.ts +85 -0
- package/dist/transcription-recordings.d.ts +2 -2
- package/dist/turn-initiator.d.ts +2 -2
- package/dist/video-generation.d.ts +225 -0
- package/dist/video-generation.js +68 -0
- package/dist/video-generation.js.map +1 -0
- package/dist/workspace-artifacts.d.ts +1 -1
- package/dist/workspace-instruction-policies.d.ts +1 -1
- package/dist/workspace-learning-policy-schema.d.ts +932 -0
- package/dist/workspace-learning-policy.d.ts +161 -0
- package/dist/xai-subscription.d.ts +326 -0
- package/drizzle/0183_model_call_provider_cost_estimates.sql +39 -0
- package/drizzle/0184_sandbox_drain_teardown_fence.sql +682 -0
- package/drizzle/0185_temporal_schedule_cleanup_outbox.sql +168 -0
- package/drizzle/0186_sandbox_capture_provider_contract.sql +400 -0
- package/drizzle/0187_generated_image_artifacts.sql +173 -0
- package/drizzle/0188_image_generation_retention_failure.sql +25 -0
- package/drizzle/0189_retained_session_image_formats.sql +13 -0
- package/drizzle/0190_timeline_annotations.sql +31 -0
- package/drizzle/0191_editable_artifact_engine.sql +3853 -0
- package/drizzle/0192_editable_artifact_live_tickets.sql +338 -0
- package/drizzle/0193_editable_artifact_authorization.sql +190 -0
- package/drizzle/0194_editable_artifact_durable_exports.sql +160 -0
- package/drizzle/0195_editable_artifact_import_authorization.sql +203 -0
- package/drizzle/0196_rig_provider_images.sql +152 -0
- package/drizzle/0197_knowledge_source_sync_schedules.sql +523 -0
- package/drizzle/0198_memory_slack_publication_delivery.sql +393 -0
- package/drizzle/0199_workspace_learning_policy.sql +980 -0
- package/drizzle/0201_company_profile_authority.sql +849 -0
- package/drizzle/0202_document_index_checkpoints.sql +85 -0
- package/drizzle/0203_durable_video_generation.sql +353 -0
- package/drizzle/0204_video_generation_funding.sql +44 -0
- package/drizzle/0205_attempt_tool_catalogs.sql +230 -0
- package/drizzle/0206_browser_sessions.sql +646 -0
- package/drizzle/0207_browser_identities.sql +379 -0
- package/drizzle/0208_attached_browser_devices.sql +165 -0
- package/drizzle/0209_computer_sessions.sql +575 -0
- package/drizzle/0210_browser_auth_network_interventions.sql +441 -0
- package/drizzle/0211_editable_artifact_session_links.sql +58 -0
- package/drizzle/0212_browser_state_transfer_hardening.sql +560 -0
- package/drizzle/0212_slack_installation_bindings.sql +348 -0
- package/drizzle/0213_browser_interaction_authority.sql +67 -0
- package/drizzle/0213_slack_user_link_access_requests.sql +177 -0
- package/drizzle/0214_browser_download_saves.sql +34 -0
- package/drizzle/0214_session_activity_commit_gate.sql +262 -0
- package/drizzle/0215_browser_controller_host.sql +385 -0
- package/drizzle/0215_capabilities_platform.sql +980 -0
- package/drizzle/0216_browser_auth_health_evidence.sql +137 -0
- package/drizzle/0216_pack_component_ownership.sql +235 -0
- package/drizzle/0217_capability_definition_delete_authority.sql +32 -0
- package/drizzle/0217_external_browser_auth_operations.sql +22 -0
- package/drizzle/0218_organization_tenancy_foundation.sql +299 -0
- package/drizzle/0219_organization_tenancy_managed_human_provisioning.sql +317 -0
- package/drizzle/0219_site_auth_maintenance_sessions.sql +234 -0
- package/drizzle/0220_memory_slack_append_only_cascade.sql +38 -0
- package/drizzle/0220_session_channels.sql +54 -0
- package/drizzle/0221_sessions_channel_index.sql +5 -0
- package/drizzle/0222_session_visibility_authority_epochs.sql +158 -0
- package/drizzle/0222_sessions_channel_fk.sql +89 -0
- package/drizzle/0223_pending_tool_event_output.sql +55 -0
- package/drizzle/0223_sessions_channel_fk_validate.sql +118 -0
- package/drizzle/0224_slack_post_outcome_reconciliation.sql +123 -0
- package/drizzle/0225_session_visibility_fork_activation.sql +1363 -0
- package/drizzle/0226_personal_codex_authority_foundation.sql +365 -0
- package/drizzle/0227_slack_native_actions.sql +145 -0
- package/drizzle/0228_interaction_controller_data_plane.sql +14 -0
- package/drizzle/0228_slack_task_policy.sql +400 -0
- package/drizzle/0229_slack_inbox_file_fact.sql +10 -0
- package/drizzle/0230_user_scoped_variable_sets_rigs.sql +84 -0
- package/drizzle/0231_integration_definition_identity_cutover.sql +271 -0
- package/drizzle/0232_integration_facet_authority_cutover.sql +610 -0
- package/drizzle/0233_skill_and_integration_authority_cutover.sql +1162 -0
- package/drizzle/0234_xai_subscription_authority.sql +1139 -0
- package/drizzle/0235_canonical_human_login_bindings.sql +920 -0
- package/drizzle/0236_browser_identity_lifecycle.sql +39 -0
- package/drizzle/0236_session_visibility_slack_policy.sql +72 -0
- package/drizzle/0237_interaction_transition_reaper.sql +263 -0
- package/drizzle/0238_goal_persistence_policy.sql +471 -0
- package/drizzle/0238_supergrok_realtime_model.sql +29 -0
- package/drizzle/0239_supergrok_video_funding.sql +50 -0
- package/drizzle/0239_task_tree_notes.sql +990 -0
- package/package.json +26 -5
- package/src/attached-browser-devices.ts +371 -0
- package/src/attempt-tool-catalogs.ts +131 -0
- package/src/browser-auth.ts +4373 -0
- package/src/browser-downloads.ts +517 -0
- package/src/browser-identities.ts +1385 -0
- package/src/browser-sessions.ts +2294 -0
- package/src/browser-state-artifacts.ts +449 -0
- package/src/canonical-human-identities.ts +317 -0
- package/src/capability-components.ts +166 -0
- package/src/capability-integrations.ts +1571 -0
- package/src/codemode-operations.ts +674 -0
- package/src/company-profile-schema.ts +143 -0
- package/src/company-profile.ts +968 -0
- package/src/computer-sessions.ts +1130 -0
- package/src/connection-token-resolver.ts +270 -25
- package/src/database.ts +468 -24
- package/src/editable-artifact-durable-export.ts +1201 -0
- package/src/editable-artifact-materialization.ts +893 -0
- package/src/editable-artifacts-schema.ts +879 -0
- package/src/editable-artifacts.ts +5404 -0
- package/src/generated-images.ts +740 -0
- package/src/index.ts +9963 -1465
- package/src/insights.ts +251 -23
- package/src/integration-bindings.ts +455 -0
- package/src/integration-facets.ts +862 -0
- package/src/interaction-revisions.ts +70 -0
- package/src/interaction-schema.ts +1606 -0
- package/src/knowledge-source-sync-schema.ts +192 -0
- package/src/knowledge-source-sync.ts +1922 -0
- package/src/memory-slack-delivery.ts +801 -0
- package/src/pack-components.ts +954 -0
- package/src/pack-installations.ts +886 -0
- package/src/persistence-errors.ts +4 -7
- package/src/plugin-packages.ts +1186 -0
- package/src/provision-roles.ts +534 -1
- package/src/runtime-posture-cli.ts +9 -0
- package/src/runtime-posture.ts +721 -5
- package/src/schema.ts +6270 -3159
- package/src/scoped-knowledge-schema.ts +1 -1
- package/src/scoped-knowledge.ts +655 -3
- package/src/session-control.ts +130 -42
- package/src/session-queue-commands.ts +265 -15
- package/src/session-realtime-context.ts +2 -2
- package/src/session-realtime-ledger.ts +3 -3
- package/src/session-realtime.ts +7 -7
- package/src/session-tenancy.ts +188 -0
- package/src/session-tool-call-settlement.ts +18 -3
- package/src/slack-task-policy-schema.ts +130 -0
- package/src/slack-task-policy.ts +341 -0
- package/src/slack-user-link-access.ts +702 -0
- package/src/task-notes-schema.ts +135 -0
- package/src/task-notes.ts +178 -0
- package/src/video-generation.ts +1530 -0
- package/src/workspace-artifacts.ts +1 -1
- package/src/workspace-learning-policy-schema.ts +139 -0
- package/src/workspace-learning-policy.ts +595 -0
- package/src/xai-subscription.ts +1887 -0
- package/dist/chunk-P6CUHXQZ.js +0 -7248
- package/dist/chunk-P6CUHXQZ.js.map +0 -1
- package/dist/chunk-VHBFHMPC.js +0 -1219
- package/dist/chunk-VHBFHMPC.js.map +0 -1
package/src/session-control.ts
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
type TurnInitiatorContext,
|
|
8
8
|
} from "@opengeni/contracts";
|
|
9
9
|
import { and, eq, inArray, sql } from "drizzle-orm";
|
|
10
|
-
import type { Database } from "./database";
|
|
10
|
+
import type { Database, SessionActivityDatabase } from "./database";
|
|
11
11
|
import { withLosslessContentWriteVersion } from "./lossless-json";
|
|
12
12
|
import * as schema from "./schema";
|
|
13
13
|
import { closePendingSessionToolCallsInTransaction } from "./session-tool-call-settlement";
|
|
@@ -200,7 +200,7 @@ export class SessionCommandIdempotencyError extends Error {
|
|
|
200
200
|
|
|
201
201
|
export class AgentCommandAuthorityError extends Error {
|
|
202
202
|
constructor(
|
|
203
|
-
readonly code: "CALLER_STALE" | "CALLER_INTERRUPTED" | "
|
|
203
|
+
readonly code: "CALLER_STALE" | "CALLER_INTERRUPTED" | "TARGET_NOT_VERTICAL" | "SELF_STEER",
|
|
204
204
|
message: string,
|
|
205
205
|
) {
|
|
206
206
|
super(message);
|
|
@@ -232,10 +232,12 @@ export async function assertAgentCommandAuthorityInTransaction(
|
|
|
232
232
|
attemptIds: [input.actor.attemptId],
|
|
233
233
|
});
|
|
234
234
|
const lockedSessions = authorityLocks.sessions;
|
|
235
|
-
|
|
235
|
+
const callerSession = lockedSessions.find((row) => row.id === input.actor.sessionId);
|
|
236
|
+
if (!callerSession) {
|
|
236
237
|
throw new AgentCommandAuthorityError("CALLER_STALE", "The calling session no longer exists");
|
|
237
238
|
}
|
|
238
|
-
|
|
239
|
+
const targetSession = lockedSessions.find((row) => row.id === input.targetSessionId);
|
|
240
|
+
if (!targetSession) {
|
|
239
241
|
throw new SessionControlInvariantError(`Target session not found: ${input.targetSessionId}`);
|
|
240
242
|
}
|
|
241
243
|
const rows = await db.execute<{
|
|
@@ -298,37 +300,21 @@ export async function assertAgentCommandAuthorityInTransaction(
|
|
|
298
300
|
if (input.action === "steer" && input.targetSessionId === input.actor.sessionId) {
|
|
299
301
|
throw new AgentCommandAuthorityError("SELF_STEER", "An agent cannot steer its own session");
|
|
300
302
|
}
|
|
301
|
-
|
|
302
|
-
const
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
union all
|
|
312
|
-
select parent.id, parent.parent_session_id, child.depth + 1,
|
|
313
|
-
child.path || parent.id, parent.id = any(child.path)
|
|
314
|
-
from caller_ancestry child
|
|
315
|
-
join ${schema.sessions} parent
|
|
316
|
-
on parent.workspace_id = ${input.workspaceId} and parent.id = child.parent_id
|
|
317
|
-
where child.depth < ${SESSION_ANCESTRY_LIMIT} and not child.cycle
|
|
318
|
-
)
|
|
319
|
-
select
|
|
320
|
-
coalesce(bool_or(id = ${input.targetSessionId}), false) as "containsCaller",
|
|
321
|
-
coalesce(bool_or(cycle), false) or coalesce(max(depth), 0) >= ${SESSION_ANCESTRY_LIMIT}
|
|
322
|
-
as invalid
|
|
323
|
-
from caller_ancestry
|
|
324
|
-
`);
|
|
325
|
-
if (ancestry[0]?.invalid) {
|
|
326
|
-
throw new SessionControlInvariantError("Caller ancestry is invalid");
|
|
327
|
-
}
|
|
328
|
-
if (ancestry[0]?.containsCaller) {
|
|
303
|
+
const targetsSelf = targetSession.id === callerSession.id;
|
|
304
|
+
const targetsDirectParent = callerSession.parentSessionId === targetSession.id;
|
|
305
|
+
const targetsDirectChild = targetSession.parentSessionId === callerSession.id;
|
|
306
|
+
const verticalTargetAllowed =
|
|
307
|
+
input.action === "goal"
|
|
308
|
+
? targetsSelf
|
|
309
|
+
: input.action === "message"
|
|
310
|
+
? targetsSelf || targetsDirectParent || targetsDirectChild
|
|
311
|
+
: targetsDirectChild;
|
|
312
|
+
if (!verticalTargetAllowed) {
|
|
329
313
|
throw new AgentCommandAuthorityError(
|
|
330
|
-
"
|
|
331
|
-
|
|
314
|
+
"TARGET_NOT_VERTICAL",
|
|
315
|
+
input.action === "message"
|
|
316
|
+
? "An agent may message only its own session, direct parent, or direct child"
|
|
317
|
+
: "An agent may control only a direct child session",
|
|
332
318
|
);
|
|
333
319
|
}
|
|
334
320
|
}
|
|
@@ -430,7 +416,7 @@ export type SessionEventWriteLocks = {
|
|
|
430
416
|
*
|
|
431
417
|
* workspace_inference_controls (when control-aware)
|
|
432
418
|
* -> actual workspaces row FOR KEY SHARE
|
|
433
|
-
* -> session rows FOR UPDATE, UUID ordered
|
|
419
|
+
* -> session rows FOR NO KEY UPDATE, UUID ordered
|
|
434
420
|
* -> exact turn rows FOR UPDATE, UUID ordered
|
|
435
421
|
* -> exact attempt rows FOR UPDATE, UUID ordered
|
|
436
422
|
*
|
|
@@ -439,6 +425,11 @@ export type SessionEventWriteLocks = {
|
|
|
439
425
|
* `FOR UPDATE` lock serialized unrelated sessions and inverted the activity
|
|
440
426
|
* path's session -> implicit workspace-FK edge.
|
|
441
427
|
*
|
|
428
|
+
* `FOR NO KEY UPDATE` is equally deliberate for sessions. Session primary and
|
|
429
|
+
* composite identity keys are immutable, so writers need to exclude only concurrent
|
|
430
|
+
* non-key mutation. Keeping FK `FOR KEY SHARE` checks compatible prevents the
|
|
431
|
+
* activity finalizer's workspace counter from participating in a lock cycle.
|
|
432
|
+
*
|
|
442
433
|
* Complex lifecycle transactions may acquire allocator/control locks before
|
|
443
434
|
* this helper and may discover exact turn IDs only after locking the session.
|
|
444
435
|
* They use the explicit `already_locked` stages, while retaining the same
|
|
@@ -478,7 +469,7 @@ export async function lockSessionEventWriteRows(
|
|
|
478
469
|
),
|
|
479
470
|
)
|
|
480
471
|
.orderBy(schema.sessions.id)
|
|
481
|
-
.for("update")
|
|
472
|
+
.for("no key update")
|
|
482
473
|
: [];
|
|
483
474
|
|
|
484
475
|
const turnIds = [...new Set(input.turnIds ?? [])].sort();
|
|
@@ -529,14 +520,24 @@ export async function registerSessionTurnAttemptClaim(
|
|
|
529
520
|
temporalWorkflowRunId: string;
|
|
530
521
|
temporalActivityId: string;
|
|
531
522
|
verifiedControlRevision: number;
|
|
523
|
+
authorityEpoch: number;
|
|
524
|
+
authorityVisibility: "user_private" | "workspace_shared";
|
|
525
|
+
authorityOwnerOrganizationMembershipId: string | null;
|
|
532
526
|
mcpApprovalPolicies: Record<string, SessionMcpApprovalPolicy>;
|
|
533
527
|
connectorActionPolicies: schema.ConnectorActionPolicySnapshotEntry[];
|
|
534
528
|
},
|
|
535
529
|
): Promise<typeof schema.sessionTurnAttempts.$inferSelect> {
|
|
530
|
+
const authoritySnapshot = assertSessionAuthoritySnapshot({
|
|
531
|
+
attemptId: input.id,
|
|
532
|
+
authorityEpoch: input.authorityEpoch,
|
|
533
|
+
authorityVisibility: input.authorityVisibility,
|
|
534
|
+
authorityOwnerOrganizationMembershipId: input.authorityOwnerOrganizationMembershipId,
|
|
535
|
+
});
|
|
536
536
|
const [inserted] = await db
|
|
537
537
|
.insert(schema.sessionTurnAttempts)
|
|
538
538
|
.values({
|
|
539
539
|
...input,
|
|
540
|
+
...authoritySnapshot,
|
|
540
541
|
state: "claimed",
|
|
541
542
|
})
|
|
542
543
|
// Only an idempotent replay of this exact preallocated attempt ID may
|
|
@@ -557,12 +558,22 @@ export async function registerSessionTurnAttemptClaim(
|
|
|
557
558
|
)
|
|
558
559
|
.for("update")
|
|
559
560
|
.limit(1);
|
|
561
|
+
const existingAuthoritySnapshot = existing
|
|
562
|
+
? assertSessionAuthoritySnapshot({
|
|
563
|
+
attemptId: existing.id,
|
|
564
|
+
authorityEpoch: existing.authorityEpoch,
|
|
565
|
+
authorityVisibility: existing.authorityVisibility,
|
|
566
|
+
authorityOwnerOrganizationMembershipId: existing.authorityOwnerOrganizationMembershipId,
|
|
567
|
+
})
|
|
568
|
+
: null;
|
|
560
569
|
if (
|
|
561
570
|
!existing ||
|
|
562
571
|
existing.accountId !== input.accountId ||
|
|
563
572
|
existing.sessionId !== input.sessionId ||
|
|
564
573
|
existing.turnId !== input.turnId ||
|
|
565
574
|
existing.executionGeneration !== input.executionGeneration ||
|
|
575
|
+
!existingAuthoritySnapshot ||
|
|
576
|
+
!sessionAuthoritySnapshotsEqual(existingAuthoritySnapshot, authoritySnapshot) ||
|
|
566
577
|
existing.temporalWorkflowId !== input.temporalWorkflowId ||
|
|
567
578
|
existing.temporalWorkflowRunId !== input.temporalWorkflowRunId ||
|
|
568
579
|
existing.temporalActivityId !== input.temporalActivityId ||
|
|
@@ -577,6 +588,80 @@ export async function registerSessionTurnAttemptClaim(
|
|
|
577
588
|
return existing;
|
|
578
589
|
}
|
|
579
590
|
|
|
591
|
+
export type SessionAuthoritySnapshot = {
|
|
592
|
+
authorityEpoch: number;
|
|
593
|
+
authorityVisibility: "user_private" | "workspace_shared";
|
|
594
|
+
authorityOwnerOrganizationMembershipId: string | null;
|
|
595
|
+
};
|
|
596
|
+
|
|
597
|
+
/**
|
|
598
|
+
* Validate the complete accepted-attempt authority tuple. Missing or partial
|
|
599
|
+
* values are not legacy defaults: current claim writers must provide the
|
|
600
|
+
* exact locked session authority explicitly.
|
|
601
|
+
*/
|
|
602
|
+
export function assertSessionAuthoritySnapshot(input: {
|
|
603
|
+
attemptId?: string;
|
|
604
|
+
authorityEpoch: unknown;
|
|
605
|
+
authorityVisibility: unknown;
|
|
606
|
+
authorityOwnerOrganizationMembershipId: unknown;
|
|
607
|
+
}): SessionAuthoritySnapshot {
|
|
608
|
+
const valid =
|
|
609
|
+
Number.isSafeInteger(input.authorityEpoch) &&
|
|
610
|
+
(input.authorityEpoch as number) > 0 &&
|
|
611
|
+
(input.authorityVisibility === "user_private" ||
|
|
612
|
+
input.authorityVisibility === "workspace_shared") &&
|
|
613
|
+
((input.authorityVisibility === "user_private" &&
|
|
614
|
+
typeof input.authorityOwnerOrganizationMembershipId === "string") ||
|
|
615
|
+
(input.authorityVisibility === "workspace_shared" &&
|
|
616
|
+
(input.authorityOwnerOrganizationMembershipId === null ||
|
|
617
|
+
typeof input.authorityOwnerOrganizationMembershipId === "string")));
|
|
618
|
+
if (!valid) {
|
|
619
|
+
throw new SessionControlInvariantError(
|
|
620
|
+
`Attempt ${input.attemptId ?? "unknown"} has an invalid session authority snapshot`,
|
|
621
|
+
);
|
|
622
|
+
}
|
|
623
|
+
return {
|
|
624
|
+
authorityEpoch: input.authorityEpoch as number,
|
|
625
|
+
authorityVisibility:
|
|
626
|
+
input.authorityVisibility as SessionAuthoritySnapshot["authorityVisibility"],
|
|
627
|
+
authorityOwnerOrganizationMembershipId: input.authorityOwnerOrganizationMembershipId as
|
|
628
|
+
| string
|
|
629
|
+
| null,
|
|
630
|
+
};
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
export function sessionAuthoritySnapshotMatchesSession(
|
|
634
|
+
snapshot: SessionAuthoritySnapshot,
|
|
635
|
+
session: Pick<
|
|
636
|
+
typeof schema.sessions.$inferSelect,
|
|
637
|
+
"authorityEpoch" | "visibility" | "ownerOrganizationMembershipId"
|
|
638
|
+
>,
|
|
639
|
+
): boolean {
|
|
640
|
+
return (
|
|
641
|
+
snapshot.authorityEpoch === session.authorityEpoch &&
|
|
642
|
+
snapshot.authorityVisibility === session.visibility &&
|
|
643
|
+
snapshot.authorityOwnerOrganizationMembershipId ===
|
|
644
|
+
(session.ownerOrganizationMembershipId ?? null)
|
|
645
|
+
);
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
export function sessionAuthoritySnapshotsEqual(
|
|
649
|
+
left: Pick<
|
|
650
|
+
SessionAuthoritySnapshot,
|
|
651
|
+
"authorityEpoch" | "authorityVisibility" | "authorityOwnerOrganizationMembershipId"
|
|
652
|
+
>,
|
|
653
|
+
right: Pick<
|
|
654
|
+
SessionAuthoritySnapshot,
|
|
655
|
+
"authorityEpoch" | "authorityVisibility" | "authorityOwnerOrganizationMembershipId"
|
|
656
|
+
>,
|
|
657
|
+
): boolean {
|
|
658
|
+
return (
|
|
659
|
+
left.authorityEpoch === right.authorityEpoch &&
|
|
660
|
+
left.authorityVisibility === right.authorityVisibility &&
|
|
661
|
+
left.authorityOwnerOrganizationMembershipId === right.authorityOwnerOrganizationMembershipId
|
|
662
|
+
);
|
|
663
|
+
}
|
|
664
|
+
|
|
580
665
|
/**
|
|
581
666
|
* Close the exact first-class owner while the caller still holds the owning
|
|
582
667
|
* session/turn locks. Every path that clears `session_turns.active_attempt_id`
|
|
@@ -1163,7 +1248,10 @@ export async function evaluateSessionDiscoveryControls(
|
|
|
1163
1248
|
);
|
|
1164
1249
|
}
|
|
1165
1250
|
|
|
1166
|
-
|
|
1251
|
+
// Discovery owns one read-only repeatable-read snapshot, so this projection
|
|
1252
|
+
// must not join the writer lock graph merely to keep workspace/session facts
|
|
1253
|
+
// coherent. The snapshot is the consistency boundary.
|
|
1254
|
+
const workspace = await lockWorkspaceInferenceControl(db, workspaceId, "none");
|
|
1167
1255
|
const workspacePauseRevision = asSafeRevision(
|
|
1168
1256
|
workspace.workspacePauseRevision,
|
|
1169
1257
|
"workspace pause revision",
|
|
@@ -1412,12 +1500,12 @@ export async function reserveSessionCommandReceipt(
|
|
|
1412
1500
|
if (
|
|
1413
1501
|
identityScope === "goal_operation" &&
|
|
1414
1502
|
(input.actor.type !== "agent_attempt" ||
|
|
1415
|
-
|
|
1503
|
+
!["goal.update", "goal.progress"].includes(input.action) ||
|
|
1416
1504
|
input.targetSessionId === null ||
|
|
1417
1505
|
input.targetTurnId !== null)
|
|
1418
1506
|
) {
|
|
1419
1507
|
throw new SessionControlInvariantError(
|
|
1420
|
-
"Target-scoped receipt identity is reserved for agent goal
|
|
1508
|
+
"Target-scoped receipt identity is reserved for agent goal commands",
|
|
1421
1509
|
);
|
|
1422
1510
|
}
|
|
1423
1511
|
const actorSubjectId = input.actor.type === "agent_attempt" ? null : input.actor.subjectId;
|
|
@@ -2050,7 +2138,7 @@ async function assertSessionBranchIsNotCancelled(
|
|
|
2050
2138
|
}
|
|
2051
2139
|
|
|
2052
2140
|
async function cancelSessionSubtreeInTransaction(
|
|
2053
|
-
db:
|
|
2141
|
+
db: SessionActivityDatabase,
|
|
2054
2142
|
input: {
|
|
2055
2143
|
accountId: string;
|
|
2056
2144
|
workspaceId: string;
|
|
@@ -2375,7 +2463,7 @@ async function cancelSessionSubtreeInTransaction(
|
|
|
2375
2463
|
}
|
|
2376
2464
|
|
|
2377
2465
|
export async function mutateSessionControlInTransaction(
|
|
2378
|
-
db:
|
|
2466
|
+
db: SessionActivityDatabase,
|
|
2379
2467
|
input: {
|
|
2380
2468
|
accountId: string;
|
|
2381
2469
|
workspaceId: string;
|
|
@@ -2694,7 +2782,7 @@ export async function mutateSessionControlInTransaction(
|
|
|
2694
2782
|
}
|
|
2695
2783
|
|
|
2696
2784
|
export async function autoResumeSessionBranchInTransaction(
|
|
2697
|
-
db:
|
|
2785
|
+
db: SessionActivityDatabase,
|
|
2698
2786
|
input: {
|
|
2699
2787
|
workspaceId: string;
|
|
2700
2788
|
sessionId: string;
|