@opengeni/db 4.3.2 → 4.3.3-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-UVBPOGA7.js → chunk-232VC2LW.js} +2 -2
- package/dist/{chunk-DVSLOUEI.js → chunk-2ZMTQVTR.js} +2 -2
- package/dist/{chunk-AI4NC6XW.js → chunk-6TKL3GQO.js} +47 -1
- package/dist/chunk-6TKL3GQO.js.map +1 -0
- package/dist/{chunk-F4BIHJ7J.js → chunk-EYF6MH6C.js} +4 -4
- package/dist/{chunk-I4ITNMX2.js → chunk-GVZJ7XSR.js} +16 -4
- package/dist/{chunk-I4ITNMX2.js.map → chunk-GVZJ7XSR.js.map} +1 -1
- package/dist/{chunk-XBXANJQS.js → chunk-M7PSMVFF.js} +2 -2
- package/dist/{chunk-PFBUHOI5.js → chunk-QLA3UQNX.js} +3 -3
- package/dist/{chunk-YVYBAWBU.js → chunk-THJGMEK5.js} +53 -1
- package/dist/chunk-THJGMEK5.js.map +1 -0
- package/dist/{chunk-UUPY6IGP.js → chunk-UK57QA2H.js} +2 -2
- package/dist/connection-token-resolver.d.ts +2 -0
- package/dist/database.d.ts +7 -2
- package/dist/editable-artifact-durable-export.js +2 -2
- package/dist/editable-artifacts.js +3 -3
- package/dist/host-mcp-bindings.d.ts +3 -1
- package/dist/index.d.ts +9 -0
- package/dist/index.js +85 -26
- package/dist/index.js.map +1 -1
- package/dist/managed-auth-session-sets.js +3 -3
- package/dist/mcp-operations.d.ts +95 -0
- package/dist/mcp-operations.js +95 -0
- package/dist/mcp-operations.js.map +1 -0
- package/dist/provision-roles.js +1 -1
- package/dist/retained-provider-commands.js +2 -2
- package/dist/runtime-posture.d.ts +3 -3
- package/dist/schema.d.ts +517 -0
- package/dist/schema.js +3 -1
- package/dist/session-background-commands.js +4 -4
- package/dist/session-command-output.js +4 -4
- package/dist/session-event-slices.js +2 -2
- package/dist/session-tenancy.js +3 -3
- package/dist/video-generation.js +3 -3
- package/dist/workspace-tool-defaults.js +4 -4
- package/drizzle/0459_mcp_operations.sql +396 -0
- package/package.json +10 -6
- package/src/connection-token-resolver.ts +2 -0
- package/src/database.ts +23 -2
- package/src/host-mcp-bindings.ts +14 -1
- package/src/index.ts +84 -4
- package/src/mcp-operations.ts +189 -0
- package/src/provision-roles.ts +6 -0
- package/src/runtime-posture.ts +50 -0
- package/src/schema.ts +46 -0
- package/dist/chunk-AI4NC6XW.js.map +0 -1
- package/dist/chunk-YVYBAWBU.js.map +0 -1
- /package/dist/{chunk-UVBPOGA7.js.map → chunk-232VC2LW.js.map} +0 -0
- /package/dist/{chunk-DVSLOUEI.js.map → chunk-2ZMTQVTR.js.map} +0 -0
- /package/dist/{chunk-F4BIHJ7J.js.map → chunk-EYF6MH6C.js.map} +0 -0
- /package/dist/{chunk-XBXANJQS.js.map → chunk-M7PSMVFF.js.map} +0 -0
- /package/dist/{chunk-PFBUHOI5.js.map → chunk-QLA3UQNX.js.map} +0 -0
- /package/dist/{chunk-UUPY6IGP.js.map → chunk-UK57QA2H.js.map} +0 -0
package/src/index.ts
CHANGED
|
@@ -272,6 +272,7 @@ import {
|
|
|
272
272
|
SANDBOX_PROVIDER_INSTANCE_ID_FIELDS_BY_BACKEND,
|
|
273
273
|
parseWorkspaceArchiveDescriptor,
|
|
274
274
|
parseWorkspaceArchiveObjectRef,
|
|
275
|
+
validateWorkspaceArchiveObjectRef,
|
|
275
276
|
workspaceArchivePayloadPresent,
|
|
276
277
|
omitInlineWorkspaceArchiveWhenObjectRefPresent,
|
|
277
278
|
type WorkspaceArchiveObjectRef,
|
|
@@ -53448,13 +53449,30 @@ export async function adoptLegacyModalCheckpointArtifact(
|
|
|
53448
53449
|
}
|
|
53449
53450
|
|
|
53450
53451
|
function publishedWorkspaceArchiveFields(input: {
|
|
53452
|
+
accountId: string;
|
|
53453
|
+
workspaceId: string;
|
|
53454
|
+
sandboxGroupId: string;
|
|
53455
|
+
workspaceArchiveMeta: SandboxArchiveRevision;
|
|
53451
53456
|
workspaceArchive?: string | null;
|
|
53452
53457
|
workspaceArchiveRef?: WorkspaceArchiveObjectRef | null;
|
|
53453
53458
|
}): {
|
|
53454
53459
|
workspaceArchive?: string;
|
|
53455
53460
|
workspaceArchiveRef?: WorkspaceArchiveObjectRef;
|
|
53456
53461
|
} {
|
|
53457
|
-
const ref =
|
|
53462
|
+
const ref =
|
|
53463
|
+
input.workspaceArchiveRef == null
|
|
53464
|
+
? undefined
|
|
53465
|
+
: (validateWorkspaceArchiveObjectRef(input.workspaceArchiveRef, {
|
|
53466
|
+
accountId: input.accountId,
|
|
53467
|
+
workspaceId: input.workspaceId,
|
|
53468
|
+
sandboxGroupId: input.sandboxGroupId,
|
|
53469
|
+
descriptor: input.workspaceArchiveMeta,
|
|
53470
|
+
}) ?? undefined);
|
|
53471
|
+
if (input.workspaceArchiveRef != null && !ref) {
|
|
53472
|
+
throw new Error(
|
|
53473
|
+
"Invalid workspace archive object ref: publication scope or descriptor mismatch",
|
|
53474
|
+
);
|
|
53475
|
+
}
|
|
53458
53476
|
const inline =
|
|
53459
53477
|
typeof input.workspaceArchive === "string" && input.workspaceArchive.length > 0
|
|
53460
53478
|
? input.workspaceArchive
|
|
@@ -53475,6 +53493,30 @@ function publishedWorkspaceArchiveFields(input: {
|
|
|
53475
53493
|
return { workspaceArchive: inline };
|
|
53476
53494
|
}
|
|
53477
53495
|
|
|
53496
|
+
/** Object-candidate outcome from the publication transaction, independent of
|
|
53497
|
+
* lifecycle `wrote`. Absent for inline/provider receipts and pure CAS checks.
|
|
53498
|
+
* `unused` is NOT a retirement receipt: only the owner of a fresh candidate with
|
|
53499
|
+
* no other publication in flight may use it for immediate cleanup. Exceptions
|
|
53500
|
+
* give no disposition (commit may have happened). Legacy/shared keys and evicted
|
|
53501
|
+
* refs need durable no-reattachment evidence before deletion. */
|
|
53502
|
+
export type WorkspaceArchiveCandidateDisposition = "adopted" | "already_referenced" | "unused";
|
|
53503
|
+
|
|
53504
|
+
function workspaceArchiveCandidateFields(
|
|
53505
|
+
candidate: WorkspaceArchiveObjectRef | undefined,
|
|
53506
|
+
lockedResumeState: Record<string, unknown> | null | undefined,
|
|
53507
|
+
): { candidateDisposition?: WorkspaceArchiveCandidateDisposition } {
|
|
53508
|
+
if (!candidate) return {};
|
|
53509
|
+
const sessionState = lockedResumeState?.sessionState as Record<string, unknown> | undefined;
|
|
53510
|
+
const referenced = [
|
|
53511
|
+
sessionState?.workspaceArchiveRef,
|
|
53512
|
+
sessionState?.workspaceArchivePrevRef,
|
|
53513
|
+
].some((value) => {
|
|
53514
|
+
const ref = parseWorkspaceArchiveObjectRef(value);
|
|
53515
|
+
return ref?.key === candidate.key && ref.backend === candidate.backend;
|
|
53516
|
+
});
|
|
53517
|
+
return { candidateDisposition: referenced ? "already_referenced" : "unused" };
|
|
53518
|
+
}
|
|
53519
|
+
|
|
53478
53520
|
export async function persistDrainSnapshot(
|
|
53479
53521
|
db: Database,
|
|
53480
53522
|
input: {
|
|
@@ -53511,12 +53553,14 @@ export async function persistDrainSnapshot(
|
|
|
53511
53553
|
): Promise<{
|
|
53512
53554
|
wrote: boolean;
|
|
53513
53555
|
archiveRevision: string | null;
|
|
53556
|
+
candidateDisposition?: WorkspaceArchiveCandidateDisposition;
|
|
53514
53557
|
}> {
|
|
53515
53558
|
const workspaceArchiveMeta =
|
|
53516
53559
|
input.workspaceArchive === null ? null : parseArchiveRevision(input.workspaceArchiveMeta);
|
|
53517
53560
|
if (input.workspaceArchive !== null && !workspaceArchiveMeta) {
|
|
53518
53561
|
throw new Error("Invalid verified workspace archive descriptor");
|
|
53519
53562
|
}
|
|
53563
|
+
const published = input.workspaceArchive === null ? null : publishedWorkspaceArchiveFields(input);
|
|
53520
53564
|
if (
|
|
53521
53565
|
workspaceArchiveMeta?.version === 2 &&
|
|
53522
53566
|
(workspaceArchiveMeta.provider === "modal_snapshot_filesystem" ||
|
|
@@ -53575,10 +53619,15 @@ export async function persistDrainSnapshot(
|
|
|
53575
53619
|
for update
|
|
53576
53620
|
`);
|
|
53577
53621
|
const row = guard[0];
|
|
53622
|
+
const candidateFields = workspaceArchiveCandidateFields(
|
|
53623
|
+
published?.workspaceArchiveRef,
|
|
53624
|
+
row?.resume_state,
|
|
53625
|
+
);
|
|
53578
53626
|
if (!row) {
|
|
53579
53627
|
return {
|
|
53580
53628
|
wrote: false,
|
|
53581
53629
|
archiveRevision: null,
|
|
53630
|
+
...candidateFields,
|
|
53582
53631
|
};
|
|
53583
53632
|
}
|
|
53584
53633
|
const sourceLeaseMatches =
|
|
@@ -53624,7 +53673,7 @@ export async function persistDrainSnapshot(
|
|
|
53624
53673
|
lateReceipt.providerRequestId === input.providerRequestId &&
|
|
53625
53674
|
!row.unsettled_mutation;
|
|
53626
53675
|
if (!activePublication && !coldLatePublication) {
|
|
53627
|
-
return { wrote: false, archiveRevision: null };
|
|
53676
|
+
return { wrote: false, archiveRevision: null, ...candidateFields };
|
|
53628
53677
|
}
|
|
53629
53678
|
const priorArchive = row.prior_archive ?? null;
|
|
53630
53679
|
const priorArchivePrev = row.prior_archive_prev ?? null;
|
|
@@ -53642,7 +53691,7 @@ export async function persistDrainSnapshot(
|
|
|
53642
53691
|
archiveRevision: null,
|
|
53643
53692
|
};
|
|
53644
53693
|
}
|
|
53645
|
-
|
|
53694
|
+
if (!published) throw new Error("Missing workspace archive publication fields");
|
|
53646
53695
|
const priorMeta = parseArchiveRevision(priorSessionState?.workspaceArchiveMeta);
|
|
53647
53696
|
if (activePublication && row.archive_capture_published_at !== null) {
|
|
53648
53697
|
// A predecessor and its successor may receive the same provider result.
|
|
@@ -53668,7 +53717,7 @@ export async function persistDrainSnapshot(
|
|
|
53668
53717
|
)
|
|
53669
53718
|
`);
|
|
53670
53719
|
}
|
|
53671
|
-
return { wrote: true, archiveRevision: priorMeta.revision };
|
|
53720
|
+
return { wrote: true, archiveRevision: priorMeta.revision, ...candidateFields };
|
|
53672
53721
|
}
|
|
53673
53722
|
const rotation = rotateWorkspaceArchives({
|
|
53674
53723
|
resumeState: row.resume_state,
|
|
@@ -53729,11 +53778,13 @@ export async function persistDrainSnapshot(
|
|
|
53729
53778
|
return {
|
|
53730
53779
|
wrote: false,
|
|
53731
53780
|
archiveRevision: null,
|
|
53781
|
+
...candidateFields,
|
|
53732
53782
|
};
|
|
53733
53783
|
}
|
|
53734
53784
|
return {
|
|
53735
53785
|
wrote: true,
|
|
53736
53786
|
archiveRevision: workspaceArchiveMeta?.revision ?? null,
|
|
53787
|
+
...(published.workspaceArchiveRef ? { candidateDisposition: "adopted" as const } : {}),
|
|
53737
53788
|
};
|
|
53738
53789
|
},
|
|
53739
53790
|
);
|
|
@@ -54132,6 +54183,7 @@ export async function persistWarmSnapshot(
|
|
|
54132
54183
|
throttled: boolean;
|
|
54133
54184
|
superseded: boolean;
|
|
54134
54185
|
archiveRevision: string | null;
|
|
54186
|
+
candidateDisposition?: WorkspaceArchiveCandidateDisposition;
|
|
54135
54187
|
}> {
|
|
54136
54188
|
const capturedAtMs = input.capturedAtMs ?? Date.now();
|
|
54137
54189
|
const workspaceArchiveMeta = parseArchiveRevision(input.workspaceArchiveMeta);
|
|
@@ -54201,6 +54253,26 @@ export async function persistWarmSnapshot(
|
|
|
54201
54253
|
(attempt.outcome === "completed" ||
|
|
54202
54254
|
attempt.outcome === "failed" ||
|
|
54203
54255
|
attempt.outcome === "requires_action"));
|
|
54256
|
+
// Even a replay rejected by the attempt/epoch/capture guards may name
|
|
54257
|
+
// a committed current or previous object. Inspect those slots under the
|
|
54258
|
+
// same lease lock as publication, after the canonical workspace lock.
|
|
54259
|
+
// This conveys no retirement or no-future-reattachment authority.
|
|
54260
|
+
const candidateLease = published.workspaceArchiveRef
|
|
54261
|
+
? await scopedDb.execute<{ resume_state: Record<string, unknown> | null }>(sql`
|
|
54262
|
+
select jsonb_build_object('sessionState', jsonb_build_object(
|
|
54263
|
+
'workspaceArchiveRef', resume_state #> '{sessionState,workspaceArchiveRef}',
|
|
54264
|
+
'workspaceArchivePrevRef', resume_state #> '{sessionState,workspaceArchivePrevRef}'
|
|
54265
|
+
)) as resume_state
|
|
54266
|
+
from sandbox_leases
|
|
54267
|
+
where workspace_id = ${input.workspaceId}
|
|
54268
|
+
and sandbox_group_id = ${input.sandboxGroupId}
|
|
54269
|
+
for update
|
|
54270
|
+
`)
|
|
54271
|
+
: [];
|
|
54272
|
+
const candidateFields = workspaceArchiveCandidateFields(
|
|
54273
|
+
published.workspaceArchiveRef,
|
|
54274
|
+
candidateLease[0]?.resume_state,
|
|
54275
|
+
);
|
|
54204
54276
|
if (
|
|
54205
54277
|
!attempt ||
|
|
54206
54278
|
attempt.accountId !== input.accountId ||
|
|
@@ -54213,6 +54285,7 @@ export async function persistWarmSnapshot(
|
|
|
54213
54285
|
throttled: false,
|
|
54214
54286
|
superseded: true,
|
|
54215
54287
|
archiveRevision: null,
|
|
54288
|
+
...candidateFields,
|
|
54216
54289
|
};
|
|
54217
54290
|
}
|
|
54218
54291
|
const guard = await scopedDb.execute<{
|
|
@@ -54270,6 +54343,7 @@ export async function persistWarmSnapshot(
|
|
|
54270
54343
|
throttled: false,
|
|
54271
54344
|
superseded: false,
|
|
54272
54345
|
archiveRevision: null,
|
|
54346
|
+
...candidateFields,
|
|
54273
54347
|
};
|
|
54274
54348
|
}
|
|
54275
54349
|
const priorArchive = guard[0]!.prior_archive ?? null;
|
|
@@ -54290,6 +54364,7 @@ export async function persistWarmSnapshot(
|
|
|
54290
54364
|
throttled: false,
|
|
54291
54365
|
superseded: true,
|
|
54292
54366
|
archiveRevision: null,
|
|
54367
|
+
...candidateFields,
|
|
54293
54368
|
};
|
|
54294
54369
|
}
|
|
54295
54370
|
if (
|
|
@@ -54302,6 +54377,7 @@ export async function persistWarmSnapshot(
|
|
|
54302
54377
|
throttled: true,
|
|
54303
54378
|
superseded: false,
|
|
54304
54379
|
archiveRevision: null,
|
|
54380
|
+
...candidateFields,
|
|
54305
54381
|
};
|
|
54306
54382
|
}
|
|
54307
54383
|
const rotation = rotateWorkspaceArchives({
|
|
@@ -54323,6 +54399,7 @@ export async function persistWarmSnapshot(
|
|
|
54323
54399
|
throttled: false,
|
|
54324
54400
|
superseded: false,
|
|
54325
54401
|
archiveRevision: null,
|
|
54402
|
+
...candidateFields,
|
|
54326
54403
|
};
|
|
54327
54404
|
}
|
|
54328
54405
|
const livenessGuard: "warm" | "draining" = rowLiveness;
|
|
@@ -54355,6 +54432,7 @@ export async function persistWarmSnapshot(
|
|
|
54355
54432
|
throttled: false,
|
|
54356
54433
|
superseded: false,
|
|
54357
54434
|
archiveRevision: null,
|
|
54435
|
+
...candidateFields,
|
|
54358
54436
|
};
|
|
54359
54437
|
}
|
|
54360
54438
|
return {
|
|
@@ -54362,6 +54440,7 @@ export async function persistWarmSnapshot(
|
|
|
54362
54440
|
throttled: false,
|
|
54363
54441
|
superseded: false,
|
|
54364
54442
|
archiveRevision: workspaceArchiveMeta.revision,
|
|
54443
|
+
...(published.workspaceArchiveRef ? { candidateDisposition: "adopted" as const } : {}),
|
|
54365
54444
|
};
|
|
54366
54445
|
},
|
|
54367
54446
|
);
|
|
@@ -64024,6 +64103,7 @@ export async function claimSessionWorkForAttempt(
|
|
|
64024
64103
|
stage: "session_attempts.claim",
|
|
64025
64104
|
eventTypes: ["session.turn.attempt_claimed"],
|
|
64026
64105
|
maxAttempts: 3,
|
|
64106
|
+
organizationMembershipFence: true,
|
|
64027
64107
|
},
|
|
64028
64108
|
async (scopedDb) =>
|
|
64029
64109
|
await withSessionActivitySavepoint(scopedDb, async (tx) => {
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { AttemptToolResult } from "@opengeni/contracts";
|
|
2
|
+
import { sql } from "drizzle-orm";
|
|
3
|
+
import { type Database, withRlsContext } from "./database";
|
|
4
|
+
import {
|
|
5
|
+
fromPostgresLosslessJson,
|
|
6
|
+
toPostgresLosslessJson,
|
|
7
|
+
LOSSLESS_CONTENT_CODEC_VERSION,
|
|
8
|
+
} from "./lossless-json";
|
|
9
|
+
|
|
10
|
+
/** Worker-authenticated invocation identity, never model/HTTP/request JSON.
|
|
11
|
+
* Possessing a DB handle or matching GUCs does NOT authenticate a caller.
|
|
12
|
+
* Bind this tuple only after verifying the worker invocation credential. SQL
|
|
13
|
+
* then derives the principal and rechecks canonical live disclosure authority. */
|
|
14
|
+
export type McpOperationAttempt = {
|
|
15
|
+
accountId: string;
|
|
16
|
+
workspaceId: string;
|
|
17
|
+
sessionId: string;
|
|
18
|
+
turnId: string;
|
|
19
|
+
attemptId: string;
|
|
20
|
+
executionGeneration: number;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/** Structurally aligned with runtime CapturedMcpOperation, without a runtime dependency. */
|
|
24
|
+
export type CaptureMcpOperationInput = {
|
|
25
|
+
operationId: string;
|
|
26
|
+
sourceCallId?: string;
|
|
27
|
+
serverId: string;
|
|
28
|
+
originalTool: string;
|
|
29
|
+
observerTool: string;
|
|
30
|
+
destinationDigest: string;
|
|
31
|
+
argumentDigest: string;
|
|
32
|
+
authorityDigest: string;
|
|
33
|
+
};
|
|
34
|
+
export type McpOperationSelector =
|
|
35
|
+
| { operationId: string }
|
|
36
|
+
| { sourceTurnId: string; sourceCallId: string };
|
|
37
|
+
export type McpOperationRecord = Omit<CaptureMcpOperationInput, "sourceCallId"> & {
|
|
38
|
+
sourceCallId: string | null;
|
|
39
|
+
accountId: string;
|
|
40
|
+
workspaceId: string;
|
|
41
|
+
sessionId: string;
|
|
42
|
+
sourceTurnId: string;
|
|
43
|
+
sourceAttemptId: string;
|
|
44
|
+
sourceExecutionGeneration: number;
|
|
45
|
+
principalKind: "subject" | "service";
|
|
46
|
+
principalId: string;
|
|
47
|
+
/** captured means possibly dispatched, NEVER permission to replay a mutation. */
|
|
48
|
+
originalOutcome: "captured" | "completed" | "outcome_unknown";
|
|
49
|
+
originalResult: AttemptToolResult | null;
|
|
50
|
+
observationResult: AttemptToolResult | null;
|
|
51
|
+
receiptRevision: string | null;
|
|
52
|
+
receiptDigest: string | null;
|
|
53
|
+
};
|
|
54
|
+
export type McpOperationLookup =
|
|
55
|
+
| { status: "found"; operation: McpOperationRecord }
|
|
56
|
+
| { status: "not_found" | "ambiguous" };
|
|
57
|
+
|
|
58
|
+
async function command<T>(
|
|
59
|
+
db: Database,
|
|
60
|
+
attempt: McpOperationAttempt,
|
|
61
|
+
action: string,
|
|
62
|
+
payload: object,
|
|
63
|
+
): Promise<T> {
|
|
64
|
+
return withRlsContext(
|
|
65
|
+
db,
|
|
66
|
+
{ accountId: attempt.accountId, workspaceId: attempt.workspaceId },
|
|
67
|
+
async (tx) => {
|
|
68
|
+
const result =
|
|
69
|
+
await tx.execute(sql`select mcp_operation_command(${JSON.stringify(attempt)}::jsonb,
|
|
70
|
+
${action}::text, ${JSON.stringify(payload)}::jsonb) as value`);
|
|
71
|
+
const rows = Array.isArray(result) ? result : result.rows;
|
|
72
|
+
if (!rows?.[0]) throw new Error("MCP operation command returned no receipt");
|
|
73
|
+
return rows[0].value as T;
|
|
74
|
+
},
|
|
75
|
+
undefined,
|
|
76
|
+
"none", // SQL owns membership -> tenancy -> control -> session lock order.
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function captureMcpOperation(
|
|
81
|
+
db: Database,
|
|
82
|
+
attempt: McpOperationAttempt,
|
|
83
|
+
operation: CaptureMcpOperationInput,
|
|
84
|
+
) {
|
|
85
|
+
return command<"created" | "existing">(db, attempt, "capture", operation);
|
|
86
|
+
}
|
|
87
|
+
export async function settleOriginalMcpOperation(
|
|
88
|
+
db: Database,
|
|
89
|
+
attempt: McpOperationAttempt,
|
|
90
|
+
input:
|
|
91
|
+
| { operationId: string; outcome: "completed"; result: AttemptToolResult }
|
|
92
|
+
| { operationId: string; outcome: "outcome_unknown" },
|
|
93
|
+
): Promise<void> {
|
|
94
|
+
const payload =
|
|
95
|
+
input.outcome === "completed"
|
|
96
|
+
? {
|
|
97
|
+
...input,
|
|
98
|
+
result: toPostgresLosslessJson(AttemptToolResult.parse(input.result)),
|
|
99
|
+
resultCodecVersion: LOSSLESS_CONTENT_CODEC_VERSION,
|
|
100
|
+
}
|
|
101
|
+
: input;
|
|
102
|
+
const result = await command<{ status: string }>(db, attempt, "settle_original", payload);
|
|
103
|
+
if (result.status !== "settled") throw new Error("Original MCP operation not found");
|
|
104
|
+
}
|
|
105
|
+
export async function readMcpOperation(
|
|
106
|
+
db: Database,
|
|
107
|
+
attempt: McpOperationAttempt,
|
|
108
|
+
selector: McpOperationSelector,
|
|
109
|
+
): Promise<McpOperationLookup> {
|
|
110
|
+
const result = await command<McpOperationLookup>(db, attempt, "read", selector);
|
|
111
|
+
if (result.status !== "found") return result;
|
|
112
|
+
const { originalResultCodecVersion, observationResultCodecVersion, ...operation } =
|
|
113
|
+
result.operation as McpOperationRecord & {
|
|
114
|
+
originalResultCodecVersion: number | null;
|
|
115
|
+
observationResultCodecVersion: number | null;
|
|
116
|
+
};
|
|
117
|
+
return {
|
|
118
|
+
status: "found",
|
|
119
|
+
operation: {
|
|
120
|
+
...operation,
|
|
121
|
+
originalResult: fromPostgresLosslessJson(
|
|
122
|
+
operation.originalResult,
|
|
123
|
+
originalResultCodecVersion,
|
|
124
|
+
),
|
|
125
|
+
observationResult: fromPostgresLosslessJson(
|
|
126
|
+
operation.observationResult,
|
|
127
|
+
observationResultCodecVersion,
|
|
128
|
+
),
|
|
129
|
+
},
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
/** Claims authorize only the read observer; expiry never authorizes a mutation. */
|
|
133
|
+
export function claimMcpOperationObservation(
|
|
134
|
+
db: Database,
|
|
135
|
+
attempt: McpOperationAttempt,
|
|
136
|
+
operationId: string,
|
|
137
|
+
) {
|
|
138
|
+
return command<
|
|
139
|
+
{ status: "claimed"; claimId: string } | { status: "busy" | "terminal" | "not_found" }
|
|
140
|
+
>(db, attempt, "claim_read", { operationId });
|
|
141
|
+
}
|
|
142
|
+
export function settleMcpOperationObservation(
|
|
143
|
+
db: Database,
|
|
144
|
+
attempt: McpOperationAttempt,
|
|
145
|
+
input: {
|
|
146
|
+
operationId: string;
|
|
147
|
+
claimId: string;
|
|
148
|
+
receiptRevision: string;
|
|
149
|
+
result: AttemptToolResult;
|
|
150
|
+
},
|
|
151
|
+
) {
|
|
152
|
+
// This atomically stores one receipt, not an autonomous session notification.
|
|
153
|
+
// Explicit operation_read is a new ordinary tool call: its existing result
|
|
154
|
+
// lifecycle delivers the evidence. Repeated explicit reads legitimately have
|
|
155
|
+
// distinct call outputs while the original timeout and receipt stay immutable.
|
|
156
|
+
return command<
|
|
157
|
+
| { status: "settled" | "existing" | "conflict"; receiptDigest: string }
|
|
158
|
+
| { status: "stale_claim" | "not_found" | "original_completed" }
|
|
159
|
+
>(db, attempt, "settle_observation", {
|
|
160
|
+
...input,
|
|
161
|
+
result: toPostgresLosslessJson(AttemptToolResult.parse(input.result)),
|
|
162
|
+
resultCodecVersion: LOSSLESS_CONTENT_CODEC_VERSION,
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/** Unknown/pending/error cleanup only; never releases or replaces a receipt. */
|
|
167
|
+
export function releaseMcpOperationObservation(
|
|
168
|
+
db: Database,
|
|
169
|
+
attempt: McpOperationAttempt,
|
|
170
|
+
input: { operationId: string; claimId: string },
|
|
171
|
+
) {
|
|
172
|
+
return command<{ status: "released" | "stale_claim" | "terminal" | "not_found" }>(
|
|
173
|
+
db,
|
|
174
|
+
attempt,
|
|
175
|
+
"release_read",
|
|
176
|
+
input,
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/** Bind only inside the trusted worker, after exact invocation authentication.
|
|
181
|
+
* Provider authorization and immutable binding fences remain the broker's job. */
|
|
182
|
+
export function createMcpOperationPersistence(db: Database, attempt: McpOperationAttempt) {
|
|
183
|
+
const frozen = { ...attempt };
|
|
184
|
+
return {
|
|
185
|
+
capture: (operation: CaptureMcpOperationInput) => captureMcpOperation(db, frozen, operation),
|
|
186
|
+
settleOriginal: (input: Parameters<typeof settleOriginalMcpOperation>[2]) =>
|
|
187
|
+
settleOriginalMcpOperation(db, frozen, input),
|
|
188
|
+
};
|
|
189
|
+
}
|
package/src/provision-roles.ts
CHANGED
|
@@ -618,6 +618,10 @@ DECLARE
|
|
|
618
618
|
BEGIN
|
|
619
619
|
EXECUTE format('REVOKE CREATE ON DATABASE %I FROM %I', current_database(), ${literal(role)});
|
|
620
620
|
IF EXISTS (SELECT 1 FROM pg_namespace WHERE nspname = ${literal(schema)}) THEN
|
|
621
|
+
IF to_regprocedure(format('%I.mcp_operation_command(jsonb,text,jsonb)', ${literal(schema)})) IS NOT NULL THEN
|
|
622
|
+
EXECUTE format('REVOKE ALL ON FUNCTION %I.mcp_operation_command(jsonb,text,jsonb) FROM PUBLIC', ${literal(schema)});
|
|
623
|
+
EXECUTE format('GRANT EXECUTE ON FUNCTION %I.mcp_operation_command(jsonb,text,jsonb) TO %I', ${literal(schema)}, ${literal(role)});
|
|
624
|
+
END IF;
|
|
621
625
|
EXECUTE format('GRANT USAGE ON SCHEMA %I TO %I', ${literal(schema)}, ${literal(role)});
|
|
622
626
|
EXECUTE format('REVOKE CREATE ON SCHEMA %I FROM %I', ${literal(schema)}, ${literal(role)});
|
|
623
627
|
EXECUTE format('REVOKE ALL PRIVILEGES ON ALL TABLES IN SCHEMA %I FROM %I', ${literal(schema)}, ${literal(role)});
|
|
@@ -2120,6 +2124,8 @@ BEGIN
|
|
|
2120
2124
|
EXECUTE format('REVOKE CREATE ON SCHEMA opengeni_private FROM %I', ${literal(role)});
|
|
2121
2125
|
EXECUTE format('GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA opengeni_private TO %I', ${literal(role)});
|
|
2122
2126
|
FOREACH routine_signature IN ARRAY ARRAY[
|
|
2127
|
+
'guard_mcp_operation_immutable()',
|
|
2128
|
+
'mcp_operation_command_scoped(jsonb,text,jsonb)',
|
|
2123
2129
|
'guard_workspace_owned_skill_head_delete()',
|
|
2124
2130
|
'guard_workspace_owned_skill_history_delete()'
|
|
2125
2131
|
] LOOP
|
package/src/runtime-posture.ts
CHANGED
|
@@ -51,7 +51,24 @@ const AUTOMATIC_SESSION_TITLE_FANOUT_OUTBOX_TABLE = "automatic_session_title_fan
|
|
|
51
51
|
const AUTOMATIC_SESSION_TITLE_QUARANTINE_FENCE_ROUTINE =
|
|
52
52
|
"acquire_automatic_session_title_quarantine_fences_v1(integer)";
|
|
53
53
|
|
|
54
|
+
const MCP_OPERATION_CAPABILITY_ROUTINE = "mcp_operation_command(jsonb, text, jsonb)";
|
|
55
|
+
const MCP_OPERATION_AUTHORITY_TABLES = [
|
|
56
|
+
"mcp_operations",
|
|
57
|
+
"sessions",
|
|
58
|
+
"session_turns",
|
|
59
|
+
"session_turn_attempts",
|
|
60
|
+
"workspaces",
|
|
61
|
+
"workspace_inference_controls",
|
|
62
|
+
"organization_memberships",
|
|
63
|
+
"workspace_memberships",
|
|
64
|
+
"external_identity_links",
|
|
65
|
+
"external_link_turn_authorities",
|
|
66
|
+
"host_mcp_turn_authorities",
|
|
67
|
+
"scheduled_task_runs",
|
|
68
|
+
] as const;
|
|
54
69
|
const OWNER_INTERNAL_PRIVATE_ROUTINES = new Set<string>([
|
|
70
|
+
"guard_mcp_operation_immutable()",
|
|
71
|
+
"mcp_operation_command_scoped(jsonb, text, jsonb)",
|
|
55
72
|
"guard_workspace_owned_skill_head_delete()",
|
|
56
73
|
"guard_workspace_owned_skill_history_delete()",
|
|
57
74
|
...ARTIFACT_OUTBOX_CAPABILITY_ROUTINES,
|
|
@@ -557,6 +574,7 @@ const XAI_AUTHORITY_TABLES = [
|
|
|
557
574
|
] as const;
|
|
558
575
|
|
|
559
576
|
export const RUNTIME_TARGET_SCHEMA_CAPABILITY_ROUTINES = [
|
|
577
|
+
MCP_OPERATION_CAPABILITY_ROUTINE,
|
|
560
578
|
"skill_apply_lifecycle(uuid, uuid, jsonb, jsonb)",
|
|
561
579
|
COMPANY_BRAIN_CONTEXT_INSPECTION_ROUTINE,
|
|
562
580
|
COMPANY_BRAIN_CONTEXT_SELECTION_ROUTINE,
|
|
@@ -807,6 +825,7 @@ export const FORCE_RLS_TABLES = [
|
|
|
807
825
|
"managed_auth_login_transactions",
|
|
808
826
|
"managed_auth_session_set_operations",
|
|
809
827
|
"managed_auth_session_sets",
|
|
828
|
+
"mcp_operations",
|
|
810
829
|
"memory_slack_publication_configurations",
|
|
811
830
|
"memory_slack_publication_receipts",
|
|
812
831
|
"memory_slack_publications",
|
|
@@ -1381,6 +1400,7 @@ export const PROTECTED_NO_DIRECT_DML_TABLES = [
|
|
|
1381
1400
|
"managed_auth_login_transactions",
|
|
1382
1401
|
"managed_auth_session_set_operations",
|
|
1383
1402
|
"managed_auth_session_sets",
|
|
1403
|
+
"mcp_operations",
|
|
1384
1404
|
"organization_company_profile_agent_policies",
|
|
1385
1405
|
"organization_company_profile_agent_policy_events",
|
|
1386
1406
|
"organization_invitation_binding_events",
|
|
@@ -2231,6 +2251,19 @@ export function evaluateRuntimeDatabasePosture(
|
|
|
2231
2251
|
);
|
|
2232
2252
|
}
|
|
2233
2253
|
}
|
|
2254
|
+
} else if (routine.name === MCP_OPERATION_CAPABILITY_ROUTINE) {
|
|
2255
|
+
const missing = MCP_OPERATION_AUTHORITY_TABLES.filter((name) => !tableByName.has(name));
|
|
2256
|
+
if (missing.length > 0) {
|
|
2257
|
+
violations.push(`MCP operation authority tables are missing: ${missing.join(", ")}`);
|
|
2258
|
+
} else if (
|
|
2259
|
+
MCP_OPERATION_AUTHORITY_TABLES.some(
|
|
2260
|
+
(name) => tableByName.get(name)!.owner !== routine.owner,
|
|
2261
|
+
)
|
|
2262
|
+
) {
|
|
2263
|
+
violations.push(
|
|
2264
|
+
`MCP operation capability ${routine.name} authority table owners do not match`,
|
|
2265
|
+
);
|
|
2266
|
+
}
|
|
2234
2267
|
} else if (routine.name === KNOWLEDGE_SOURCE_SYNC_LOCK_AUTHORITY_ROUTINE) {
|
|
2235
2268
|
const missingAuthorityTables = KNOWLEDGE_SOURCE_SYNC_LOCK_AUTHORITY_TABLES.filter(
|
|
2236
2269
|
(tableName) => !tableByName.has(tableName),
|
|
@@ -3385,6 +3418,23 @@ export function evaluateRuntimeDatabasePosture(
|
|
|
3385
3418
|
violations.push(`runtime role owns private routine ${routine.name}`);
|
|
3386
3419
|
}
|
|
3387
3420
|
const ownerInternalRoutine = OWNER_INTERNAL_PRIVATE_ROUTINES.has(routine.name);
|
|
3421
|
+
if (
|
|
3422
|
+
[
|
|
3423
|
+
"guard_mcp_operation_immutable()",
|
|
3424
|
+
"mcp_operation_command_scoped(jsonb, text, jsonb)",
|
|
3425
|
+
].includes(routine.name)
|
|
3426
|
+
) {
|
|
3427
|
+
if (routine.execute || routine.publicExecute) {
|
|
3428
|
+
violations.push(
|
|
3429
|
+
`runtime or PUBLIC has forbidden EXECUTE on MCP operation internal routine ${routine.name}`,
|
|
3430
|
+
);
|
|
3431
|
+
}
|
|
3432
|
+
if (routine.owner !== tableByName.get("mcp_operations")?.owner) {
|
|
3433
|
+
violations.push(
|
|
3434
|
+
`MCP operation internal routine ${routine.name} owner does not match ledger owner`,
|
|
3435
|
+
);
|
|
3436
|
+
}
|
|
3437
|
+
}
|
|
3388
3438
|
if (
|
|
3389
3439
|
[
|
|
3390
3440
|
"guard_workspace_owned_skill_head_delete()",
|
package/src/schema.ts
CHANGED
|
@@ -6928,6 +6928,52 @@ export const sessionRealtimeContextProjections = pgTable(
|
|
|
6928
6928
|
// First-class ownership for one accepted execution attempt. A workflow may
|
|
6929
6929
|
// preallocate id, but this row is inserted only by the activity transaction
|
|
6930
6930
|
// that actually claims the logical turn and registers its exact dispatch.
|
|
6931
|
+
// Protected EXECUTE-only ledger. SQL owns live-attempt/principal derivation,
|
|
6932
|
+
// immutable settlement, bounds, RLS and source ownership constraints.
|
|
6933
|
+
export const mcpOperations = pgTable(
|
|
6934
|
+
"mcp_operations",
|
|
6935
|
+
{
|
|
6936
|
+
operationId: uuid("operation_id").primaryKey(),
|
|
6937
|
+
accountId: uuid("account_id").notNull(),
|
|
6938
|
+
workspaceId: uuid("workspace_id").notNull(),
|
|
6939
|
+
sessionId: uuid("session_id").notNull(),
|
|
6940
|
+
sourceTurnId: uuid("source_turn_id").notNull(),
|
|
6941
|
+
sourceAttemptId: uuid("source_attempt_id").notNull(),
|
|
6942
|
+
sourceExecutionGeneration: integer("source_execution_generation").notNull(),
|
|
6943
|
+
sourceCallId: text("source_call_id"),
|
|
6944
|
+
principalKind: text("principal_kind").notNull(),
|
|
6945
|
+
principalId: text("principal_id").notNull(),
|
|
6946
|
+
principalMembershipId: uuid("principal_membership_id"),
|
|
6947
|
+
principalMembershipRevision: bigint("principal_membership_revision", { mode: "number" }),
|
|
6948
|
+
serverId: text("server_id").notNull(),
|
|
6949
|
+
originalTool: text("original_tool").notNull(),
|
|
6950
|
+
observerTool: text("observer_tool").notNull(),
|
|
6951
|
+
argumentDigest: text("argument_digest").notNull(),
|
|
6952
|
+
destinationDigest: text("destination_digest").notNull(),
|
|
6953
|
+
authorityDigest: text("authority_digest").notNull(),
|
|
6954
|
+
originalOutcome: text("original_outcome").notNull().default("captured"),
|
|
6955
|
+
originalResult: jsonb("original_result"),
|
|
6956
|
+
originalResultCodecVersion: integer("original_result_codec_version"),
|
|
6957
|
+
observationResult: jsonb("observation_result"),
|
|
6958
|
+
observationResultCodecVersion: integer("observation_result_codec_version"),
|
|
6959
|
+
receiptRevision: text("receipt_revision"),
|
|
6960
|
+
receiptDigest: text("receipt_digest"),
|
|
6961
|
+
observationClaimId: uuid("observation_claim_id"),
|
|
6962
|
+
observationClaimAttemptId: uuid("observation_claim_attempt_id"),
|
|
6963
|
+
observationClaimExpiresAt: timestamp("observation_claim_expires_at", { withTimezone: true }),
|
|
6964
|
+
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
6965
|
+
observedAt: timestamp("observed_at", { withTimezone: true }),
|
|
6966
|
+
},
|
|
6967
|
+
(table) => ({
|
|
6968
|
+
source: index("mcp_operations_source_idx").on(
|
|
6969
|
+
table.workspaceId,
|
|
6970
|
+
table.sessionId,
|
|
6971
|
+
table.sourceTurnId,
|
|
6972
|
+
table.sourceCallId,
|
|
6973
|
+
),
|
|
6974
|
+
}),
|
|
6975
|
+
);
|
|
6976
|
+
|
|
6931
6977
|
export const sessionTurnAttempts = pgTable(
|
|
6932
6978
|
"session_turn_attempts",
|
|
6933
6979
|
{
|