agent-hitch 0.2.12 → 0.2.14

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.
Files changed (165) hide show
  1. package/benchmark-packages/automationbench/RESOURCES.md +27 -0
  2. package/benchmark-packages/automationbench/resources.mjs +86 -0
  3. package/benchmark-packages/shared-tree/README.md +14 -0
  4. package/benchmark-packages/shared-tree/import.mjs +39 -0
  5. package/dist/scripts/canary-automation-resources.js +86 -0
  6. package/dist/scripts/canary-automation-resources.js.map +1 -0
  7. package/dist/scripts/canary-resource-empty-daemon.js +195 -0
  8. package/dist/scripts/canary-resource-empty-daemon.js.map +1 -0
  9. package/dist/scripts/canary-resources.js +89 -0
  10. package/dist/scripts/canary-resources.js.map +1 -0
  11. package/dist/scripts/check-architecture.js +6 -5
  12. package/dist/scripts/check-architecture.js.map +1 -1
  13. package/dist/scripts/resource-space-sampler.js +83 -0
  14. package/dist/scripts/resource-space-sampler.js.map +1 -0
  15. package/dist/src/adapters/providers/shared.js +0 -1
  16. package/dist/src/adapters/providers/shared.js.map +1 -1
  17. package/dist/src/backends/harbor/backend.js +5 -1
  18. package/dist/src/backends/harbor/backend.js.map +1 -1
  19. package/dist/src/backends/harbor/resource-admission.js +23 -0
  20. package/dist/src/backends/harbor/resource-admission.js.map +1 -0
  21. package/dist/src/cli/commands/resources.js +23 -0
  22. package/dist/src/cli/commands/resources.js.map +1 -0
  23. package/dist/src/cli/main.js +2 -0
  24. package/dist/src/cli/main.js.map +1 -1
  25. package/dist/src/control-plane/remote-offer-contract.js +11 -2
  26. package/dist/src/control-plane/remote-offer-contract.js.map +1 -1
  27. package/dist/src/control-plane/remote-result-transport.js +10 -0
  28. package/dist/src/control-plane/remote-result-transport.js.map +1 -1
  29. package/dist/src/control-plane/remote-work-coordinator.js +4 -1
  30. package/dist/src/control-plane/remote-work-coordinator.js.map +1 -1
  31. package/dist/src/control-plane/remote-work-inputs.js +16 -4
  32. package/dist/src/control-plane/remote-work-inputs.js.map +1 -1
  33. package/dist/src/control-plane/remote-worker-client.js +22 -0
  34. package/dist/src/control-plane/remote-worker-client.js.map +1 -1
  35. package/dist/src/control-plane/remote-worker-codecs.js +1 -1
  36. package/dist/src/control-plane/remote-worker-codecs.js.map +1 -1
  37. package/dist/src/control-plane/remote-worker-protocol.js +12 -2
  38. package/dist/src/control-plane/remote-worker-protocol.js.map +1 -1
  39. package/dist/src/control-plane/remote-worker-runner.js +1 -1
  40. package/dist/src/control-plane/remote-worker-runner.js.map +1 -1
  41. package/dist/src/control-plane/remote-workers.js +2 -1
  42. package/dist/src/control-plane/remote-workers.js.map +1 -1
  43. package/dist/src/domain/validation.js +41 -6
  44. package/dist/src/domain/validation.js.map +1 -1
  45. package/dist/src/evals/benchmark-adapter-manifest.js +4 -0
  46. package/dist/src/evals/benchmark-adapter-manifest.js.map +1 -1
  47. package/dist/src/evals/benchmark-candidate.js +11 -3
  48. package/dist/src/evals/benchmark-candidate.js.map +1 -1
  49. package/dist/src/evals/eval-result-builder.js +22 -1
  50. package/dist/src/evals/eval-result-builder.js.map +1 -1
  51. package/dist/src/evals/index.js +1 -0
  52. package/dist/src/evals/index.js.map +1 -1
  53. package/dist/src/evals/planned-execution.js +5 -14
  54. package/dist/src/evals/planned-execution.js.map +1 -1
  55. package/dist/src/evals/request.js +9 -0
  56. package/dist/src/evals/request.js.map +1 -1
  57. package/dist/src/evals/resource-eval-lifecycle.js +31 -0
  58. package/dist/src/evals/resource-eval-lifecycle.js.map +1 -0
  59. package/dist/src/evals/resource-legacy-export.js +57 -0
  60. package/dist/src/evals/resource-legacy-export.js.map +1 -0
  61. package/dist/src/evals/service.js +5 -20
  62. package/dist/src/evals/service.js.map +1 -1
  63. package/dist/src/evals/task-resources.js +12 -4
  64. package/dist/src/evals/task-resources.js.map +1 -1
  65. package/dist/src/evals/trial-bundle-files.js +81 -0
  66. package/dist/src/evals/trial-bundle-files.js.map +1 -0
  67. package/dist/src/evals/trial-import.js +7 -78
  68. package/dist/src/evals/trial-import.js.map +1 -1
  69. package/dist/src/foundation/durable-json.js +33 -0
  70. package/dist/src/foundation/durable-json.js.map +1 -0
  71. package/dist/src/foundation/index.js +2 -0
  72. package/dist/src/foundation/index.js.map +1 -1
  73. package/dist/src/foundation/resource-image-references.js +52 -0
  74. package/dist/src/foundation/resource-image-references.js.map +1 -0
  75. package/dist/src/images/gc.js +2 -2
  76. package/dist/src/images/gc.js.map +1 -1
  77. package/dist/src/images/registry.js +27 -2
  78. package/dist/src/images/registry.js.map +1 -1
  79. package/dist/src/resources/api.js +207 -0
  80. package/dist/src/resources/api.js.map +1 -0
  81. package/dist/src/resources/bundle.js +117 -0
  82. package/dist/src/resources/bundle.js.map +1 -0
  83. package/dist/src/resources/evidence.js +93 -0
  84. package/dist/src/resources/evidence.js.map +1 -0
  85. package/dist/src/resources/gc.js +123 -0
  86. package/dist/src/resources/gc.js.map +1 -0
  87. package/dist/src/resources/index.js +14 -0
  88. package/dist/src/resources/index.js.map +1 -0
  89. package/dist/src/resources/materialize.js +143 -0
  90. package/dist/src/resources/materialize.js.map +1 -0
  91. package/dist/src/resources/object-store.js +191 -0
  92. package/dist/src/resources/object-store.js.map +1 -0
  93. package/dist/src/resources/oci-layer-validation.js +202 -0
  94. package/dist/src/resources/oci-layer-validation.js.map +1 -0
  95. package/dist/src/resources/oci-provider.js +101 -0
  96. package/dist/src/resources/oci-provider.js.map +1 -0
  97. package/dist/src/resources/oci-registry-bundle.js +253 -0
  98. package/dist/src/resources/oci-registry-bundle.js.map +1 -0
  99. package/dist/src/resources/protocol.js +222 -0
  100. package/dist/src/resources/protocol.js.map +1 -0
  101. package/dist/src/resources/result-retention.js +93 -0
  102. package/dist/src/resources/result-retention.js.map +1 -0
  103. package/dist/src/resources/role-context.js +54 -0
  104. package/dist/src/resources/role-context.js.map +1 -0
  105. package/dist/src/resources/stats.js +36 -0
  106. package/dist/src/resources/stats.js.map +1 -0
  107. package/dist/src/resources/store.js +310 -0
  108. package/dist/src/resources/store.js.map +1 -0
  109. package/dist/src/resources/tasks.js +153 -0
  110. package/dist/src/resources/tasks.js.map +1 -0
  111. package/dist/src/resources/transfer.js +162 -0
  112. package/dist/src/resources/transfer.js.map +1 -0
  113. package/dist/src/resources/views.js +130 -0
  114. package/dist/src/resources/views.js.map +1 -0
  115. package/dist/src/trajectories/analysis.js +31 -9
  116. package/dist/src/trajectories/analysis.js.map +1 -1
  117. package/dist/src/trajectories/chunk-projection.js +24 -11
  118. package/dist/src/trajectories/chunk-projection.js.map +1 -1
  119. package/dist/src/trajectories/contract.js +4 -0
  120. package/dist/src/trajectories/contract.js.map +1 -1
  121. package/dist/src/trajectories/dsh-chunk-contract.js +2 -2
  122. package/dist/src/trajectories/dsh-chunk-contract.js.map +1 -1
  123. package/dist/src/trajectories/dsh-contract.js +114 -17
  124. package/dist/src/trajectories/dsh-contract.js.map +1 -1
  125. package/dist/src/trajectories/embedded-stream.js +95 -0
  126. package/dist/src/trajectories/embedded-stream.js.map +1 -0
  127. package/dist/src/trajectories/events-chunk-drill.js +40 -0
  128. package/dist/src/trajectories/events-chunk-drill.js.map +1 -1
  129. package/dist/src/trajectories/events-page.js +43 -3
  130. package/dist/src/trajectories/events-page.js.map +1 -1
  131. package/dist/src/trajectories/format.js +3 -7
  132. package/dist/src/trajectories/format.js.map +1 -1
  133. package/dist/src/trajectories/index.js +1 -1
  134. package/dist/src/trajectories/index.js.map +1 -1
  135. package/dist/src/trajectories/providers/deepseek-codec.js +134 -0
  136. package/dist/src/trajectories/providers/deepseek-codec.js.map +1 -0
  137. package/dist/src/trajectories/providers/deepseek.js +32 -20
  138. package/dist/src/trajectories/providers/deepseek.js.map +1 -1
  139. package/dist/src/trajectories/request-attempt.js +16 -3
  140. package/dist/src/trajectories/request-attempt.js.map +1 -1
  141. package/dist/src/trajectories/store.js +28 -13
  142. package/dist/src/trajectories/store.js.map +1 -1
  143. package/dist/src/trajectories/stream-reader.js +12 -4
  144. package/dist/src/trajectories/stream-reader.js.map +1 -1
  145. package/dist/src/trajectories/surface-fold.js +26 -6
  146. package/dist/src/trajectories/surface-fold.js.map +1 -1
  147. package/dist/src/trajectories/unstarted-tool-repair.js +65 -0
  148. package/dist/src/trajectories/unstarted-tool-repair.js.map +1 -0
  149. package/dist/src/workers/remote-harbor-work-spec.js +9 -3
  150. package/dist/src/workers/remote-harbor-work-spec.js.map +1 -1
  151. package/dist/src/workers/remote-harbor-worker.js +24 -9
  152. package/dist/src/workers/remote-harbor-worker.js.map +1 -1
  153. package/docs/resource-storage.zh-CN.md +95 -0
  154. package/docs/schemas/execution-provider-status.schema.json +20 -0
  155. package/docs/schemas/hitch-resource-dataset-v2.schema.json +590 -0
  156. package/docs/schemas/hitch-resource-lock-v1.schema.json +341 -0
  157. package/docs/schemas/hitch-resource-plan-v1.schema.json +423 -0
  158. package/docs/schemas/hitch-resource-selection-v1.schema.json +608 -0
  159. package/docs/schemas/hitch-tree-v1.schema.json +75 -0
  160. package/docs/schemas/remote-harbor-work-spec.schema.json +47 -3
  161. package/docs/schemas/remote-work-offer.schema.json +2 -1
  162. package/docs/schemas/remote-worker-registration.schema.json +20 -0
  163. package/docs/schemas/trajectory-analysis.schema.json +17 -3
  164. package/package.json +9 -3
  165. package/test-contracts/hitch-resources-v1.json +197 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"object-store.js","sourceRoot":"","sources":["../../../src/resources/object-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,202 @@
1
+ import { createHash } from "node:crypto";
2
+ import { createReadStream } from "node:fs";
3
+ import { Writable } from "node:stream";
4
+ import { pipeline } from "node:stream/promises";
5
+ import { createGunzip } from "node:zlib";
6
+ import path from "node:path";
7
+ export const DEFAULT_IMAGE_IMPORT_BUDGET = { maxExpandedBytes: 8 * 1024 ** 3, maxFiles: 100_000 };
8
+ const utf8 = new TextDecoder("utf-8", { fatal: true });
9
+ const text = (bytes) => utf8.decode(bytes.subarray(0, bytes.indexOf(0) < 0 ? bytes.length : bytes.indexOf(0)));
10
+ function number(bytes) {
11
+ const value = text(bytes).trim();
12
+ if (!/^[0-7]*$/.test(value))
13
+ throw new Error("unsupported OCI tar numeric encoding");
14
+ const parsed = parseInt(value || "0", 8);
15
+ if (!Number.isSafeInteger(parsed))
16
+ throw new Error("OCI tar size overflow");
17
+ return parsed;
18
+ }
19
+ function safePath(value) {
20
+ if (!value || Buffer.byteLength(value) > 4096 || value.startsWith("/") || /[\\\0]/.test(value) || value.split("/").some(part => part === ".." || Buffer.byteLength(part) > 255))
21
+ throw new Error("unsafe OCI layer path");
22
+ return path.posix.normalize(value).replace(/\/$/, "");
23
+ }
24
+ /** Inspects an uncompressed tar stream without writing any entry to disk.
25
+ * Supports regular entries, directories, links, PAX metadata and GNU long names.
26
+ * Sparse files and unknown entry/metadata formats fail closed before Docker runs. */
27
+ class TarBudget {
28
+ budget;
29
+ files = 0;
30
+ header = Buffer.alloc(512);
31
+ fill = 0;
32
+ remaining = 0;
33
+ content = 0;
34
+ extension = "";
35
+ metadata = [];
36
+ zeros = 0;
37
+ pending = {};
38
+ paths = new Map();
39
+ parents = new Set();
40
+ constructor(budget) {
41
+ this.budget = budget;
42
+ }
43
+ accept(bytes) {
44
+ let offset = 0;
45
+ while (offset < bytes.length) {
46
+ if (this.remaining) {
47
+ const size = Math.min(this.remaining, bytes.length - offset);
48
+ if (this.extension && this.content)
49
+ this.metadata.push(Buffer.from(bytes.subarray(offset, offset + Math.min(size, this.content))));
50
+ this.content = Math.max(0, this.content - size);
51
+ this.remaining -= size;
52
+ offset += size;
53
+ if (!this.remaining && this.extension)
54
+ this.finishExtension();
55
+ continue;
56
+ }
57
+ const headerBytes = Math.min(512 - this.fill, bytes.length - offset);
58
+ bytes.copy(this.header, this.fill, offset, offset + headerBytes);
59
+ this.fill += headerBytes;
60
+ offset += headerBytes;
61
+ if (this.fill !== 512)
62
+ continue;
63
+ this.fill = 0;
64
+ if (this.header.every(n => n === 0)) {
65
+ this.zeros++;
66
+ continue;
67
+ }
68
+ if (this.zeros)
69
+ throw new Error("OCI tar data after end marker");
70
+ const sum = this.header.reduce((n, byte, i) => n + (i >= 148 && i < 156 ? 32 : byte), 0);
71
+ if (sum !== number(this.header.subarray(148, 156)))
72
+ throw new Error("OCI tar checksum mismatch");
73
+ if (++this.files > this.budget.maxFiles)
74
+ throw new Error("OCI layer entry budget exceeded");
75
+ const type = String.fromCharCode(this.header[156] || 48), rawSize = number(this.header.subarray(124, 136));
76
+ const magic = this.header.subarray(257, 263).toString("latin1");
77
+ if (!["ustar\0", "ustar ", "\0\0\0\0\0\0"].includes(magic))
78
+ throw new Error("unsupported OCI tar header format");
79
+ if (["x", "g", "L", "K"].includes(type)) {
80
+ if (rawSize < 1 || rawSize > 64 * 1024)
81
+ throw new Error("OCI tar metadata budget exceeded");
82
+ this.extension = type;
83
+ this.content = rawSize;
84
+ this.remaining = Math.ceil(rawSize / 512) * 512;
85
+ continue;
86
+ }
87
+ if (!["0", "1", "2", "5"].includes(type))
88
+ throw new Error(`unsupported OCI tar entry type: ${type}`);
89
+ const metadata = this.pending;
90
+ this.pending = {};
91
+ const prefix = magic === "ustar\0" ? text(this.header.subarray(345, 500)) : "", name = safePath(metadata.path ?? `${prefix ? `${prefix}/` : ""}${text(this.header.subarray(0, 100))}`);
92
+ if (name === "." && type !== "5")
93
+ throw new Error("invalid OCI root entry");
94
+ if (this.paths.has(name))
95
+ throw new Error("duplicate OCI layer path");
96
+ if (type !== "5" && this.parents.has(name))
97
+ throw new Error("OCI layer path replaces a parent directory");
98
+ const parts = name.split("/");
99
+ for (let i = 1; i < parts.length; i++) {
100
+ const parentPath = parts.slice(0, i).join("/");
101
+ this.parents.add(parentPath);
102
+ const parent = this.paths.get(parentPath);
103
+ if (parent && parent !== "5")
104
+ throw new Error("OCI layer path traverses a non-directory entry");
105
+ }
106
+ this.paths.set(name, type);
107
+ const size = metadata.size === undefined ? rawSize : Number(metadata.size);
108
+ if (!Number.isSafeInteger(size) || size < 0 || size > this.budget.maxExpandedBytes)
109
+ throw new Error("OCI layer expanded byte budget exceeded");
110
+ if (type !== "0" && size !== 0)
111
+ throw new Error("OCI non-file entry contains data");
112
+ if (type === "1" || type === "2") {
113
+ const target = metadata.linkpath ?? text(this.header.subarray(157, 257));
114
+ if (!target || Buffer.byteLength(target) > 4096 || /[\\\0]/.test(target))
115
+ throw new Error("unsafe OCI layer link");
116
+ if (type === "1")
117
+ safePath(target);
118
+ else {
119
+ // Absolute symlinks are container-root relative. Relative links must
120
+ // stay within that root; no host path is ever opened by this scanner.
121
+ const resolved = path.posix.normalize(target.startsWith("/") ? target.slice(1) : path.posix.join(path.posix.dirname(name), target));
122
+ if (resolved === ".." || resolved.startsWith("../"))
123
+ throw new Error("unsafe OCI layer link escape");
124
+ }
125
+ }
126
+ this.remaining = Math.ceil(size / 512) * 512;
127
+ }
128
+ }
129
+ finishExtension() {
130
+ const bytes = Buffer.concat(this.metadata);
131
+ this.metadata = [];
132
+ const type = this.extension;
133
+ this.extension = "";
134
+ if (type === "L" || type === "K") {
135
+ this.pending[type === "L" ? "path" : "linkpath"] = text(bytes);
136
+ return;
137
+ }
138
+ const values = {};
139
+ for (let offset = 0; offset < bytes.length;) {
140
+ const space = bytes.indexOf(32, offset), lengthText = bytes.subarray(offset, space).toString();
141
+ const length = Number(lengthText);
142
+ if (space < offset || !/^[1-9][0-9]*$/.test(lengthText) || !Number.isSafeInteger(length) || length <= space - offset + 1 || offset + length > bytes.length || bytes[offset + length - 1] !== 10)
143
+ throw new Error("invalid OCI PAX record");
144
+ const value = utf8.decode(bytes.subarray(space + 1, offset + length - 1)), equals = value.indexOf("="), key = value.slice(0, equals);
145
+ if (equals < 1 || Object.hasOwn(values, key))
146
+ throw new Error("invalid OCI PAX key");
147
+ if (!["path", "linkpath", "size", "mtime", "atime", "ctime", "uid", "gid", "uname", "gname", "charset", "comment", "LIBARCHIVE.creationtime"].includes(key) && !key.startsWith("SCHILY.xattr."))
148
+ throw new Error(`unsupported OCI PAX metadata: ${key}`);
149
+ values[key] = value.slice(equals + 1);
150
+ offset += length;
151
+ }
152
+ if (values.size !== undefined && !/^(0|[1-9][0-9]*)$/.test(values.size))
153
+ throw new Error("invalid OCI PAX size");
154
+ if (type === "g") {
155
+ if (["path", "linkpath", "size"].some(key => key in values))
156
+ throw new Error("unsupported OCI global path/size override");
157
+ }
158
+ else
159
+ for (const key of ["path", "linkpath", "size"])
160
+ if (values[key] !== undefined)
161
+ this.pending[key] = values[key];
162
+ }
163
+ finish() {
164
+ if (this.fill || this.remaining || this.zeros < 2 || Object.keys(this.pending).length)
165
+ throw new Error("truncated OCI layer tar");
166
+ }
167
+ }
168
+ export async function validateOciLayer(file, start, size, mediaType, budget, signal) {
169
+ const gzip = ["application/vnd.oci.image.layer.v1.tar+gzip", "application/vnd.docker.image.rootfs.diff.tar.gzip"].includes(mediaType);
170
+ if (!gzip && mediaType !== "application/vnd.oci.image.layer.v1.tar" && mediaType !== "application/vnd.docker.image.rootfs.diff.tar")
171
+ throw new Error(`unsupported OCI layer media type: ${mediaType}`);
172
+ if (!size)
173
+ throw new Error("empty OCI layer blob");
174
+ const parser = new TarBudget(budget), hash = createHash("sha256");
175
+ let expandedBytes = 0;
176
+ // A Writable preserves the parser failure across pipeline teardown on Node 22;
177
+ // throwing from an async-iterator sink can replace it with an AbortError.
178
+ const consume = new Writable({
179
+ write(chunk, _encoding, callback) {
180
+ try {
181
+ signal?.throwIfAborted();
182
+ expandedBytes += chunk.length;
183
+ if (expandedBytes > budget.maxExpandedBytes)
184
+ throw new Error("OCI layer expanded byte budget exceeded");
185
+ hash.update(chunk);
186
+ parser.accept(chunk);
187
+ callback();
188
+ }
189
+ catch (error) {
190
+ callback(error instanceof Error ? error : new Error(String(error)));
191
+ }
192
+ }
193
+ });
194
+ const input = createReadStream(file, { start, end: start + size - 1 });
195
+ if (gzip)
196
+ await pipeline(input, createGunzip(), consume, { signal });
197
+ else
198
+ await pipeline(input, consume, { signal });
199
+ parser.finish();
200
+ return { expandedBytes, files: parser.files, diffId: `sha256:${hash.digest("hex")}` };
201
+ }
202
+ //# sourceMappingURL=oci-layer-validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oci-layer-validation.js","sourceRoot":"","sources":["../../../src/resources/oci-layer-validation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,101 @@
1
+ import { DockerRegistryResolver, resolveRegistryEnvironmentImage } from "../images/index.js";
2
+ import { durableWriteJSON } from "../foundation/index.js";
3
+ import { lstat, mkdir, mkdtemp, readFile, rm } from "node:fs/promises";
4
+ import path from "node:path";
5
+ import { exportRegistryBundle, fetchRegistryManifest, verifyRegistryManifest, importRegistryBundle, validateRegistryBundle, isRegistryBundle } from "./oci-registry-bundle.js";
6
+ import { DEFAULT_IMAGE_IMPORT_BUDGET } from "./oci-layer-validation.js";
7
+ import { DEFAULT_RESOURCE_LIMITS } from "./object-store.js";
8
+ import { sha } from "./protocol.js";
9
+ /** Transport is deliberately separate from the lock and all task identities. */
10
+ export class DockerResourceImageProvider {
11
+ root;
12
+ transport;
13
+ resolver;
14
+ offline;
15
+ imagePolicy;
16
+ budget;
17
+ protocol = "hitch-oci-provider@1";
18
+ constructor(root, transport, resolver = new DockerRegistryResolver({ policy: "cache-first" }), offline = {}, imagePolicy = "cache-first", budget = DEFAULT_RESOURCE_LIMITS) {
19
+ this.root = root;
20
+ this.transport = transport;
21
+ this.resolver = resolver;
22
+ this.offline = offline;
23
+ this.imagePolicy = imagePolicy;
24
+ this.budget = budget;
25
+ if (resolver instanceof DockerRegistryResolver)
26
+ this.resolver = resolver.withBeforePull(async (reference, platform, signal) => {
27
+ const resource = { kind: "oci-image", manifestDigest: sha(reference.split("@")[1]), platform };
28
+ const staging = path.join(root, "store", "benchmark-resources", "staging");
29
+ await mkdir(staging, { recursive: true });
30
+ const temporary = await mkdtemp(path.join(staging, "oci-validation-")), file = path.join(temporary, "bundle");
31
+ try {
32
+ await exportRegistryBundle(resource, reference, file, { maxBytes: Math.min(budget.maxObjectBytes, budget.maxTotalBytes), minFreeBytes: budget.minFreeBytes }, signal);
33
+ const validated = await validateRegistryBundle(resource, file, signal, { maxExpandedBytes: budget.maxTotalBytes, maxFiles: budget.maxFiles });
34
+ await durableWriteJSON(this.proofFile(resource), { manifest: validated.manifest });
35
+ }
36
+ finally {
37
+ await rm(temporary, { recursive: true, force: true });
38
+ }
39
+ });
40
+ }
41
+ proofFile(resource) { return path.join(this.root, "store", "benchmark-resources", "oci-manifests", `${resource.manifestDigest.slice(7)}.json`); }
42
+ async exportArchive(resource, destination, signal, budget) {
43
+ if (this.offline.exportFormat === "docker-archive")
44
+ throw new Error("docker-archive cannot preserve verified manifest and expanded-layer budgets; use registry-bundle");
45
+ const image = await this.resolve(resource, signal);
46
+ return exportRegistryBundle(resource, image.reference, destination, budget ?? { maxBytes: 1024 ** 3, minFreeBytes: 64 * 1024 ** 2 }, signal);
47
+ }
48
+ async validateArchive(resource, source, signal, budget = DEFAULT_IMAGE_IMPORT_BUDGET) {
49
+ if (!await isRegistryBundle(source))
50
+ throw new Error("unvalidated Docker archives are unsupported; import a registry-bundle");
51
+ return (await validateRegistryBundle(resource, source, signal, budget)).usage;
52
+ }
53
+ async importArchive(resource, source, signal, budget = DEFAULT_IMAGE_IMPORT_BUDGET) {
54
+ signal = AbortSignal.any([AbortSignal.timeout(120_000), ...(signal ? [signal] : [])]);
55
+ const reference = this.transport[resource.manifestDigest];
56
+ if (!reference)
57
+ throw new Error("offline OCI transport missing");
58
+ if (await isRegistryBundle(source)) {
59
+ if (!this.offline.registry)
60
+ throw new Error("registry bundle import requires an explicitly configured local offline registry");
61
+ const raw = await importRegistryBundle(resource, source, reference, this.offline.registry, signal, budget);
62
+ await durableWriteJSON(this.proofFile(resource), { manifest: raw });
63
+ // Only the explicitly configured loopback registry is contacted here.
64
+ // Normal execution remains cache-only and uses the exact original digest.
65
+ await new DockerRegistryResolver({ policy: "registry" }).resolve(reference, resource.platform, signal);
66
+ }
67
+ else
68
+ throw new Error("unvalidated Docker archives are unsupported; import a registry-bundle");
69
+ await new DockerRegistryResolver({ policy: "cache-only" }).resolve(reference, resource.platform, signal);
70
+ }
71
+ async resolve(resource, signal) {
72
+ signal = AbortSignal.any([AbortSignal.timeout(120_000), ...(signal ? [signal] : [])]);
73
+ if (resource.indexDigest)
74
+ throw new Error("this OCI provider does not support index membership verification; supply a platform manifest without an index lock");
75
+ const reference = this.transport[resource.manifestDigest];
76
+ if (!reference || !reference.endsWith(`@${resource.manifestDigest}`) || /[\s\0]/.test(reference))
77
+ throw new Error("immutable OCI resource transport is missing or mismatched");
78
+ const { manifest } = await resolveRegistryEnvironmentImage({ root: this.root, benchmarkId: "benchmark-resource", benchmarkRevision: resource.manifestDigest,
79
+ reference, platform: resource.platform, resolver: this.resolver, ...(signal ? { signal } : {}) });
80
+ if (!manifest.output.config_digest)
81
+ throw new Error("OCI resource provider must verify the config digest");
82
+ const file = this.proofFile(resource), info = await lstat(file).catch(e => { if (e.code !== "ENOENT")
83
+ throw e; return undefined; });
84
+ let raw;
85
+ if (info) {
86
+ if (!info.isFile() || info.size > 4 * 1024 ** 2)
87
+ throw new Error("invalid cached OCI manifest proof");
88
+ raw = JSON.parse(await readFile(file, "utf8")).manifest;
89
+ }
90
+ else {
91
+ if (this.imagePolicy === "cache-only")
92
+ throw new Error("cache-only OCI manifest proof missing; import a registry bundle or verify the image online first");
93
+ raw = await fetchRegistryManifest(resource, reference, signal);
94
+ }
95
+ verifyRegistryManifest(raw, resource, manifest.output.config_digest);
96
+ if (!info)
97
+ await durableWriteJSON(file, { manifest: raw });
98
+ return { imageId: manifest.image_id, manifestDigest: manifest.output.manifest_digest, configDigest: manifest.output.config_digest, platform: manifest.platform, reference: manifest.output.reference };
99
+ }
100
+ }
101
+ //# sourceMappingURL=oci-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oci-provider.js","sourceRoot":"","sources":["../../../src/resources/oci-provider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,253 @@
1
+ import { createHash } from "node:crypto";
2
+ import { createReadStream } from "node:fs";
3
+ import { open, rm, statfs } from "node:fs/promises";
4
+ import path from "node:path";
5
+ import { canonical, hash, natural, object, parseStrictJson, sha } from "./protocol.js";
6
+ import { DEFAULT_IMAGE_IMPORT_BUDGET, validateOciLayer } from "./oci-layer-validation.js";
7
+ // Exact registry bytes, not a tar extraction or a reconstructed manifest.
8
+ // API: https://distribution.github.io/distribution/spec/api/
9
+ const MAGIC = Buffer.from("HITCH-OCI-REGISTRY-1\n"), MAX_HEADER = 4 * 1024 ** 2;
10
+ const ACCEPT = "application/vnd.oci.image.manifest.v1+json, application/vnd.docker.distribution.manifest.v2+json";
11
+ const FETCH_ACCEPT = `${ACCEPT}, application/vnd.oci.image.index.v1+json, application/vnd.docker.distribution.manifest.list.v2+json`;
12
+ export function registryLocation(reference) {
13
+ const [name, digest] = reference.split("@");
14
+ sha(digest);
15
+ const components = name.split("/"), explicit = /[.:]/.test(components[0]) || components[0] === "localhost";
16
+ const host = explicit ? components.shift() : "registry-1.docker.io";
17
+ if (components.length === 1 && !explicit)
18
+ components.unshift("library");
19
+ const repository = components.join("/");
20
+ if (!/^[a-z0-9]+(?:[._-][a-z0-9]+)*(?:\/[a-z0-9]+(?:[._-][a-z0-9]+)*)*$/.test(repository))
21
+ throw new Error("invalid registry repository");
22
+ const local = /^(localhost|127\.0\.0\.1)(:\d+)?$/.test(host);
23
+ return { origin: `${local ? "http" : "https"}://${host === "docker.io" ? "registry-1.docker.io" : host}`, repository, digest: digest };
24
+ }
25
+ export function localRegistry(value) {
26
+ const url = new URL(value);
27
+ if (!["localhost", "127.0.0.1", "[::1]"].includes(url.hostname) || !["http:", "https:"].includes(url.protocol) || url.username || url.password || url.pathname !== "/" || url.search || url.hash)
28
+ throw new Error("offline registry must be an explicitly configured loopback origin");
29
+ return url;
30
+ }
31
+ async function boundedBody(response, maximum) {
32
+ if (!response.ok || !response.body)
33
+ throw new Error(`OCI registry request failed: HTTP ${response.status}`);
34
+ const chunks = [];
35
+ let size = 0;
36
+ for await (const chunk of response.body) {
37
+ size += chunk.length;
38
+ if (size > maximum)
39
+ throw new Error("OCI response byte budget exceeded");
40
+ chunks.push(chunk);
41
+ }
42
+ return Buffer.concat(chunks);
43
+ }
44
+ function descriptors(manifest, image) {
45
+ if (hash(manifest) !== image.manifestDigest)
46
+ throw new Error("offline OCI manifest digest mismatch");
47
+ const m = parseStrictJson(manifest);
48
+ if (m.schemaVersion !== 2 || !Array.isArray(m.layers) || !ACCEPT.split(", ").includes(String(m.mediaType)))
49
+ throw new Error("offline registry format requires a platform image manifest, not an index");
50
+ const parse = (v) => { const d = v; if (!d || typeof d !== "object" || d.urls !== undefined)
51
+ throw new Error("foreign OCI blobs are unsupported"); return { digest: sha(d.digest), size: natural(d.size) }; };
52
+ const layers = m.layers.map(v => ({ ...parse(v), mediaType: String(v.mediaType) }));
53
+ const config = parse(m.config), entries = [config, ...layers], unique = new Map();
54
+ for (const e of entries) {
55
+ if (unique.has(e.digest) && unique.get(e.digest).size !== e.size)
56
+ throw new Error("conflicting OCI descriptor sizes");
57
+ unique.set(e.digest, e);
58
+ }
59
+ return { blobs: [...unique.values()].map(({ digest, size }) => ({ digest, size })).sort((a, b) => a.digest.localeCompare(b.digest)), layers, mediaType: String(m.mediaType), config };
60
+ }
61
+ async function registryReader(reference, signal) {
62
+ const location = registryLocation(reference);
63
+ let token;
64
+ return async (suffix, accept) => {
65
+ const url = `${location.origin}/v2/${location.repository}/${suffix}`;
66
+ const request = () => fetch(url, { signal, headers: { ...(accept ? { accept } : {}), ...(token ? { authorization: `Bearer ${token}` } : {}) } });
67
+ let response = await request();
68
+ if (response.status === 401 && !token) {
69
+ const challenge = response.headers.get("www-authenticate") ?? "";
70
+ await response.body?.cancel();
71
+ const realm = challenge.match(/realm="([^"]+)"/)?.[1], service = challenge.match(/service="([^"]+)"/)?.[1];
72
+ if (!challenge.startsWith("Bearer ") || !realm)
73
+ throw new Error("registry bundle export supports anonymous bearer authentication only");
74
+ const auth = new URL(realm);
75
+ if (auth.protocol !== "https:" || auth.username || auth.password)
76
+ throw new Error("unsafe registry authentication endpoint");
77
+ if (service)
78
+ auth.searchParams.set("service", service);
79
+ auth.searchParams.set("scope", `repository:${location.repository}:pull`);
80
+ const value = parseStrictJson((await boundedBody(await fetch(auth, { signal }), 64 * 1024)).toString());
81
+ token = typeof value.token === "string" ? value.token : typeof value.access_token === "string" ? value.access_token : undefined;
82
+ if (!token)
83
+ throw new Error("registry authentication unavailable");
84
+ response = await request();
85
+ }
86
+ if (!response.ok) {
87
+ await response.body?.cancel();
88
+ throw new Error(`OCI registry request failed: HTTP ${response.status}`);
89
+ }
90
+ return response;
91
+ };
92
+ }
93
+ export async function fetchRegistryManifest(image, reference, signal) {
94
+ const bounded = AbortSignal.any([AbortSignal.timeout(30_000), ...(signal ? [signal] : [])]);
95
+ const get = await registryReader(reference, bounded), manifest = (await boundedBody(await get(`manifests/${image.manifestDigest}`, FETCH_ACCEPT), MAX_HEADER)).toString();
96
+ descriptors(manifest, image);
97
+ return manifest;
98
+ }
99
+ export function verifyRegistryManifest(manifest, image, configDigest) {
100
+ if (descriptors(manifest, image).config.digest !== configDigest)
101
+ throw new Error("OCI manifest config differs from actual Docker image");
102
+ }
103
+ export async function exportRegistryBundle(image, reference, file, budget, signal) {
104
+ const bounded = AbortSignal.any([AbortSignal.timeout(120_000), ...(signal ? [signal] : [])]);
105
+ const get = await registryReader(reference, bounded), manifest = (await boundedBody(await get(`manifests/${image.manifestDigest}`, FETCH_ACCEPT), MAX_HEADER)).toString();
106
+ const { blobs } = descriptors(manifest, image), header = Buffer.from(JSON.stringify({ protocol: "hitch-oci-registry-bundle@1", manifest, blobs })), length = Buffer.alloc(4);
107
+ length.writeUInt32BE(header.length);
108
+ const total = MAGIC.length + 4 + header.length + blobs.reduce((n, b) => n + b.size, 0);
109
+ if (header.length > MAX_HEADER || total > budget.maxBytes)
110
+ throw new Error("offline OCI archive budget exceeded");
111
+ const space = await statfs(path.dirname(file), { bigint: true });
112
+ if (space.bavail * space.bsize < BigInt(total + budget.minFreeBytes))
113
+ throw new Error("offline OCI free-space reserve exceeded");
114
+ const output = await open(file, "wx", 0o600);
115
+ try {
116
+ await output.writeFile(Buffer.concat([MAGIC, length, header]));
117
+ for (const blob of blobs) {
118
+ let size = 0;
119
+ const digest = createHash("sha256"), response = await get(`blobs/${blob.digest}`);
120
+ for await (const chunk of response.body) {
121
+ bounded.throwIfAborted();
122
+ size += chunk.length;
123
+ if (size > blob.size)
124
+ throw new Error("OCI blob exceeds its manifest size");
125
+ digest.update(chunk);
126
+ await output.writeFile(chunk);
127
+ }
128
+ if (size !== blob.size || `sha256:${digest.digest("hex")}` !== blob.digest)
129
+ throw new Error("OCI blob integrity mismatch");
130
+ }
131
+ await output.sync();
132
+ }
133
+ catch (error) {
134
+ await rm(file, { force: true });
135
+ throw error;
136
+ }
137
+ finally {
138
+ await output.close();
139
+ }
140
+ }
141
+ export async function isRegistryBundle(file) {
142
+ const handle = await open(file, "r");
143
+ try {
144
+ const buffer = Buffer.alloc(MAGIC.length);
145
+ await handle.read(buffer, 0, buffer.length, 0);
146
+ return buffer.equals(MAGIC);
147
+ }
148
+ finally {
149
+ await handle.close();
150
+ }
151
+ }
152
+ /** Validates digests, expanded bytes, entry counts and tar paths without extraction. */
153
+ export async function validateRegistryBundle(image, file, signal, budget = DEFAULT_IMAGE_IMPORT_BUDGET) {
154
+ natural(budget.maxExpandedBytes);
155
+ natural(budget.maxFiles);
156
+ const bounded = AbortSignal.any([AbortSignal.timeout(120_000), ...(signal ? [signal] : [])]), handle = await open(file, "r");
157
+ let manifest, blobs, layers, mediaType, config, offset;
158
+ try {
159
+ const prefix = Buffer.alloc(MAGIC.length + 4);
160
+ await handle.read(prefix, 0, prefix.length, 0);
161
+ const length = prefix.readUInt32BE(MAGIC.length);
162
+ if (!prefix.subarray(0, MAGIC.length).equals(MAGIC) || length > MAX_HEADER)
163
+ throw new Error("invalid OCI bundle header");
164
+ const header = Buffer.alloc(length);
165
+ if ((await handle.read(header, 0, length, prefix.length)).bytesRead !== length)
166
+ throw new Error("truncated OCI header");
167
+ const raw = object(parseStrictJson(header.toString()), ["protocol", "manifest", "blobs"]);
168
+ if (raw.protocol !== "hitch-oci-registry-bundle@1" || typeof raw.manifest !== "string")
169
+ throw new Error("invalid OCI bundle protocol");
170
+ manifest = raw.manifest;
171
+ ({ blobs, layers, mediaType, config } = descriptors(manifest, image));
172
+ if (canonical(raw.blobs) !== canonical(blobs))
173
+ throw new Error("OCI bundle inventory mismatch");
174
+ offset = prefix.length + length;
175
+ if ((await handle.stat()).size !== offset + blobs.reduce((n, b) => n + b.size, 0))
176
+ throw new Error("OCI bundle size mismatch");
177
+ }
178
+ finally {
179
+ await handle.close();
180
+ }
181
+ let position = offset;
182
+ const positions = new Map();
183
+ let diffIds = [];
184
+ for (const blob of blobs) {
185
+ positions.set(blob.digest, position);
186
+ const digest = createHash("sha256"), chunks = [];
187
+ if (blob.size)
188
+ for await (const chunk of createReadStream(file, { start: position, end: position + blob.size - 1 })) {
189
+ bounded.throwIfAborted();
190
+ digest.update(chunk);
191
+ if (blob.digest === config.digest) {
192
+ if (blob.size > MAX_HEADER)
193
+ throw new Error("OCI config size budget exceeded");
194
+ chunks.push(chunk);
195
+ }
196
+ }
197
+ if (`sha256:${digest.digest("hex")}` !== blob.digest)
198
+ throw new Error("offline OCI blob digest mismatch");
199
+ if (blob.digest === config.digest) {
200
+ const c = parseStrictJson(Buffer.concat(chunks).toString());
201
+ if (`${c.os}/${c.architecture}${c.variant ? `/${c.variant}` : ""}` !== image.platform)
202
+ throw new Error("offline OCI config platform mismatch");
203
+ const rootfs = c.rootfs;
204
+ if (!rootfs || rootfs.type !== "layers" || !Array.isArray(rootfs.diff_ids) || rootfs.diff_ids.length !== layers.length)
205
+ throw new Error("offline OCI config layer inventory mismatch");
206
+ diffIds = rootfs.diff_ids.map(sha);
207
+ }
208
+ position += blob.size;
209
+ }
210
+ const usage = { expandedBytes: 0, files: 0 };
211
+ for (const [i, layer] of layers.entries()) {
212
+ const observed = await validateOciLayer(file, positions.get(layer.digest), layer.size, layer.mediaType, { maxExpandedBytes: budget.maxExpandedBytes - usage.expandedBytes, maxFiles: budget.maxFiles - usage.files }, bounded);
213
+ if (observed.diffId !== diffIds[i])
214
+ throw new Error("offline OCI uncompressed layer digest mismatch");
215
+ usage.expandedBytes += observed.expandedBytes;
216
+ usage.files += observed.files;
217
+ }
218
+ return { manifest: manifest, blobs: blobs, mediaType: mediaType, offset: offset, usage };
219
+ }
220
+ /** Validates every layer before any local registry or Docker mutation. */
221
+ export async function importRegistryBundle(image, file, reference, registry, signal, budget = DEFAULT_IMAGE_IMPORT_BUDGET) {
222
+ const origin = localRegistry(registry), location = registryLocation(reference);
223
+ if (new URL(location.origin).host !== origin.host)
224
+ throw new Error("offline image transport must name the configured local registry");
225
+ const bounded = AbortSignal.any([AbortSignal.timeout(120_000), ...(signal ? [signal] : [])]);
226
+ const { manifest, blobs, mediaType, offset } = await validateRegistryBundle(image, file, bounded, budget);
227
+ let position = offset;
228
+ const api = `${origin.origin}/v2/${location.repository}`;
229
+ for (const blob of blobs) {
230
+ const head = await fetch(`${api}/blobs/${blob.digest}`, { method: "HEAD", signal: bounded, redirect: "error" });
231
+ if (head.status !== 200) {
232
+ if (head.status !== 404)
233
+ throw new Error(`offline registry probe failed: ${head.status}`);
234
+ const start = await fetch(`${api}/blobs/uploads/`, { method: "POST", signal: bounded, redirect: "error" });
235
+ await start.body?.cancel();
236
+ const upload = new URL(start.headers.get("location") ?? "", api);
237
+ if (start.status !== 202 || upload.origin !== origin.origin || !upload.pathname.startsWith(`/v2/${location.repository}/blobs/uploads/`))
238
+ throw new Error("unsafe local registry upload location");
239
+ upload.searchParams.set("digest", blob.digest);
240
+ const response = await fetch(upload, { method: "PUT", signal: bounded, redirect: "error", headers: { "content-type": "application/octet-stream", "content-length": String(blob.size) }, body: blob.size ? createReadStream(file, { start: position, end: position + blob.size - 1 }) : Buffer.alloc(0), duplex: "half" });
241
+ await response.body?.cancel();
242
+ if (response.status !== 201)
243
+ throw new Error(`offline registry blob upload failed: ${response.status}`);
244
+ }
245
+ position += blob.size;
246
+ }
247
+ const result = await fetch(`${api}/manifests/${image.manifestDigest}`, { method: "PUT", signal: bounded, redirect: "error", headers: { "content-type": mediaType }, body: manifest });
248
+ await result.body?.cancel();
249
+ if (result.status !== 201)
250
+ throw new Error(`offline registry manifest publication failed: ${result.status}`);
251
+ return manifest;
252
+ }
253
+ //# sourceMappingURL=oci-registry-bundle.js.map