@tangle-network/agent-interface 0.45.0 → 0.46.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/README.md +1 -1
- package/dist/agent-candidate-profile-schema.d.ts +2 -2
- package/dist/agent-candidate-promotion-schema.d.ts +22 -22
- package/dist/agent-candidate-schema-common.js +1 -1
- package/dist/agent-candidate-schema.d.ts +2 -2
- package/dist/agent-execution-preparation.d.ts +26 -26
- package/dist/agent-profile.d.ts +10 -3
- package/dist/agent-profile.js +45 -22
- package/dist/backend-message.d.ts +14 -0
- package/dist/backend-message.js +1 -0
- package/dist/contract-limits.d.ts +26 -0
- package/dist/contract-limits.js +175 -0
- package/dist/environment-exact-process.d.ts +161 -0
- package/dist/environment-exact-process.js +1 -0
- package/dist/environment-profile-capabilities.d.ts +26 -0
- package/dist/environment-profile-capabilities.js +34 -0
- package/dist/environment-provider.d.ts +3 -730
- package/dist/environment-provider.js +3 -245
- package/dist/environment-requests.d.ts +70 -0
- package/dist/environment-requests.js +1 -0
- package/dist/environment-runtime.d.ts +834 -0
- package/dist/environment-runtime.js +228 -0
- package/dist/execution-types.d.ts +47 -0
- package/dist/execution-types.js +1 -0
- package/dist/host-services.d.ts +91 -0
- package/dist/host-services.js +1 -0
- package/dist/index.d.ts +10 -617
- package/dist/index.js +10 -125
- package/dist/interaction-answer-validation.d.ts +13 -0
- package/dist/interaction-answer-validation.js +149 -0
- package/dist/interaction-data.d.ts +22 -0
- package/dist/interaction-data.js +46 -0
- package/dist/interaction-envelope.d.ts +258 -0
- package/dist/interaction-envelope.js +245 -0
- package/dist/interaction-fields.d.ts +130 -0
- package/dist/interaction-fields.js +227 -0
- package/dist/interaction-permissions.d.ts +28 -0
- package/dist/interaction-permissions.js +57 -0
- package/dist/interaction-resolution-validation.d.ts +9 -0
- package/dist/interaction-resolution-validation.js +50 -0
- package/dist/interaction-response-validation.d.ts +17 -0
- package/dist/interaction-response-validation.js +102 -0
- package/dist/interaction.d.ts +6 -397
- package/dist/interaction.js +6 -603
- package/dist/mcp.d.ts +38 -0
- package/dist/mcp.js +1 -0
- package/dist/parts.d.ts +104 -0
- package/dist/parts.js +55 -0
- package/dist/portable-context-base.d.ts +82 -0
- package/dist/portable-context-base.js +63 -0
- package/dist/portable-context-continuation.d.ts +168 -0
- package/dist/portable-context-continuation.js +194 -0
- package/dist/portable-context-plan-request.d.ts +86 -0
- package/dist/portable-context-plan-request.js +102 -0
- package/dist/portable-context-plan.d.ts +229 -0
- package/dist/portable-context-plan.js +241 -0
- package/dist/portable-context-shared.d.ts +36 -0
- package/dist/portable-context-shared.js +46 -0
- package/dist/portable-context-transfer.d.ts +319 -0
- package/dist/portable-context-transfer.js +206 -0
- package/dist/portable-context.d.ts +5 -753
- package/dist/portable-context.js +5 -754
- package/dist/profile-diff.js +56 -47
- package/dist/provider-adapter.d.ts +45 -0
- package/dist/provider-adapter.js +1 -0
- package/dist/provider-config.d.ts +58 -0
- package/dist/provider-config.js +42 -0
- package/dist/runtime-control.d.ts +87 -10
- package/dist/runtime-control.js +159 -38
- package/dist/stream-events.d.ts +55 -0
- package/dist/stream-events.js +1 -0
- package/dist/workspace-branching-shared.d.ts +7 -0
- package/dist/workspace-branching-shared.js +20 -0
- package/dist/workspace-branching.d.ts +4 -254
- package/dist/workspace-branching.js +4 -400
- package/dist/workspace-checkpoint.d.ts +99 -0
- package/dist/workspace-checkpoint.js +169 -0
- package/dist/workspace-cleanup.d.ts +85 -0
- package/dist/workspace-cleanup.js +156 -0
- package/dist/workspace-confidentiality.d.ts +59 -0
- package/dist/workspace-confidentiality.js +123 -0
- package/dist/workspace-fork.d.ts +182 -0
- package/dist/workspace-fork.js +267 -0
- package/package.json +1 -1
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { Sha256Digest } from "./agent-candidate.js";
|
|
3
|
+
import type { WorkspaceCheckpointRequest } from "./workspace-checkpoint.js";
|
|
4
|
+
import type { WorkspaceCheckpointLookupResult, WorkspaceCheckpointResult, WorkspaceOperationLookupRequest } from "./workspace-checkpoint.js";
|
|
5
|
+
import type { WorkspaceForkRequest } from "./workspace-fork.js";
|
|
6
|
+
import type { WorkspaceForkLookupResult, WorkspaceForkResult } from "./workspace-fork.js";
|
|
7
|
+
/**
|
|
8
|
+
* Checkpoints and forked environments are separate resources with separate
|
|
9
|
+
* destroy authority, so every cleanup names which kind it addresses and the
|
|
10
|
+
* acknowledgement must echo it. Without this, one identifier shape reaches
|
|
11
|
+
* both operations and a swapped target destroys the wrong resource.
|
|
12
|
+
*/
|
|
13
|
+
export declare const WorkspaceCleanupKindSchema: z.ZodEnum<{
|
|
14
|
+
checkpoint: "checkpoint";
|
|
15
|
+
fork: "fork";
|
|
16
|
+
}>;
|
|
17
|
+
export type WorkspaceCleanupKind = z.infer<typeof WorkspaceCleanupKindSchema>;
|
|
18
|
+
export interface WorkspaceCleanupMaterial {
|
|
19
|
+
kind: WorkspaceCleanupKind;
|
|
20
|
+
targetId: string;
|
|
21
|
+
provider: string;
|
|
22
|
+
}
|
|
23
|
+
/** Digest the exact resource addressed by a cleanup operation. */
|
|
24
|
+
export declare function workspaceCleanupRequestDigest(material: WorkspaceCleanupMaterial): Sha256Digest;
|
|
25
|
+
export declare const WorkspaceCleanupRequestSchema: z.ZodObject<{
|
|
26
|
+
operationId: z.ZodString;
|
|
27
|
+
kind: z.ZodEnum<{
|
|
28
|
+
checkpoint: "checkpoint";
|
|
29
|
+
fork: "fork";
|
|
30
|
+
}>;
|
|
31
|
+
targetId: z.ZodString;
|
|
32
|
+
provider: z.ZodString;
|
|
33
|
+
requestDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
34
|
+
}, z.core.$strict>;
|
|
35
|
+
export type WorkspaceCleanupRequest = z.infer<typeof WorkspaceCleanupRequestSchema>;
|
|
36
|
+
export declare const WorkspaceCleanupAcknowledgementSchema: z.ZodObject<{
|
|
37
|
+
operationId: z.ZodString;
|
|
38
|
+
kind: z.ZodEnum<{
|
|
39
|
+
checkpoint: "checkpoint";
|
|
40
|
+
fork: "fork";
|
|
41
|
+
}>;
|
|
42
|
+
targetId: z.ZodString;
|
|
43
|
+
provider: z.ZodString;
|
|
44
|
+
requestDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
45
|
+
status: z.ZodEnum<{
|
|
46
|
+
unknown: "unknown";
|
|
47
|
+
conflict: "conflict";
|
|
48
|
+
transport_failure: "transport_failure";
|
|
49
|
+
deleted: "deleted";
|
|
50
|
+
already_absent: "already_absent";
|
|
51
|
+
in_use: "in_use";
|
|
52
|
+
}>;
|
|
53
|
+
existingRequestDigest: z.ZodOptional<z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>>;
|
|
54
|
+
message: z.ZodOptional<z.ZodString>;
|
|
55
|
+
retryable: z.ZodOptional<z.ZodBoolean>;
|
|
56
|
+
blockingTargetIds: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
57
|
+
}, z.core.$strict>;
|
|
58
|
+
export type WorkspaceCleanupAcknowledgement = z.infer<typeof WorkspaceCleanupAcknowledgementSchema>;
|
|
59
|
+
/** Optional durable workspace branch operations implemented by capable providers. */
|
|
60
|
+
export interface AgentWorkspaceBranching {
|
|
61
|
+
checkpoint(request: WorkspaceCheckpointRequest, options?: {
|
|
62
|
+
signal?: AbortSignal;
|
|
63
|
+
}): Promise<WorkspaceCheckpointResult>;
|
|
64
|
+
lookupCheckpoint(request: WorkspaceOperationLookupRequest, options?: {
|
|
65
|
+
signal?: AbortSignal;
|
|
66
|
+
}): Promise<WorkspaceCheckpointLookupResult>;
|
|
67
|
+
deleteCheckpoint(request: WorkspaceCleanupRequest & {
|
|
68
|
+
kind: "checkpoint";
|
|
69
|
+
}, options?: {
|
|
70
|
+
signal?: AbortSignal;
|
|
71
|
+
}): Promise<WorkspaceCleanupAcknowledgement>;
|
|
72
|
+
fork(request: WorkspaceForkRequest, options?: {
|
|
73
|
+
signal?: AbortSignal;
|
|
74
|
+
}): Promise<WorkspaceForkResult>;
|
|
75
|
+
lookupFork(request: WorkspaceOperationLookupRequest, options?: {
|
|
76
|
+
signal?: AbortSignal;
|
|
77
|
+
}): Promise<WorkspaceForkLookupResult>;
|
|
78
|
+
destroyFork(request: WorkspaceCleanupRequest & {
|
|
79
|
+
kind: "fork";
|
|
80
|
+
}, options?: {
|
|
81
|
+
signal?: AbortSignal;
|
|
82
|
+
}): Promise<WorkspaceCleanupAcknowledgement>;
|
|
83
|
+
}
|
|
84
|
+
/** Bind cleanup confirmation to the exact provider resource and operation. */
|
|
85
|
+
export declare function workspaceCleanupAcknowledgementMatches(request: WorkspaceCleanupRequest, acknowledgement: WorkspaceCleanupAcknowledgement): boolean;
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { canonicalCandidateDigest } from "./agent-candidate-schema-common.js";
|
|
3
|
+
import { idSchema, sha256DigestSchema } from "./workspace-branching-shared.js";
|
|
4
|
+
import { boundedStringSchema, CONTRACT_MAX_ARRAY_LENGTH } from "./contract-limits.js";
|
|
5
|
+
/**
|
|
6
|
+
* Checkpoints and forked environments are separate resources with separate
|
|
7
|
+
* destroy authority, so every cleanup names which kind it addresses and the
|
|
8
|
+
* acknowledgement must echo it. Without this, one identifier shape reaches
|
|
9
|
+
* both operations and a swapped target destroys the wrong resource.
|
|
10
|
+
*/
|
|
11
|
+
export const WorkspaceCleanupKindSchema = z.enum(["checkpoint", "fork"]);
|
|
12
|
+
const WorkspaceCleanupMaterialSchema = z.strictObject({
|
|
13
|
+
kind: WorkspaceCleanupKindSchema,
|
|
14
|
+
targetId: idSchema,
|
|
15
|
+
provider: idSchema,
|
|
16
|
+
});
|
|
17
|
+
/** Digest the exact resource addressed by a cleanup operation. */
|
|
18
|
+
export function workspaceCleanupRequestDigest(material) {
|
|
19
|
+
return canonicalCandidateDigest(WorkspaceCleanupMaterialSchema.parse(material));
|
|
20
|
+
}
|
|
21
|
+
export const WorkspaceCleanupRequestSchema = z.strictObject({
|
|
22
|
+
operationId: idSchema,
|
|
23
|
+
kind: WorkspaceCleanupKindSchema,
|
|
24
|
+
targetId: idSchema,
|
|
25
|
+
provider: idSchema,
|
|
26
|
+
requestDigest: sha256DigestSchema,
|
|
27
|
+
}).superRefine((request, refinement) => {
|
|
28
|
+
if (request.requestDigest !==
|
|
29
|
+
workspaceCleanupRequestDigest({
|
|
30
|
+
kind: request.kind,
|
|
31
|
+
targetId: request.targetId,
|
|
32
|
+
provider: request.provider,
|
|
33
|
+
})) {
|
|
34
|
+
refinement.addIssue({
|
|
35
|
+
code: "custom",
|
|
36
|
+
path: ["requestDigest"],
|
|
37
|
+
message: "cleanup request digest does not match its target",
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
export const WorkspaceCleanupAcknowledgementSchema = z
|
|
42
|
+
.strictObject({
|
|
43
|
+
operationId: idSchema,
|
|
44
|
+
kind: WorkspaceCleanupKindSchema,
|
|
45
|
+
targetId: idSchema,
|
|
46
|
+
provider: idSchema,
|
|
47
|
+
requestDigest: sha256DigestSchema,
|
|
48
|
+
status: z.enum([
|
|
49
|
+
"deleted",
|
|
50
|
+
"already_absent",
|
|
51
|
+
"unknown",
|
|
52
|
+
"in_use",
|
|
53
|
+
"conflict",
|
|
54
|
+
"transport_failure",
|
|
55
|
+
]),
|
|
56
|
+
existingRequestDigest: sha256DigestSchema.optional(),
|
|
57
|
+
message: boundedStringSchema.min(1).optional(),
|
|
58
|
+
retryable: z.boolean().optional(),
|
|
59
|
+
/** Existing resources that must be removed before this target. */
|
|
60
|
+
blockingTargetIds: z.array(idSchema).min(1).max(CONTRACT_MAX_ARRAY_LENGTH).optional(),
|
|
61
|
+
})
|
|
62
|
+
.superRefine((acknowledgement, refinement) => {
|
|
63
|
+
if (["unknown", "in_use", "conflict", "transport_failure"].includes(acknowledgement.status) &&
|
|
64
|
+
acknowledgement.message === undefined) {
|
|
65
|
+
refinement.addIssue({
|
|
66
|
+
code: "custom",
|
|
67
|
+
path: ["message"],
|
|
68
|
+
message: `${acknowledgement.status} cleanup must include a message`,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
if (acknowledgement.status === "in_use" &&
|
|
72
|
+
acknowledgement.blockingTargetIds === undefined) {
|
|
73
|
+
refinement.addIssue({
|
|
74
|
+
code: "custom",
|
|
75
|
+
path: ["blockingTargetIds"],
|
|
76
|
+
message: "in_use cleanup must identify every known blocking target",
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
if (acknowledgement.status !== "in_use" &&
|
|
80
|
+
acknowledgement.blockingTargetIds !== undefined) {
|
|
81
|
+
refinement.addIssue({
|
|
82
|
+
code: "custom",
|
|
83
|
+
path: ["blockingTargetIds"],
|
|
84
|
+
message: "only in_use cleanup may identify blocking targets",
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
if (acknowledgement.blockingTargetIds &&
|
|
88
|
+
new Set(acknowledgement.blockingTargetIds).size !==
|
|
89
|
+
acknowledgement.blockingTargetIds.length) {
|
|
90
|
+
refinement.addIssue({
|
|
91
|
+
code: "custom",
|
|
92
|
+
path: ["blockingTargetIds"],
|
|
93
|
+
message: "blocking cleanup target ids must be unique",
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
if (["unknown", "transport_failure"].includes(acknowledgement.status) &&
|
|
97
|
+
acknowledgement.retryable === undefined) {
|
|
98
|
+
refinement.addIssue({
|
|
99
|
+
code: "custom",
|
|
100
|
+
path: ["retryable"],
|
|
101
|
+
message: `${acknowledgement.status} cleanup must state whether retry is safe`,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
if (acknowledgement.status === "conflict" &&
|
|
105
|
+
acknowledgement.existingRequestDigest === undefined) {
|
|
106
|
+
refinement.addIssue({
|
|
107
|
+
code: "custom",
|
|
108
|
+
path: ["existingRequestDigest"],
|
|
109
|
+
message: "a cleanup conflict must include the existing digest",
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
if (acknowledgement.status === "conflict" &&
|
|
113
|
+
acknowledgement.existingRequestDigest === acknowledgement.requestDigest) {
|
|
114
|
+
refinement.addIssue({
|
|
115
|
+
code: "custom",
|
|
116
|
+
path: ["existingRequestDigest"],
|
|
117
|
+
message: "a cleanup conflict must identify a different request",
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
if (acknowledgement.status !== "conflict" &&
|
|
121
|
+
acknowledgement.existingRequestDigest !== undefined) {
|
|
122
|
+
refinement.addIssue({
|
|
123
|
+
code: "custom",
|
|
124
|
+
path: ["existingRequestDigest"],
|
|
125
|
+
message: "only a cleanup conflict may include an existing digest",
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
if (acknowledgement.requestDigest !==
|
|
129
|
+
workspaceCleanupRequestDigest({
|
|
130
|
+
kind: acknowledgement.kind,
|
|
131
|
+
targetId: acknowledgement.targetId,
|
|
132
|
+
provider: acknowledgement.provider,
|
|
133
|
+
})) {
|
|
134
|
+
refinement.addIssue({
|
|
135
|
+
code: "custom",
|
|
136
|
+
path: ["requestDigest"],
|
|
137
|
+
message: "cleanup acknowledgement digest does not match its target",
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
/** Bind cleanup confirmation to the exact provider resource and operation. */
|
|
142
|
+
export function workspaceCleanupAcknowledgementMatches(request, acknowledgement) {
|
|
143
|
+
const parsedRequest = WorkspaceCleanupRequestSchema.safeParse(request);
|
|
144
|
+
const parsedAcknowledgement = WorkspaceCleanupAcknowledgementSchema.safeParse(acknowledgement);
|
|
145
|
+
if (!parsedRequest.success || !parsedAcknowledgement.success)
|
|
146
|
+
return false;
|
|
147
|
+
const exactRequest = parsedRequest.data;
|
|
148
|
+
const exactAcknowledgement = parsedAcknowledgement.data;
|
|
149
|
+
return ((exactAcknowledgement.status === "deleted" ||
|
|
150
|
+
exactAcknowledgement.status === "already_absent") &&
|
|
151
|
+
exactAcknowledgement.operationId === exactRequest.operationId &&
|
|
152
|
+
exactAcknowledgement.kind === exactRequest.kind &&
|
|
153
|
+
exactAcknowledgement.targetId === exactRequest.targetId &&
|
|
154
|
+
exactAcknowledgement.provider === exactRequest.provider &&
|
|
155
|
+
exactAcknowledgement.requestDigest === exactRequest.requestDigest);
|
|
156
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { Sha256Digest } from "./agent-candidate.js";
|
|
3
|
+
import { type AgentExactRunControlRef } from "./runtime-control.js";
|
|
4
|
+
/**
|
|
5
|
+
* Evidence for a confidential environment. The signature is retained for an
|
|
6
|
+
* external provider-key check; this package never treats a self-echoed quote
|
|
7
|
+
* as authenticated on its own.
|
|
8
|
+
*/
|
|
9
|
+
export declare const ConfidentialAttestationSchema: z.ZodObject<{
|
|
10
|
+
provider: z.ZodString;
|
|
11
|
+
requested: z.ZodLiteral<true>;
|
|
12
|
+
nonce: z.ZodString;
|
|
13
|
+
measurement: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
14
|
+
environmentId: z.ZodString;
|
|
15
|
+
source: z.ZodObject<{
|
|
16
|
+
runId: z.ZodString;
|
|
17
|
+
provider: z.ZodString;
|
|
18
|
+
environmentId: z.ZodString;
|
|
19
|
+
sessionId: z.ZodString;
|
|
20
|
+
executionId: z.ZodString;
|
|
21
|
+
requestDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
22
|
+
}, z.core.$strict>;
|
|
23
|
+
requestDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
24
|
+
profileDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
25
|
+
policy: z.ZodString;
|
|
26
|
+
quote: z.ZodString;
|
|
27
|
+
providerKeyId: z.ZodString;
|
|
28
|
+
providerSignature: z.ZodString;
|
|
29
|
+
verifiedAt: z.ZodISODateTime;
|
|
30
|
+
}, z.core.$strict>;
|
|
31
|
+
export type ConfidentialAttestation = z.infer<typeof ConfidentialAttestationSchema>;
|
|
32
|
+
/** What the caller asked for, separate from what the provider proved. */
|
|
33
|
+
export declare const ConfidentialExecutionRequestSchema: z.ZodObject<{
|
|
34
|
+
requested: z.ZodBoolean;
|
|
35
|
+
nonce: z.ZodOptional<z.ZodString>;
|
|
36
|
+
policy: z.ZodOptional<z.ZodString>;
|
|
37
|
+
profileDigest: z.ZodOptional<z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>>;
|
|
38
|
+
}, z.core.$strict>;
|
|
39
|
+
export type ConfidentialExecutionRequest = z.infer<typeof ConfidentialExecutionRequestSchema>;
|
|
40
|
+
export interface ConfidentialExecutionEnvironment {
|
|
41
|
+
provider: string;
|
|
42
|
+
environmentId: string;
|
|
43
|
+
source: AgentExactRunControlRef;
|
|
44
|
+
requestDigest: Sha256Digest;
|
|
45
|
+
confidentialRequested: boolean;
|
|
46
|
+
}
|
|
47
|
+
export type ConfidentialAttestationVerifier = (attestation: ConfidentialAttestation, expected: ConfidentialExecutionEnvironment) => boolean;
|
|
48
|
+
/**
|
|
49
|
+
* Verify every request/result binding and require an external provider-key
|
|
50
|
+
* check before exposing a positive confidentiality result.
|
|
51
|
+
*/
|
|
52
|
+
export declare function confidentialExecutionVerified(input: {
|
|
53
|
+
request: ConfidentialExecutionRequest;
|
|
54
|
+
environment: ConfidentialExecutionEnvironment;
|
|
55
|
+
attestation?: ConfidentialAttestation;
|
|
56
|
+
verifyProviderAttestation?: ConfidentialAttestationVerifier;
|
|
57
|
+
}): boolean;
|
|
58
|
+
/** Digest over the complete confidentiality request. */
|
|
59
|
+
export declare function confidentialExecutionRequestDigest(request: ConfidentialExecutionRequest): Sha256Digest;
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { boundedStringSchema } from "./contract-limits.js";
|
|
3
|
+
import { AgentExactRunControlRefSchema, } from "./runtime-control.js";
|
|
4
|
+
import { idSchema, sha256DigestSchema, wireDigest } from "./workspace-branching-shared.js";
|
|
5
|
+
/**
|
|
6
|
+
* Evidence for a confidential environment. The signature is retained for an
|
|
7
|
+
* external provider-key check; this package never treats a self-echoed quote
|
|
8
|
+
* as authenticated on its own.
|
|
9
|
+
*/
|
|
10
|
+
export const ConfidentialAttestationSchema = z
|
|
11
|
+
.strictObject({
|
|
12
|
+
provider: idSchema,
|
|
13
|
+
requested: z.literal(true),
|
|
14
|
+
nonce: idSchema,
|
|
15
|
+
measurement: sha256DigestSchema,
|
|
16
|
+
environmentId: idSchema,
|
|
17
|
+
source: AgentExactRunControlRefSchema,
|
|
18
|
+
requestDigest: sha256DigestSchema,
|
|
19
|
+
profileDigest: sha256DigestSchema,
|
|
20
|
+
policy: idSchema,
|
|
21
|
+
quote: boundedStringSchema.min(1),
|
|
22
|
+
providerKeyId: idSchema,
|
|
23
|
+
providerSignature: boundedStringSchema.min(1),
|
|
24
|
+
verifiedAt: z.iso.datetime().max(64),
|
|
25
|
+
})
|
|
26
|
+
.superRefine((attestation, refinement) => {
|
|
27
|
+
if (attestation.nonce === attestation.policy) {
|
|
28
|
+
refinement.addIssue({
|
|
29
|
+
code: "custom",
|
|
30
|
+
path: ["nonce"],
|
|
31
|
+
message: "attestation nonce must not reuse the policy identifier",
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
if (attestation.providerSignature === attestation.quote) {
|
|
35
|
+
refinement.addIssue({
|
|
36
|
+
code: "custom",
|
|
37
|
+
path: ["providerSignature"],
|
|
38
|
+
message: "provider authentication must not be a copied quote",
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
/** What the caller asked for, separate from what the provider proved. */
|
|
43
|
+
export const ConfidentialExecutionRequestSchema = z
|
|
44
|
+
.strictObject({
|
|
45
|
+
requested: z.boolean(),
|
|
46
|
+
nonce: idSchema.optional(),
|
|
47
|
+
policy: idSchema.optional(),
|
|
48
|
+
profileDigest: sha256DigestSchema.optional(),
|
|
49
|
+
})
|
|
50
|
+
.superRefine((request, refinement) => {
|
|
51
|
+
const complete = request.nonce !== undefined &&
|
|
52
|
+
request.policy !== undefined &&
|
|
53
|
+
request.profileDigest !== undefined;
|
|
54
|
+
if (request.requested && !complete) {
|
|
55
|
+
refinement.addIssue({
|
|
56
|
+
code: "custom",
|
|
57
|
+
path: ["requested"],
|
|
58
|
+
message: "a confidential execution request must bind nonce, policy, and profile digest",
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
if (!request.requested && complete) {
|
|
62
|
+
refinement.addIssue({
|
|
63
|
+
code: "custom",
|
|
64
|
+
path: ["requested"],
|
|
65
|
+
message: "a non-confidential execution request cannot carry confidential admission fields",
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
/**
|
|
70
|
+
* Verify every request/result binding and require an external provider-key
|
|
71
|
+
* check before exposing a positive confidentiality result.
|
|
72
|
+
*/
|
|
73
|
+
export function confidentialExecutionVerified(input) {
|
|
74
|
+
const parsedRequest = ConfidentialExecutionRequestSchema.safeParse(input.request);
|
|
75
|
+
if (!parsedRequest.success || !parsedRequest.data.requested)
|
|
76
|
+
return false;
|
|
77
|
+
if (input.attestation === undefined || input.verifyProviderAttestation === undefined) {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
const parsedEnvironment = z
|
|
81
|
+
.strictObject({
|
|
82
|
+
provider: idSchema,
|
|
83
|
+
environmentId: idSchema,
|
|
84
|
+
source: AgentExactRunControlRefSchema,
|
|
85
|
+
requestDigest: sha256DigestSchema,
|
|
86
|
+
confidentialRequested: z.literal(true),
|
|
87
|
+
})
|
|
88
|
+
.safeParse(input.environment);
|
|
89
|
+
const parsedAttestation = ConfidentialAttestationSchema.safeParse(input.attestation);
|
|
90
|
+
if (!parsedEnvironment.success || !parsedAttestation.success)
|
|
91
|
+
return false;
|
|
92
|
+
const request = parsedRequest.data;
|
|
93
|
+
const environment = parsedEnvironment.data;
|
|
94
|
+
const attestation = parsedAttestation.data;
|
|
95
|
+
if (request.nonce === undefined ||
|
|
96
|
+
request.policy === undefined ||
|
|
97
|
+
request.profileDigest === undefined ||
|
|
98
|
+
attestation.requested !== request.requested ||
|
|
99
|
+
attestation.provider !== environment.provider ||
|
|
100
|
+
attestation.environmentId !== environment.environmentId ||
|
|
101
|
+
attestation.source.provider !== environment.source.provider ||
|
|
102
|
+
wireDigest(attestation.source) !== wireDigest(environment.source) ||
|
|
103
|
+
attestation.requestDigest !== environment.requestDigest ||
|
|
104
|
+
attestation.nonce !== request.nonce ||
|
|
105
|
+
attestation.policy !== request.policy ||
|
|
106
|
+
attestation.profileDigest !== request.profileDigest ||
|
|
107
|
+
environment.confidentialRequested !== request.requested) {
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
return input.verifyProviderAttestation(attestation, environment) === true;
|
|
111
|
+
}
|
|
112
|
+
/** Digest over the complete confidentiality request. */
|
|
113
|
+
export function confidentialExecutionRequestDigest(request) {
|
|
114
|
+
const parsed = ConfidentialExecutionRequestSchema.parse(request);
|
|
115
|
+
return wireDigest({
|
|
116
|
+
requested: parsed.requested,
|
|
117
|
+
...(parsed.nonce === undefined ? {} : { nonce: parsed.nonce }),
|
|
118
|
+
...(parsed.policy === undefined ? {} : { policy: parsed.policy }),
|
|
119
|
+
...(parsed.profileDigest === undefined
|
|
120
|
+
? {}
|
|
121
|
+
: { profileDigest: parsed.profileDigest }),
|
|
122
|
+
});
|
|
123
|
+
}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { Sha256Digest } from "./agent-candidate.js";
|
|
3
|
+
import type { PlacementInfo } from "./environment-requests.js";
|
|
4
|
+
import { type AgentExactRunControlRef } from "./runtime-control.js";
|
|
5
|
+
import { type WorkspaceCheckpointRef } from "./workspace-checkpoint.js";
|
|
6
|
+
import { type ConfidentialAttestationVerifier, type ConfidentialAttestation, type ConfidentialExecutionRequest } from "./workspace-confidentiality.js";
|
|
7
|
+
export interface WorkspaceForkMaterial {
|
|
8
|
+
checkpoint: WorkspaceCheckpointRef;
|
|
9
|
+
name?: string;
|
|
10
|
+
metadata?: Record<string, unknown>;
|
|
11
|
+
/** Requested placement is part of the operation identity. */
|
|
12
|
+
placement: PlacementInfo;
|
|
13
|
+
/** What the caller asked for; never what the provider proved. */
|
|
14
|
+
confidential?: ConfidentialExecutionRequest;
|
|
15
|
+
}
|
|
16
|
+
export interface WorkspaceForkRequest extends WorkspaceForkMaterial {
|
|
17
|
+
idempotencyKey: string;
|
|
18
|
+
requestDigest: Sha256Digest;
|
|
19
|
+
}
|
|
20
|
+
export declare function workspaceForkRequestDigest(material: WorkspaceForkMaterial): Sha256Digest;
|
|
21
|
+
export declare const WorkspaceForkRequestSchema: z.ZodObject<{
|
|
22
|
+
checkpoint: z.ZodObject<{
|
|
23
|
+
checkpointId: z.ZodString;
|
|
24
|
+
provider: z.ZodString;
|
|
25
|
+
source: z.ZodObject<{
|
|
26
|
+
runId: z.ZodString;
|
|
27
|
+
provider: z.ZodString;
|
|
28
|
+
environmentId: z.ZodString;
|
|
29
|
+
sessionId: z.ZodString;
|
|
30
|
+
executionId: z.ZodString;
|
|
31
|
+
requestDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
32
|
+
}, z.core.$strict>;
|
|
33
|
+
idempotencyKey: z.ZodString;
|
|
34
|
+
requestDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
35
|
+
createdAt: z.ZodISODateTime;
|
|
36
|
+
metadata: z.ZodOptional<z.ZodCustom<Record<string, unknown>, Record<string, unknown>>>;
|
|
37
|
+
}, z.core.$strict>;
|
|
38
|
+
name: z.ZodOptional<z.ZodString>;
|
|
39
|
+
metadata: z.ZodOptional<z.ZodCustom<Record<string, unknown>, Record<string, unknown>>>;
|
|
40
|
+
placement: z.ZodObject<{
|
|
41
|
+
kind: z.ZodEnum<{
|
|
42
|
+
provider: "provider";
|
|
43
|
+
local: "local";
|
|
44
|
+
sandbox: "sandbox";
|
|
45
|
+
fleet: "fleet";
|
|
46
|
+
}>;
|
|
47
|
+
sandboxId: z.ZodOptional<z.ZodString>;
|
|
48
|
+
fleetId: z.ZodOptional<z.ZodString>;
|
|
49
|
+
machineId: z.ZodOptional<z.ZodString>;
|
|
50
|
+
region: z.ZodOptional<z.ZodString>;
|
|
51
|
+
providerMetadata: z.ZodOptional<z.ZodCustom<Record<string, unknown>, Record<string, unknown>>>;
|
|
52
|
+
}, z.core.$strict>;
|
|
53
|
+
confidential: z.ZodOptional<z.ZodObject<{
|
|
54
|
+
requested: z.ZodBoolean;
|
|
55
|
+
nonce: z.ZodOptional<z.ZodString>;
|
|
56
|
+
policy: z.ZodOptional<z.ZodString>;
|
|
57
|
+
profileDigest: z.ZodOptional<z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>>;
|
|
58
|
+
}, z.core.$strict>>;
|
|
59
|
+
idempotencyKey: z.ZodString;
|
|
60
|
+
requestDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
61
|
+
}, z.core.$strict>;
|
|
62
|
+
export interface ForkedEnvironmentRef {
|
|
63
|
+
provider: string;
|
|
64
|
+
environmentId: string;
|
|
65
|
+
/** Environment the checkpoint was taken from; a fork must never reuse it. */
|
|
66
|
+
sourceEnvironmentId: string;
|
|
67
|
+
/** Full source run identity; an environment id alone is not sufficient. */
|
|
68
|
+
source: AgentExactRunControlRef;
|
|
69
|
+
sourceCheckpointId: string;
|
|
70
|
+
idempotencyKey: string;
|
|
71
|
+
requestDigest: Sha256Digest;
|
|
72
|
+
createdAt: string;
|
|
73
|
+
placement: PlacementInfo;
|
|
74
|
+
/**
|
|
75
|
+
* What the caller asked for. This is never proof: read it with
|
|
76
|
+
* {@link forkedEnvironmentConfidentialityVerified}, never on its own.
|
|
77
|
+
*/
|
|
78
|
+
confidentialRequested: boolean;
|
|
79
|
+
/** Present only when the provider produced verifiable attestation evidence. */
|
|
80
|
+
confidentialAttestation?: ConfidentialAttestation;
|
|
81
|
+
/** Legacy assertion retained for wire compatibility; never trusted as proof. */
|
|
82
|
+
confidential?: boolean;
|
|
83
|
+
metadata?: Record<string, unknown>;
|
|
84
|
+
}
|
|
85
|
+
export declare const ForkedEnvironmentRefSchema: z.ZodObject<{
|
|
86
|
+
provider: z.ZodString;
|
|
87
|
+
environmentId: z.ZodString;
|
|
88
|
+
sourceEnvironmentId: z.ZodString;
|
|
89
|
+
source: z.ZodObject<{
|
|
90
|
+
runId: z.ZodString;
|
|
91
|
+
provider: z.ZodString;
|
|
92
|
+
environmentId: z.ZodString;
|
|
93
|
+
sessionId: z.ZodString;
|
|
94
|
+
executionId: z.ZodString;
|
|
95
|
+
requestDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
96
|
+
}, z.core.$strict>;
|
|
97
|
+
sourceCheckpointId: z.ZodString;
|
|
98
|
+
idempotencyKey: z.ZodString;
|
|
99
|
+
requestDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
100
|
+
createdAt: z.ZodISODateTime;
|
|
101
|
+
placement: z.ZodObject<{
|
|
102
|
+
kind: z.ZodEnum<{
|
|
103
|
+
provider: "provider";
|
|
104
|
+
local: "local";
|
|
105
|
+
sandbox: "sandbox";
|
|
106
|
+
fleet: "fleet";
|
|
107
|
+
}>;
|
|
108
|
+
sandboxId: z.ZodOptional<z.ZodString>;
|
|
109
|
+
fleetId: z.ZodOptional<z.ZodString>;
|
|
110
|
+
machineId: z.ZodOptional<z.ZodString>;
|
|
111
|
+
region: z.ZodOptional<z.ZodString>;
|
|
112
|
+
providerMetadata: z.ZodOptional<z.ZodCustom<Record<string, unknown>, Record<string, unknown>>>;
|
|
113
|
+
}, z.core.$strict>;
|
|
114
|
+
confidentialRequested: z.ZodBoolean;
|
|
115
|
+
confidentialAttestation: z.ZodOptional<z.ZodObject<{
|
|
116
|
+
provider: z.ZodString;
|
|
117
|
+
requested: z.ZodLiteral<true>;
|
|
118
|
+
nonce: z.ZodString;
|
|
119
|
+
measurement: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
120
|
+
environmentId: z.ZodString;
|
|
121
|
+
source: z.ZodObject<{
|
|
122
|
+
runId: z.ZodString;
|
|
123
|
+
provider: z.ZodString;
|
|
124
|
+
environmentId: z.ZodString;
|
|
125
|
+
sessionId: z.ZodString;
|
|
126
|
+
executionId: z.ZodString;
|
|
127
|
+
requestDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
128
|
+
}, z.core.$strict>;
|
|
129
|
+
requestDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
130
|
+
profileDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
131
|
+
policy: z.ZodString;
|
|
132
|
+
quote: z.ZodString;
|
|
133
|
+
providerKeyId: z.ZodString;
|
|
134
|
+
providerSignature: z.ZodString;
|
|
135
|
+
verifiedAt: z.ZodISODateTime;
|
|
136
|
+
}, z.core.$strict>>;
|
|
137
|
+
confidential: z.ZodOptional<z.ZodBoolean>;
|
|
138
|
+
metadata: z.ZodOptional<z.ZodCustom<Record<string, unknown>, Record<string, unknown>>>;
|
|
139
|
+
}, z.core.$strict>;
|
|
140
|
+
/** The only supported way to decide whether a fork may be shown confidential. */
|
|
141
|
+
export declare function forkedEnvironmentConfidentialityVerified(request: WorkspaceForkRequest, environment: ForkedEnvironmentRef, verifyProviderAttestation?: ConfidentialAttestationVerifier): boolean;
|
|
142
|
+
export type WorkspaceForkResult = {
|
|
143
|
+
status: "created" | "replayed";
|
|
144
|
+
idempotencyKey: string;
|
|
145
|
+
requestDigest: Sha256Digest;
|
|
146
|
+
environment: ForkedEnvironmentRef;
|
|
147
|
+
} | {
|
|
148
|
+
status: "conflict";
|
|
149
|
+
idempotencyKey: string;
|
|
150
|
+
requestDigest: Sha256Digest;
|
|
151
|
+
existingRequestDigest: Sha256Digest;
|
|
152
|
+
} | {
|
|
153
|
+
status: "unknown";
|
|
154
|
+
idempotencyKey: string;
|
|
155
|
+
requestDigest: Sha256Digest;
|
|
156
|
+
message: string;
|
|
157
|
+
retryable: boolean;
|
|
158
|
+
};
|
|
159
|
+
export declare const WorkspaceForkResultSchema: z.ZodType<WorkspaceForkResult>;
|
|
160
|
+
export type WorkspaceForkLookupResult = {
|
|
161
|
+
status: "found";
|
|
162
|
+
idempotencyKey: string;
|
|
163
|
+
requestDigest: Sha256Digest;
|
|
164
|
+
environment: ForkedEnvironmentRef;
|
|
165
|
+
} | {
|
|
166
|
+
status: "not_found";
|
|
167
|
+
idempotencyKey: string;
|
|
168
|
+
requestDigest: Sha256Digest;
|
|
169
|
+
} | {
|
|
170
|
+
status: "conflict";
|
|
171
|
+
idempotencyKey: string;
|
|
172
|
+
requestDigest: Sha256Digest;
|
|
173
|
+
existingRequestDigest: Sha256Digest;
|
|
174
|
+
} | {
|
|
175
|
+
status: "unknown";
|
|
176
|
+
idempotencyKey: string;
|
|
177
|
+
requestDigest: Sha256Digest;
|
|
178
|
+
message: string;
|
|
179
|
+
retryable: boolean;
|
|
180
|
+
};
|
|
181
|
+
export declare const WorkspaceForkLookupResultSchema: z.ZodType<WorkspaceForkLookupResult>;
|
|
182
|
+
export declare function workspaceForkResultMatchesRequest(request: WorkspaceForkRequest, result: WorkspaceForkResult | WorkspaceForkLookupResult): boolean;
|