@treeseed/sdk 0.13.0-rc.55 → 0.13.0-rc.56
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/agent-capacity/contracts/capacity/providers/supply-policy.d.ts +0 -2
- package/dist/agent-capacity/validation/activity-profile.js +18 -9
- package/dist/agent-capacity/validation/agent-definition-schema.d.ts +540 -618
- package/dist/agent-capacity/validation/agent-definition-schema.js +8 -28
- package/dist/agent-capacity/validation/agent-lab-forensics-schema.d.ts +11 -11
- package/dist/capacity-provider/capability-ontology.d.ts +1211 -0
- package/dist/capacity-provider/capability-ontology.js +200 -0
- package/dist/capacity-provider/contracts/governance.d.ts +37 -2
- package/dist/capacity-provider/core-capability-catalog.d.ts +47 -0
- package/dist/capacity-provider/core-capability-catalog.js +63 -0
- package/dist/capacity-provider/environment-catalog.d.ts +877 -0
- package/dist/capacity-provider/environment-catalog.js +116 -0
- package/dist/capacity-provider/index.d.ts +3 -0
- package/dist/capacity-provider/index.js +3 -0
- package/dist/capacity-provider/sandbox-contracts.d.ts +147 -26
- package/dist/capacity-provider/sandbox-contracts.js +16 -1
- package/dist/capacity-provider/validation.d.ts +2 -1
- package/dist/capacity-provider/validation.js +34 -1
- package/dist/content/validation/content-model-schemas.d.ts +985 -1128
- package/dist/content/validation/portable-content-data.d.ts +90 -103
- package/dist/deployment/schemas.d.ts +17 -17
- package/dist/deployment/schemas.js +1 -1
- package/dist/operator-contracts/canonical-command-tree.js +6 -0
- package/dist/operator-contracts/catalog/capability-ontology-operations.d.ts +164 -0
- package/dist/operator-contracts/catalog/capability-ontology-operations.js +24 -0
- package/dist/operator-contracts/catalog/control-plane-catalog.d.ts +6 -0
- package/dist/operator-contracts/catalog/control-plane-catalog.js +18 -0
- package/dist/operator-contracts/control-plane-operations.d.ts +510 -342
- package/dist/operator-contracts/control-plane-operations.js +7 -10
- package/dist/operator-contracts/index.d.ts +1 -0
- package/dist/operator-contracts/index.js +1 -0
- package/dist/types/agents/agent-activity-profile.d.ts +15 -33
- package/package.json +1 -1
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { createHash, createPublicKey, verify } from "node:crypto";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
const identifier = z.string().regex(/^[a-z][a-z0-9._-]{0,127}$/u);
|
|
4
|
+
const digest = z.string().regex(/^sha256:[a-f0-9]{64}$/u);
|
|
5
|
+
const version = z.string().regex(/^\d+\.\d+\.\d+$/u);
|
|
6
|
+
const sandboxEnvironmentContractSchema = z.object({
|
|
7
|
+
id: identifier,
|
|
8
|
+
version,
|
|
9
|
+
digest,
|
|
10
|
+
capabilities: z.array(identifier)
|
|
11
|
+
}).strict();
|
|
12
|
+
const provenance = z.object({
|
|
13
|
+
sourceRepository: z.string().url(),
|
|
14
|
+
sourceRevision: z.union([z.string().regex(/^[a-f0-9]{40}$/u), digest]),
|
|
15
|
+
buildRecipeDigest: digest,
|
|
16
|
+
sbomDigest: digest,
|
|
17
|
+
signature: z.object({ keyId: identifier, algorithm: z.enum(["Ed25519", "cosign"]), value: z.string().min(1) }).strict()
|
|
18
|
+
}).strict();
|
|
19
|
+
const sandboxEnvironmentCatalogEntrySchema = z.object({
|
|
20
|
+
id: identifier,
|
|
21
|
+
version,
|
|
22
|
+
kind: z.enum(["base", "extension"]),
|
|
23
|
+
contract: sandboxEnvironmentContractSchema,
|
|
24
|
+
image: z.object({ reference: z.string().min(1), digest, architectures: z.array(z.enum(["amd64", "arm64"])).min(1), operatingSystem: z.literal("linux") }).strict(),
|
|
25
|
+
derivedFrom: z.array(z.object({ entryId: identifier, version, imageDigest: digest }).strict()).min(1).nullable(),
|
|
26
|
+
provenance,
|
|
27
|
+
qualification: z.object({ suiteId: identifier, suiteVersion: version, evidenceDigest: digest, status: z.literal("passed"), completedAt: z.string().datetime() }).strict(),
|
|
28
|
+
status: z.enum(["active", "deprecated", "revoked"]),
|
|
29
|
+
createdAt: z.string().datetime()
|
|
30
|
+
}).strict().superRefine((entry, context) => {
|
|
31
|
+
if (new Set(entry.image.architectures).size !== entry.image.architectures.length) context.addIssue({ code: z.ZodIssueCode.custom, path: ["image", "architectures"], message: "Image architectures must be unique." });
|
|
32
|
+
if (entry.kind === "base" && entry.derivedFrom !== null) context.addIssue({ code: z.ZodIssueCode.custom, path: ["derivedFrom"], message: "Base environments cannot derive from another catalog entry." });
|
|
33
|
+
if (entry.kind === "extension" && entry.derivedFrom === null) context.addIssue({ code: z.ZodIssueCode.custom, path: ["derivedFrom"], message: "Extended environments require exact catalog bases." });
|
|
34
|
+
});
|
|
35
|
+
const sandboxEnvironmentCatalogSchema = z.object({
|
|
36
|
+
schemaVersion: z.literal("treeseed.sandbox-environment-catalog/v1"),
|
|
37
|
+
generation: z.number().int().positive(),
|
|
38
|
+
catalogDigest: digest,
|
|
39
|
+
rootPolicy: z.object({ allowedBaseImageDigests: z.array(digest).min(1) }).strict(),
|
|
40
|
+
entries: z.array(sandboxEnvironmentCatalogEntrySchema),
|
|
41
|
+
createdAt: z.string().datetime(),
|
|
42
|
+
signature: z.object({ keyId: identifier, algorithm: z.literal("Ed25519"), value: z.string().min(1) }).strict()
|
|
43
|
+
}).strict().superRefine((catalog, context) => {
|
|
44
|
+
const entries = new Map(catalog.entries.map((entry) => [`${entry.id}@${entry.version}`, entry]));
|
|
45
|
+
for (const [index, entry] of catalog.entries.entries()) {
|
|
46
|
+
if (entry.kind === "base" && !catalog.rootPolicy.allowedBaseImageDigests.includes(entry.image.digest)) context.addIssue({ code: z.ZodIssueCode.custom, path: ["entries", index, "image", "digest"], message: "Base image is not an allowed catalog root." });
|
|
47
|
+
if (entry.kind !== "extension" || !entry.derivedFrom) continue;
|
|
48
|
+
const parentArchitectures = /* @__PURE__ */ new Set();
|
|
49
|
+
for (const [parentIndex, reference] of entry.derivedFrom.entries()) {
|
|
50
|
+
const parent = entries.get(`${reference.entryId}@${reference.version}`);
|
|
51
|
+
if (!parent || parent.image.digest !== reference.imageDigest) {
|
|
52
|
+
context.addIssue({ code: z.ZodIssueCode.custom, path: ["entries", index, "derivedFrom", parentIndex], message: "Environment extension does not bind an exact entry in this catalog." });
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
const pending = [parent], seen = /* @__PURE__ */ new Set(), roots = [];
|
|
56
|
+
while (pending.length) {
|
|
57
|
+
const current = pending.pop(), key = `${current.id}@${current.version}`;
|
|
58
|
+
if (seen.has(key)) {
|
|
59
|
+
roots.length = 0;
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
seen.add(key);
|
|
63
|
+
if (current.kind === "base") {
|
|
64
|
+
roots.push(current);
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
for (const ancestor of current.derivedFrom ?? []) {
|
|
68
|
+
const resolved = entries.get(`${ancestor.entryId}@${ancestor.version}`);
|
|
69
|
+
if (!resolved || resolved.image.digest !== ancestor.imageDigest) {
|
|
70
|
+
roots.length = 0;
|
|
71
|
+
pending.length = 0;
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
pending.push(resolved);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (!roots.length || roots.some((root) => !catalog.rootPolicy.allowedBaseImageDigests.includes(root.image.digest))) context.addIssue({ code: z.ZodIssueCode.custom, path: ["entries", index, "derivedFrom", parentIndex], message: "Environment extension does not resolve to an allowed catalog root." });
|
|
78
|
+
else for (const root of roots) for (const architecture of root.image.architectures) parentArchitectures.add(architecture);
|
|
79
|
+
}
|
|
80
|
+
for (const architecture of entry.image.architectures) if (!parentArchitectures.has(architecture)) context.addIssue({ code: z.ZodIssueCode.custom, path: ["entries", index, "derivedFrom"], message: `Environment extension has no allowed ${architecture} base.` });
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
const providerSandboxEnvironmentAvailabilitySchema = z.object({
|
|
84
|
+
schemaVersion: z.literal("treeseed.provider-sandbox-environments/v1"),
|
|
85
|
+
providerId: z.string().min(1),
|
|
86
|
+
catalogGeneration: z.number().int().positive(),
|
|
87
|
+
catalogDigest: digest,
|
|
88
|
+
entries: z.array(z.object({ entryId: identifier, version, contractDigest: digest, imageDigest: digest, status: z.enum(["pulling", "ready", "failed", "quarantined"]), checkedAt: z.string().datetime(), reason: z.string().min(1).nullable() }).strict())
|
|
89
|
+
}).strict();
|
|
90
|
+
function canonical(value) {
|
|
91
|
+
if (value === null || typeof value !== "object") return JSON.stringify(value);
|
|
92
|
+
if (Array.isArray(value)) return `[${value.map(canonical).join(",")}]`;
|
|
93
|
+
return `{${Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, item]) => `${JSON.stringify(key)}:${canonical(item)}`).join(",")}}`;
|
|
94
|
+
}
|
|
95
|
+
function sandboxEnvironmentCatalogDigest(value) {
|
|
96
|
+
return `sha256:${createHash("sha256").update(canonical(value)).digest("hex")}`;
|
|
97
|
+
}
|
|
98
|
+
function sandboxEnvironmentCatalogSigningBytes(value) {
|
|
99
|
+
return Buffer.from(canonical({ ...value, signature: { ...value.signature, value: "" } }));
|
|
100
|
+
}
|
|
101
|
+
function verifySandboxEnvironmentCatalog(value, publicJwk) {
|
|
102
|
+
const catalog = sandboxEnvironmentCatalogSchema.parse(value);
|
|
103
|
+
const { catalogDigest, signature: _signature, ...material } = catalog;
|
|
104
|
+
if (sandboxEnvironmentCatalogDigest(material) !== catalogDigest) throw new Error("Sandbox environment catalog digest does not match its canonical content.");
|
|
105
|
+
if (!verify(null, sandboxEnvironmentCatalogSigningBytes(catalog), createPublicKey({ key: publicJwk, format: "jwk" }), Buffer.from(catalog.signature.value, "base64url"))) throw new Error("Sandbox environment catalog signature is invalid.");
|
|
106
|
+
return catalog;
|
|
107
|
+
}
|
|
108
|
+
export {
|
|
109
|
+
providerSandboxEnvironmentAvailabilitySchema,
|
|
110
|
+
sandboxEnvironmentCatalogDigest,
|
|
111
|
+
sandboxEnvironmentCatalogEntrySchema,
|
|
112
|
+
sandboxEnvironmentCatalogSchema,
|
|
113
|
+
sandboxEnvironmentCatalogSigningBytes,
|
|
114
|
+
sandboxEnvironmentContractSchema,
|
|
115
|
+
verifySandboxEnvironmentCatalog
|
|
116
|
+
};
|
|
@@ -2,3 +2,6 @@ export * from './client.js';
|
|
|
2
2
|
export * from './contracts/index.js';
|
|
3
3
|
export * from './validation.js';
|
|
4
4
|
export * from './sandbox-contracts.js';
|
|
5
|
+
export * from './environment-catalog.js';
|
|
6
|
+
export * from './capability-ontology.js';
|
|
7
|
+
export * from './core-capability-catalog.js';
|
|
@@ -2,3 +2,6 @@ export * from "./client.js";
|
|
|
2
2
|
export * from "./contracts/index.js";
|
|
3
3
|
export * from "./validation.js";
|
|
4
4
|
export * from "./sandbox-contracts.js";
|
|
5
|
+
export * from "./environment-catalog.js";
|
|
6
|
+
export * from "./capability-ontology.js";
|
|
7
|
+
export * from "./core-capability-catalog.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
declare const sandboxProfile: z.
|
|
2
|
+
declare const sandboxProfile: z.ZodString;
|
|
3
3
|
export declare const sandboxAssignmentSchema: z.ZodObject<{
|
|
4
4
|
schemaVersion: z.ZodLiteral<"treeseed.sandbox-assignment/v1">;
|
|
5
5
|
assignmentId: z.ZodString;
|
|
@@ -8,7 +8,23 @@ export declare const sandboxAssignmentSchema: z.ZodObject<{
|
|
|
8
8
|
providerId: z.ZodString;
|
|
9
9
|
teamId: z.ZodString;
|
|
10
10
|
projectId: z.ZodString;
|
|
11
|
-
profile: z.
|
|
11
|
+
profile: z.ZodString;
|
|
12
|
+
environmentContract: z.ZodOptional<z.ZodObject<{
|
|
13
|
+
id: z.ZodString;
|
|
14
|
+
version: z.ZodString;
|
|
15
|
+
digest: z.ZodString;
|
|
16
|
+
capabilities: z.ZodArray<z.ZodString, "many">;
|
|
17
|
+
}, "strict", z.ZodTypeAny, {
|
|
18
|
+
id: string;
|
|
19
|
+
digest: string;
|
|
20
|
+
version: string;
|
|
21
|
+
capabilities: string[];
|
|
22
|
+
}, {
|
|
23
|
+
id: string;
|
|
24
|
+
digest: string;
|
|
25
|
+
version: string;
|
|
26
|
+
capabilities: string[];
|
|
27
|
+
}>>;
|
|
12
28
|
guestImage: z.ZodString;
|
|
13
29
|
guestImageDigest: z.ZodString;
|
|
14
30
|
identityManifestDigest: z.ZodString;
|
|
@@ -158,7 +174,7 @@ export declare const sandboxAssignmentSchema: z.ZodObject<{
|
|
|
158
174
|
outputBytes: number;
|
|
159
175
|
};
|
|
160
176
|
projectId: string;
|
|
161
|
-
profile:
|
|
177
|
+
profile: string;
|
|
162
178
|
network: {
|
|
163
179
|
defaultDeny: true;
|
|
164
180
|
relayUrl: string;
|
|
@@ -169,10 +185,6 @@ export declare const sandboxAssignmentSchema: z.ZodObject<{
|
|
|
169
185
|
guestImageDigest: string;
|
|
170
186
|
providerId: string;
|
|
171
187
|
runnerId: string;
|
|
172
|
-
leaseExpiresAt: string;
|
|
173
|
-
attempt: number;
|
|
174
|
-
identityManifestDigest: string;
|
|
175
|
-
contextManifestDigest: string;
|
|
176
188
|
inputs: {
|
|
177
189
|
id: string;
|
|
178
190
|
mediaType: string;
|
|
@@ -181,6 +193,15 @@ export declare const sandboxAssignmentSchema: z.ZodObject<{
|
|
|
181
193
|
disposition: "read-only" | "copy-on-write";
|
|
182
194
|
targetPath: string;
|
|
183
195
|
}[];
|
|
196
|
+
signature: {
|
|
197
|
+
value: string;
|
|
198
|
+
algorithm: "Ed25519";
|
|
199
|
+
keyId: string;
|
|
200
|
+
};
|
|
201
|
+
leaseExpiresAt: string;
|
|
202
|
+
attempt: number;
|
|
203
|
+
identityManifestDigest: string;
|
|
204
|
+
contextManifestDigest: string;
|
|
184
205
|
modelPolicy: {
|
|
185
206
|
provider: string;
|
|
186
207
|
capabilities: string[];
|
|
@@ -195,11 +216,12 @@ export declare const sandboxAssignmentSchema: z.ZodObject<{
|
|
|
195
216
|
revealAllowed: false;
|
|
196
217
|
}[];
|
|
197
218
|
treeDxHandleIds: string[];
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
219
|
+
environmentContract?: {
|
|
220
|
+
id: string;
|
|
221
|
+
digest: string;
|
|
222
|
+
version: string;
|
|
223
|
+
capabilities: string[];
|
|
224
|
+
} | undefined;
|
|
203
225
|
}, {
|
|
204
226
|
teamId: string;
|
|
205
227
|
assignmentId: string;
|
|
@@ -219,7 +241,7 @@ export declare const sandboxAssignmentSchema: z.ZodObject<{
|
|
|
219
241
|
outputBytes: number;
|
|
220
242
|
};
|
|
221
243
|
projectId: string;
|
|
222
|
-
profile:
|
|
244
|
+
profile: string;
|
|
223
245
|
network: {
|
|
224
246
|
defaultDeny: true;
|
|
225
247
|
relayUrl: string;
|
|
@@ -230,10 +252,6 @@ export declare const sandboxAssignmentSchema: z.ZodObject<{
|
|
|
230
252
|
guestImageDigest: string;
|
|
231
253
|
providerId: string;
|
|
232
254
|
runnerId: string;
|
|
233
|
-
leaseExpiresAt: string;
|
|
234
|
-
attempt: number;
|
|
235
|
-
identityManifestDigest: string;
|
|
236
|
-
contextManifestDigest: string;
|
|
237
255
|
inputs: {
|
|
238
256
|
id: string;
|
|
239
257
|
mediaType: string;
|
|
@@ -242,6 +260,15 @@ export declare const sandboxAssignmentSchema: z.ZodObject<{
|
|
|
242
260
|
disposition: "read-only" | "copy-on-write";
|
|
243
261
|
targetPath: string;
|
|
244
262
|
}[];
|
|
263
|
+
signature: {
|
|
264
|
+
value: string;
|
|
265
|
+
algorithm: "Ed25519";
|
|
266
|
+
keyId: string;
|
|
267
|
+
};
|
|
268
|
+
leaseExpiresAt: string;
|
|
269
|
+
attempt: number;
|
|
270
|
+
identityManifestDigest: string;
|
|
271
|
+
contextManifestDigest: string;
|
|
245
272
|
modelPolicy: {
|
|
246
273
|
provider: string;
|
|
247
274
|
capabilities: string[];
|
|
@@ -256,11 +283,12 @@ export declare const sandboxAssignmentSchema: z.ZodObject<{
|
|
|
256
283
|
revealAllowed: false;
|
|
257
284
|
}[];
|
|
258
285
|
treeDxHandleIds: string[];
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
286
|
+
environmentContract?: {
|
|
287
|
+
id: string;
|
|
288
|
+
digest: string;
|
|
289
|
+
version: string;
|
|
290
|
+
capabilities: string[];
|
|
291
|
+
} | undefined;
|
|
264
292
|
}>;
|
|
265
293
|
export declare const sandboxEventSchema: z.ZodObject<{
|
|
266
294
|
schemaVersion: z.ZodLiteral<"treeseed.sandbox-event/v1">;
|
|
@@ -313,26 +341,26 @@ export declare const sandboxLeaseRenewalSchema: z.ZodObject<{
|
|
|
313
341
|
assignmentId: string;
|
|
314
342
|
schemaVersion: "treeseed.sandbox-lease-renewal/v1";
|
|
315
343
|
providerId: string;
|
|
316
|
-
leaseExpiresAt: string;
|
|
317
|
-
issuedAt: string;
|
|
318
344
|
signature: {
|
|
319
345
|
value: string;
|
|
320
346
|
algorithm: "Ed25519";
|
|
321
347
|
keyId: string;
|
|
322
348
|
};
|
|
349
|
+
issuedAt: string;
|
|
350
|
+
leaseExpiresAt: string;
|
|
323
351
|
sandboxId: string;
|
|
324
352
|
}, {
|
|
325
353
|
teamId: string;
|
|
326
354
|
assignmentId: string;
|
|
327
355
|
schemaVersion: "treeseed.sandbox-lease-renewal/v1";
|
|
328
356
|
providerId: string;
|
|
329
|
-
leaseExpiresAt: string;
|
|
330
|
-
issuedAt: string;
|
|
331
357
|
signature: {
|
|
332
358
|
value: string;
|
|
333
359
|
algorithm: "Ed25519";
|
|
334
360
|
keyId: string;
|
|
335
361
|
};
|
|
362
|
+
issuedAt: string;
|
|
363
|
+
leaseExpiresAt: string;
|
|
336
364
|
sandboxId: string;
|
|
337
365
|
}>;
|
|
338
366
|
export declare const sandboxResultSchema: z.ZodObject<{
|
|
@@ -414,9 +442,102 @@ export declare const sandboxResultSchema: z.ZodObject<{
|
|
|
414
442
|
diagnostics?: Record<string, unknown> | undefined;
|
|
415
443
|
responseMarkdown?: string | undefined;
|
|
416
444
|
}>;
|
|
445
|
+
export declare const providerEnvironmentReceiptSchema: z.ZodObject<{
|
|
446
|
+
schemaVersion: z.ZodLiteral<"treeseed.provider-environment-receipt/v1">;
|
|
447
|
+
assignmentId: z.ZodString;
|
|
448
|
+
offerId: z.ZodString;
|
|
449
|
+
providerId: z.ZodString;
|
|
450
|
+
imageDigest: z.ZodString;
|
|
451
|
+
baseLineage: z.ZodObject<{
|
|
452
|
+
baseImageDigest: z.ZodString;
|
|
453
|
+
provenanceDigest: z.ZodString;
|
|
454
|
+
architectures: z.ZodArray<z.ZodEnum<["amd64", "arm64"]>, "many">;
|
|
455
|
+
}, "strict", z.ZodTypeAny, {
|
|
456
|
+
baseImageDigest: string;
|
|
457
|
+
provenanceDigest: string;
|
|
458
|
+
architectures: ("amd64" | "arm64")[];
|
|
459
|
+
}, {
|
|
460
|
+
baseImageDigest: string;
|
|
461
|
+
provenanceDigest: string;
|
|
462
|
+
architectures: ("amd64" | "arm64")[];
|
|
463
|
+
}>;
|
|
464
|
+
securityAttestationDigest: z.ZodString;
|
|
465
|
+
brokerVersion: z.ZodString;
|
|
466
|
+
teardown: z.ZodObject<{
|
|
467
|
+
verified: z.ZodBoolean;
|
|
468
|
+
completedAt: z.ZodNullable<z.ZodString>;
|
|
469
|
+
}, "strict", z.ZodTypeAny, {
|
|
470
|
+
completedAt: string | null;
|
|
471
|
+
verified: boolean;
|
|
472
|
+
}, {
|
|
473
|
+
completedAt: string | null;
|
|
474
|
+
verified: boolean;
|
|
475
|
+
}>;
|
|
476
|
+
createdAt: z.ZodString;
|
|
477
|
+
signature: z.ZodObject<{
|
|
478
|
+
keyId: z.ZodString;
|
|
479
|
+
algorithm: z.ZodLiteral<"Ed25519">;
|
|
480
|
+
value: z.ZodString;
|
|
481
|
+
}, "strict", z.ZodTypeAny, {
|
|
482
|
+
value: string;
|
|
483
|
+
algorithm: "Ed25519";
|
|
484
|
+
keyId: string;
|
|
485
|
+
}, {
|
|
486
|
+
value: string;
|
|
487
|
+
algorithm: "Ed25519";
|
|
488
|
+
keyId: string;
|
|
489
|
+
}>;
|
|
490
|
+
}, "strict", z.ZodTypeAny, {
|
|
491
|
+
assignmentId: string;
|
|
492
|
+
schemaVersion: "treeseed.provider-environment-receipt/v1";
|
|
493
|
+
createdAt: string;
|
|
494
|
+
providerId: string;
|
|
495
|
+
signature: {
|
|
496
|
+
value: string;
|
|
497
|
+
algorithm: "Ed25519";
|
|
498
|
+
keyId: string;
|
|
499
|
+
};
|
|
500
|
+
offerId: string;
|
|
501
|
+
teardown: {
|
|
502
|
+
completedAt: string | null;
|
|
503
|
+
verified: boolean;
|
|
504
|
+
};
|
|
505
|
+
imageDigest: string;
|
|
506
|
+
baseLineage: {
|
|
507
|
+
baseImageDigest: string;
|
|
508
|
+
provenanceDigest: string;
|
|
509
|
+
architectures: ("amd64" | "arm64")[];
|
|
510
|
+
};
|
|
511
|
+
securityAttestationDigest: string;
|
|
512
|
+
brokerVersion: string;
|
|
513
|
+
}, {
|
|
514
|
+
assignmentId: string;
|
|
515
|
+
schemaVersion: "treeseed.provider-environment-receipt/v1";
|
|
516
|
+
createdAt: string;
|
|
517
|
+
providerId: string;
|
|
518
|
+
signature: {
|
|
519
|
+
value: string;
|
|
520
|
+
algorithm: "Ed25519";
|
|
521
|
+
keyId: string;
|
|
522
|
+
};
|
|
523
|
+
offerId: string;
|
|
524
|
+
teardown: {
|
|
525
|
+
completedAt: string | null;
|
|
526
|
+
verified: boolean;
|
|
527
|
+
};
|
|
528
|
+
imageDigest: string;
|
|
529
|
+
baseLineage: {
|
|
530
|
+
baseImageDigest: string;
|
|
531
|
+
provenanceDigest: string;
|
|
532
|
+
architectures: ("amd64" | "arm64")[];
|
|
533
|
+
};
|
|
534
|
+
securityAttestationDigest: string;
|
|
535
|
+
brokerVersion: string;
|
|
536
|
+
}>;
|
|
417
537
|
export type SandboxAssignment = z.infer<typeof sandboxAssignmentSchema>;
|
|
418
538
|
export type SandboxEvent = z.infer<typeof sandboxEventSchema>;
|
|
419
539
|
export type SandboxLeaseRenewal = z.infer<typeof sandboxLeaseRenewalSchema>;
|
|
420
540
|
export type SandboxResult = z.infer<typeof sandboxResultSchema>;
|
|
541
|
+
export type ProviderEnvironmentReceipt = z.infer<typeof providerEnvironmentReceiptSchema>;
|
|
421
542
|
export type SandboxEnvironmentProfile = z.infer<typeof sandboxProfile>;
|
|
422
543
|
export {};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
const identifier = z.string().regex(/^[a-z][a-z0-9._-]{0,127}$/u);
|
|
3
3
|
const digest = z.string().regex(/^sha256:[a-f0-9]{64}$/u);
|
|
4
|
-
const sandboxProfile =
|
|
4
|
+
const sandboxProfile = identifier;
|
|
5
5
|
const sandboxAssignmentSchema = z.object({
|
|
6
6
|
schemaVersion: z.literal("treeseed.sandbox-assignment/v1"),
|
|
7
7
|
assignmentId: z.string().min(1),
|
|
@@ -11,6 +11,7 @@ const sandboxAssignmentSchema = z.object({
|
|
|
11
11
|
teamId: z.string().min(1),
|
|
12
12
|
projectId: z.string().min(1),
|
|
13
13
|
profile: sandboxProfile,
|
|
14
|
+
environmentContract: z.object({ id: identifier, version: z.string().regex(/^\d+\.\d+\.\d+$/u), digest, capabilities: z.array(identifier) }).strict().optional(),
|
|
14
15
|
guestImage: z.string().min(1),
|
|
15
16
|
guestImageDigest: digest,
|
|
16
17
|
identityManifestDigest: digest,
|
|
@@ -63,7 +64,21 @@ const sandboxResultSchema = z.object({
|
|
|
63
64
|
diagnostics: z.record(z.unknown()).default({}),
|
|
64
65
|
teardown: z.object({ verified: z.boolean(), completedAt: z.string().datetime().nullable() }).strict()
|
|
65
66
|
}).strict();
|
|
67
|
+
const providerEnvironmentReceiptSchema = z.object({
|
|
68
|
+
schemaVersion: z.literal("treeseed.provider-environment-receipt/v1"),
|
|
69
|
+
assignmentId: z.string().min(1),
|
|
70
|
+
offerId: identifier,
|
|
71
|
+
providerId: z.string().min(1),
|
|
72
|
+
imageDigest: digest,
|
|
73
|
+
baseLineage: z.object({ baseImageDigest: digest, provenanceDigest: digest, architectures: z.array(z.enum(["amd64", "arm64"])).min(1) }).strict(),
|
|
74
|
+
securityAttestationDigest: digest,
|
|
75
|
+
brokerVersion: z.string().min(1),
|
|
76
|
+
teardown: z.object({ verified: z.boolean(), completedAt: z.string().datetime().nullable() }).strict(),
|
|
77
|
+
createdAt: z.string().datetime(),
|
|
78
|
+
signature: z.object({ keyId: identifier, algorithm: z.literal("Ed25519"), value: z.string().min(1) }).strict()
|
|
79
|
+
}).strict();
|
|
66
80
|
export {
|
|
81
|
+
providerEnvironmentReceiptSchema,
|
|
67
82
|
sandboxAssignmentSchema,
|
|
68
83
|
sandboxEventSchema,
|
|
69
84
|
sandboxLeaseRenewalSchema,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type CapacityProviderManifestV3, type CapacityProviderManifestV4, type CapacityProviderProofPayload, type CapacityProviderPublicJwk, type ProviderSupplyOffer } from './contracts/index.js';
|
|
1
|
+
import { type CapacityProviderManifestV3, type CapacityProviderManifestV4, type CapacityProviderManifestV5, type CapacityProviderProofPayload, type CapacityProviderPublicJwk, type ProviderSupplyOffer } from './contracts/index.js';
|
|
2
2
|
export interface CapacityProviderContractDiagnostic {
|
|
3
3
|
code: string;
|
|
4
4
|
path: string;
|
|
@@ -21,6 +21,7 @@ export declare function validateCapacityProviderProofPayload(payload: CapacityPr
|
|
|
21
21
|
export declare function validateProviderSupplyOffer(offer: ProviderSupplyOffer, path?: string): CapacityProviderContractValidation;
|
|
22
22
|
export declare function validateCapacityProviderManifestV3(manifest: CapacityProviderManifestV3): CapacityProviderContractValidation;
|
|
23
23
|
export declare function validateCapacityProviderManifestV4(manifest: CapacityProviderManifestV4): CapacityProviderContractValidation;
|
|
24
|
+
export declare function validateCapacityProviderManifestV5(manifest: CapacityProviderManifestV5): CapacityProviderContractValidation;
|
|
24
25
|
export declare function capacityProviderSecurityDefaults(): {
|
|
25
26
|
proofTtlSeconds: number;
|
|
26
27
|
accessTokenTtlSeconds: number;
|
|
@@ -187,13 +187,45 @@ function validateCapacityProviderManifestV4(manifest) {
|
|
|
187
187
|
if (!manifest.sandbox?.brokerSocket?.startsWith("/run/treeseed/")) add(diagnostics, "provider_sandbox_socket_invalid", "sandbox.brokerSocket", "Sandbox broker socket must remain under /run/treeseed.");
|
|
188
188
|
const profiles = new Set((manifest.sandbox?.profiles ?? []).map((profile) => profile.id));
|
|
189
189
|
for (const [index, profile] of (manifest.sandbox?.profiles ?? []).entries()) {
|
|
190
|
-
if (
|
|
190
|
+
if (!/^[a-z][a-z0-9._-]{0,127}$/u.test(profile.id)) add(diagnostics, "provider_sandbox_profile_invalid", `sandbox.profiles[${index}].id`, "Sandbox profile id must be a provider-local identifier.");
|
|
191
|
+
if (profile.contract) {
|
|
192
|
+
if (!/^[a-z][a-z0-9._-]{0,127}$/u.test(profile.contract.id) || !/^\d+\.\d+\.\d+$/u.test(profile.contract.version) || !/^sha256:[a-f0-9]{64}$/u.test(profile.contract.digest)) add(diagnostics, "provider_sandbox_contract_invalid", `sandbox.profiles[${index}].contract`, "Portable sandbox contracts require an id, exact semantic version, and immutable digest.");
|
|
193
|
+
if (!Array.isArray(profile.contract.capabilities) || profile.contract.capabilities.some((capability) => !/^[a-z][a-z0-9._-]{0,127}$/u.test(capability))) add(diagnostics, "provider_sandbox_contract_capabilities_invalid", `sandbox.profiles[${index}].contract.capabilities`, "Sandbox contract capabilities must be portable identifiers.");
|
|
194
|
+
}
|
|
191
195
|
if (!/^sha256:[a-f0-9]{64}$/u.test(profile.guestImageDigest)) add(diagnostics, "provider_sandbox_image_digest_invalid", `sandbox.profiles[${index}].guestImageDigest`, "Guest images require an immutable SHA-256 digest.");
|
|
192
196
|
if (profile.defaultDenyNetwork !== true) add(diagnostics, "provider_sandbox_network_policy_invalid", `sandbox.profiles[${index}].defaultDenyNetwork`, "Sandbox networking must default deny.");
|
|
193
197
|
}
|
|
194
198
|
for (const [index, adapter] of manifest.adapters.entries()) {
|
|
195
199
|
if (adapter.isolation !== "microvm") add(diagnostics, "provider_v4_microvm_required", `adapters[${index}].isolation`, "Manifest v4 adapters must use microvm isolation.");
|
|
196
200
|
for (const profile of adapter.sandboxProfileIds ?? []) if (!profiles.has(profile)) add(diagnostics, "provider_sandbox_profile_unknown", `adapters[${index}].sandboxProfileIds`, `Unknown sandbox profile ${profile}.`);
|
|
201
|
+
for (const [purpose, profile] of Object.entries(adapter.defaultSandboxProfiles ?? {})) if (!profiles.has(profile)) add(diagnostics, "provider_sandbox_default_unknown", `adapters[${index}].defaultSandboxProfiles.${purpose}`, `Unknown default sandbox profile ${profile}.`);
|
|
202
|
+
}
|
|
203
|
+
return result(diagnostics);
|
|
204
|
+
}
|
|
205
|
+
function validateCapacityProviderManifestV5(manifest) {
|
|
206
|
+
const compatible = { ...manifest, schemaVersion: 4, adapters: manifest.adapters.map((adapter) => ({
|
|
207
|
+
...adapter,
|
|
208
|
+
capabilities: [...new Set(adapter.offers.flatMap(({ offer }) => offer.capabilities.map(({ id }) => id)))],
|
|
209
|
+
sandboxProfileIds: [...new Set(adapter.offers.map(({ sandboxProfileId }) => sandboxProfileId))],
|
|
210
|
+
defaultSandboxProfiles: void 0
|
|
211
|
+
})) };
|
|
212
|
+
const diagnostics = validateCapacityProviderManifestV4(compatible).diagnostics.filter((entry) => entry.code !== "provider_sandbox_default_unknown");
|
|
213
|
+
if (manifest.schemaVersion !== 5) add(diagnostics, "provider_manifest_schema_invalid", "schemaVersion", "Capacity provider manifest schemaVersion must be 5.");
|
|
214
|
+
if (!Number.isInteger(manifest.ontology?.generation) || manifest.ontology.generation < 1 || !/^sha256:[a-f0-9]{64}$/u.test(manifest.ontology?.digest ?? "")) add(diagnostics, "provider_ontology_binding_invalid", "ontology", "Manifest v5 requires an exact ontology generation and digest.");
|
|
215
|
+
const profiles = new Set(manifest.sandbox.profiles.map(({ id }) => id)), offerIds = /* @__PURE__ */ new Set();
|
|
216
|
+
for (const [profileIndex, profile] of manifest.sandbox.profiles.entries()) {
|
|
217
|
+
if (!profile.lineage || !/^sha256:[a-f0-9]{64}$/u.test(profile.lineage.baseImageDigest) || !/^sha256:[a-f0-9]{64}$/u.test(profile.lineage.provenanceDigest) || !profile.lineage.architectures.length || !profile.lineage.signature.value) add(diagnostics, "provider_sandbox_lineage_required", `sandbox.profiles[${profileIndex}].lineage`, "Manifest v5 sandbox images require signed exact sandbox-base lineage and architectures.");
|
|
218
|
+
}
|
|
219
|
+
for (const [adapterIndex, adapter] of manifest.adapters.entries()) {
|
|
220
|
+
if (!adapter.offers.length) add(diagnostics, "provider_adapter_offers_required", `adapters[${adapterIndex}].offers`, "Every v5 adapter must expose at least one standardized capability offer.");
|
|
221
|
+
for (const [offerIndex, binding] of adapter.offers.entries()) {
|
|
222
|
+
const path = `adapters[${adapterIndex}].offers[${offerIndex}]`;
|
|
223
|
+
if (offerIds.has(binding.offer.offerId)) add(diagnostics, "provider_offer_id_duplicate", `${path}.offer.offerId`, "Offer ids must be provider-global unique.");
|
|
224
|
+
offerIds.add(binding.offer.offerId);
|
|
225
|
+
if (!profiles.has(binding.sandboxProfileId)) add(diagnostics, "provider_offer_sandbox_unknown", `${path}.sandboxProfileId`, "Offer references an unknown provider-local sandbox profile.");
|
|
226
|
+
if (binding.offer.capabilities.some((reference) => !reference.id.startsWith("treeseed.") && !reference.id.startsWith("provider."))) add(diagnostics, "provider_offer_capability_namespace_invalid", `${path}.offer.capabilities`, "Offers require standardized TreeSeed or provider capability references.");
|
|
227
|
+
if (binding.offer.conformance.some((entry) => entry.status !== "passed")) add(diagnostics, "provider_offer_conformance_failed", `${path}.offer.conformance`, "Only passing capability conformance may be advertised.");
|
|
228
|
+
}
|
|
197
229
|
}
|
|
198
230
|
return result(diagnostics);
|
|
199
231
|
}
|
|
@@ -211,6 +243,7 @@ export {
|
|
|
211
243
|
result,
|
|
212
244
|
validateCapacityProviderManifestV3,
|
|
213
245
|
validateCapacityProviderManifestV4,
|
|
246
|
+
validateCapacityProviderManifestV5,
|
|
214
247
|
validateCapacityProviderProofPayload,
|
|
215
248
|
validateCapacityProviderPublicJwk,
|
|
216
249
|
validateProviderSupplyOffer
|