@lapxo/bound 0.2.4 → 0.2.6

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 (333) hide show
  1. package/CITATION.cff +1 -1
  2. package/README.md +20 -3
  3. package/TARGET.bound +85 -47
  4. package/dist/cli/accept.js +61 -590
  5. package/dist/cli/act-result.js +3 -103
  6. package/dist/cli/args.js +3 -44
  7. package/dist/cli/custodian.js +2 -29
  8. package/dist/cli/host.js +4 -32
  9. package/dist/cli/names.js +1 -12
  10. package/dist/cli/native-descendant.js +1 -19
  11. package/dist/cli/native.js +3 -60
  12. package/dist/cli/observe.js +1 -13
  13. package/dist/cli/owner.js +3 -139
  14. package/dist/cli/pass.js +22 -321
  15. package/dist/cli/place.js +6 -282
  16. package/dist/cli/release-result.js +3 -80
  17. package/dist/cli/retained-judgment.js +1 -25
  18. package/dist/cli/standing-result.js +4 -19
  19. package/dist/cli/takes.js +10 -112
  20. package/dist/cli/verb.d.ts +1 -2
  21. package/dist/cli/verb.js +85 -684
  22. package/dist/engine/computation.js +2 -0
  23. package/dist/engine/conformance.js +4 -0
  24. package/dist/engine/encoding.js +1 -2
  25. package/dist/engine/index.d.ts +1 -13
  26. package/dist/engine/index.js +2 -11
  27. package/dist/engine/object.js +1 -38
  28. package/dist/engine/ports.js +2 -117
  29. package/dist/fold/admission-history.js +1 -17
  30. package/dist/fold/bootstrap-anchor.js +1 -28
  31. package/dist/fold/ceilings.js +1 -142
  32. package/dist/fold/claims.js +2 -132
  33. package/dist/fold/closed.js +24 -235
  34. package/dist/fold/configures.js +1 -25
  35. package/dist/fold/digests.js +10 -226
  36. package/dist/fold/evidence.js +1 -22
  37. package/dist/fold/fold-worker.js +1 -13
  38. package/dist/fold/kept.js +12 -173
  39. package/dist/fold/keys.js +3 -91
  40. package/dist/fold/laid.js +3 -90
  41. package/dist/fold/nos.js +1 -48
  42. package/dist/fold/object.js +1 -2
  43. package/dist/fold/observed.js +28 -534
  44. package/dist/fold/opened.js +1 -33
  45. package/dist/fold/own.js +3 -217
  46. package/dist/fold/paid.js +1 -92
  47. package/dist/fold/place-inputs.js +1 -70
  48. package/dist/fold/places.js +3 -100
  49. package/dist/fold/rank.js +1 -9
  50. package/dist/fold/reach.js +1 -83
  51. package/dist/fold/readers.js +6 -142
  52. package/dist/fold/receipts.js +1 -47
  53. package/dist/fold/region-declarations.js +1 -13
  54. package/dist/fold/region.js +8 -286
  55. package/dist/fold/release-policy.js +1 -101
  56. package/dist/fold/resolved.js +6 -145
  57. package/dist/fold/roles.js +2 -59
  58. package/dist/fold/second.js +4 -71
  59. package/dist/fold/shards.js +12 -100
  60. package/dist/fold/signed.js +3 -81
  61. package/dist/fold/signers.js +1 -54
  62. package/dist/fold/stranger.js +6 -24
  63. package/dist/fold/views.js +1 -66
  64. package/dist/fold/wire.js +1 -46
  65. package/dist/fold/zoom.js +3 -81
  66. package/dist/host/act-cost.js +1 -25
  67. package/dist/host/adapters/keys/ed25519.js +1 -30
  68. package/dist/host/adapters/modules/javascript.js +1 -50
  69. package/dist/host/adapters/transport/http.js +1 -28
  70. package/dist/host/admitted-place.js +1 -35
  71. package/dist/host/archive.js +1 -152
  72. package/dist/host/call-context.js +1 -14
  73. package/dist/host/capsule-process.js +2 -62
  74. package/dist/host/capsule.js +9 -171
  75. package/dist/host/cell-receipts.js +12 -128
  76. package/dist/host/command-server.js +4 -0
  77. package/dist/host/commit-result.js +1 -5
  78. package/dist/host/content-needed.js +1 -8
  79. package/dist/host/content-store.js +1 -31
  80. package/dist/host/contextual-place.js +2 -72
  81. package/dist/host/digest.js +2 -15
  82. package/dist/host/hash.js +1 -9
  83. package/dist/host/host-controls.js +1 -19
  84. package/dist/host/in-process-act.js +3 -84
  85. package/dist/host/in-process-context.js +3 -91
  86. package/dist/host/in-process-root.js +6 -84
  87. package/dist/host/in-process.js +4 -55
  88. package/dist/host/index.d.ts +1 -15
  89. package/dist/host/index.js +1 -7
  90. package/dist/host/io.js +1 -11
  91. package/dist/host/lifetime.js +1 -79
  92. package/dist/host/located.js +6 -105
  93. package/dist/host/native/authority-card-view.js +5 -0
  94. package/dist/host/native/authority-card.js +1 -0
  95. package/dist/host/native/bounded-file.js +1 -32
  96. package/dist/host/native/command.js +1 -91
  97. package/dist/host/native/control-bridge-worker.js +2 -88
  98. package/dist/host/native/control-bridge.js +1 -110
  99. package/dist/host/native/control-selection.js +1 -32
  100. package/dist/host/native/custody.js +1 -91
  101. package/dist/host/native/deadline.js +1 -28
  102. package/dist/host/native/descendants.js +1 -528
  103. package/dist/host/native/generated-custodian.js +5 -267
  104. package/dist/host/native/generated.js +1 -379
  105. package/dist/host/native/image.js +1 -45
  106. package/dist/host/native/installed-package.d.ts +1 -0
  107. package/dist/host/native/installed-package.js +5 -0
  108. package/dist/host/native/jobs.js +2 -148
  109. package/dist/host/native/loader.js +1 -269
  110. package/dist/host/native/materialize.js +1 -175
  111. package/dist/host/native/module-closure.js +1 -130
  112. package/dist/host/native/module-delivery.d.ts +1 -62
  113. package/dist/host/native/module-delivery.js +1 -151
  114. package/dist/host/native/module-inventory.js +2 -0
  115. package/dist/host/native/module-syntax.js +1 -69
  116. package/dist/host/native/native-binary.js +1 -115
  117. package/dist/host/native/native-program.js +1 -72
  118. package/dist/host/native/node-jobs.js +3 -187
  119. package/dist/host/native/node-launch.js +1 -159
  120. package/dist/host/native/preload.js +1 -45
  121. package/dist/host/native/probes.js +1 -0
  122. package/dist/host/native/reading-witness-admission.js +5 -0
  123. package/dist/host/native/reading.js +1 -249
  124. package/dist/host/native/receipt-environment.js +1 -41
  125. package/dist/host/native/references.js +1 -30
  126. package/dist/host/native/root.js +1 -37
  127. package/dist/host/native/route.js +1 -216
  128. package/dist/host/native/runtime.js +1 -9
  129. package/dist/host/native-place-state.js +1 -0
  130. package/dist/host/native-reader-context.js +1 -8
  131. package/dist/host/native-receiver.js +1 -25
  132. package/dist/host/objects.js +1 -38
  133. package/dist/host/order.js +1 -2
  134. package/dist/host/persistent-host.js +1 -0
  135. package/dist/host/physical-lines.d.ts +1 -0
  136. package/dist/host/physical-lines.js +1 -0
  137. package/dist/host/place-act-transaction.js +4 -78
  138. package/dist/host/place-clock-selection.js +5 -124
  139. package/dist/host/ports/ingress.js +2 -57
  140. package/dist/host/ports/local-act.js +5 -183
  141. package/dist/host/ports/place-act.js +1 -134
  142. package/dist/host/ports/publication.js +1 -56
  143. package/dist/host/ports/signing.js +1 -74
  144. package/dist/host/ports/store.js +1 -18
  145. package/dist/host/ports/transport.js +1 -48
  146. package/dist/host/process-lifetime.js +1 -17
  147. package/dist/host/profile-composition.d.ts +1 -0
  148. package/dist/host/profile-composition.js +2 -0
  149. package/dist/host/provide.js +1 -183
  150. package/dist/host/read-only.js +1 -9
  151. package/dist/host/reading-closures.js +7 -227
  152. package/dist/host/reading-context.js +1 -53
  153. package/dist/host/reading-identity-types.js +0 -0
  154. package/dist/host/reading-identity.js +3 -0
  155. package/dist/host/reading-preparation.js +6 -0
  156. package/dist/host/reference-authenticated.d.ts +1 -40
  157. package/dist/host/reference-authenticated.js +3 -100
  158. package/dist/host/reference-contracts.js +1 -6
  159. package/dist/host/reference-export.js +6 -81
  160. package/dist/host/reference-native-api.d.ts +1 -3
  161. package/dist/host/reference-native-api.js +1 -3
  162. package/dist/host/reference-native.js +1 -74
  163. package/dist/host/reference-profile.js +1 -63
  164. package/dist/host/reference-standing.js +2 -18
  165. package/dist/host/reference.js +1 -24
  166. package/dist/host/refusals.js +2 -43
  167. package/dist/host/release.js +4 -256
  168. package/dist/host/root-clock-source.js +1 -307
  169. package/dist/host/selected-capsules.js +1 -50
  170. package/dist/host/selected-topos.js +1 -80
  171. package/dist/host/signature-era.js +1 -12
  172. package/dist/host/signing.js +2 -48
  173. package/dist/host/source-content.js +2 -111
  174. package/dist/host/standing-carrier.js +1 -18
  175. package/dist/host/standing-projection.js +1 -50
  176. package/dist/host/timing.js +1 -7
  177. package/dist/host/walk.js +20 -193
  178. package/dist/host/work-trace.js +1 -0
  179. package/dist/judge/late.js +1 -33
  180. package/dist/judge/take.js +2 -75
  181. package/dist/judge/widening.js +1 -25
  182. package/dist/land/act.js +8 -336
  183. package/dist/land/alias.js +1 -41
  184. package/dist/land/held.js +1 -23
  185. package/dist/land/inert.js +1 -33
  186. package/dist/land/leaving.js +1 -55
  187. package/dist/land/ledger.js +6 -188
  188. package/dist/land/owned.js +4 -66
  189. package/dist/land/sign.js +1 -53
  190. package/dist/land/standing-pin.js +1 -49
  191. package/dist/land/vouched.js +1 -112
  192. package/dist/land/withdraw.js +1 -24
  193. package/dist/observe/files.js +1 -88
  194. package/dist/observe/identity.js +1 -61
  195. package/dist/observe/match.js +1 -8
  196. package/dist/observe/regions.js +7 -306
  197. package/dist/observe/run.js +1 -41
  198. package/dist/observe/runner.js +4 -101
  199. package/dist/public-types.d.ts +2019 -0
  200. package/dist/render/capsule.js +1 -30
  201. package/dist/render/field.js +1 -40
  202. package/dist/render/names.js +1 -4
  203. package/dist/render/open.js +1 -61
  204. package/dist/render/page.js +1 -7
  205. package/dist/render/receipt-projection.js +1 -0
  206. package/dist/render/receipts.js +1 -47
  207. package/dist/render/shape.js +1 -74
  208. package/dist/render/target.js +4 -52
  209. package/dist/render/view.js +7 -197
  210. package/dist/vendor/bundle.json +1 -0
  211. package/dist/vendor/library14.js +1 -0
  212. package/dist/vendor/object-provider.js +42 -0
  213. package/dist/vendor/runtime.js +61 -0
  214. package/dist/wasm/adapter.d.ts +1 -51
  215. package/dist/wasm/adapter.js +1 -180
  216. package/dist/wasm/node-worker.js +1 -13
  217. package/dist/wasm/object.js +1 -76
  218. package/dist/wasm/worker.js +1 -7
  219. package/docs/contracts/authenticated-reference.publication.json +1 -1
  220. package/docs/contracts/authority-preflight.md +17 -0
  221. package/docs/contracts/authority-preflight.publication.json +25 -0
  222. package/docs/contracts/closure-delivery.md +1 -1
  223. package/docs/contracts/closure-delivery.publication.json +1 -1
  224. package/docs/contracts/conformance.json +142 -0
  225. package/docs/contracts/determinism.bound +9 -0
  226. package/docs/contracts/engine-object-projection.publication.json +1 -1
  227. package/docs/contracts/engine.md +21 -1
  228. package/docs/contracts/installed-package.md +21 -0
  229. package/docs/contracts/installed-package.publication.json +25 -0
  230. package/docs/contracts/materialized-leaf-sequence.md +15 -0
  231. package/docs/contracts/materialized-leaf-sequence.publication.json +25 -0
  232. package/docs/contracts/module-inventory.md +15 -0
  233. package/docs/contracts/module-inventory.publication.json +25 -0
  234. package/docs/contracts/native-host.md +29 -1
  235. package/docs/contracts/native-host.publication.json +4 -4
  236. package/docs/contracts/native-probes.md +13 -0
  237. package/docs/contracts/native-probes.publication.json +25 -0
  238. package/docs/contracts/native-publication.inventory.json +10 -1
  239. package/docs/contracts/native-view-batch.md +17 -0
  240. package/docs/contracts/native-view-batch.publication.json +25 -0
  241. package/docs/contracts/optional-wasm-adapter.publication.json +1 -1
  242. package/docs/contracts/physical-lines.md +19 -0
  243. package/docs/contracts/physical-lines.publication.json +25 -0
  244. package/docs/contracts/profile-composition.md +17 -0
  245. package/docs/contracts/profile-composition.publication.json +25 -0
  246. package/docs/contracts/profile-preparation-native-meaning.md +9 -0
  247. package/docs/contracts/publication.md +12 -0
  248. package/docs/contracts/reading-identity.md +61 -0
  249. package/docs/contracts/reading-identity.publication.json +25 -0
  250. package/docs/contracts/reading-witness-admission.md +49 -0
  251. package/docs/contracts/readme.publication.json +1 -1
  252. package/docs/contracts/reference-port.md +11 -0
  253. package/docs/contracts/reference-port.publication.json +1 -1
  254. package/docs/contracts/refusals.bound +346 -94
  255. package/docs/contracts/refusals.md +119 -39
  256. package/docs/contracts/refusals.publication.json +2 -2
  257. package/docs/contracts/views.md +8 -0
  258. package/docs/reference.md +9 -0
  259. package/licenses/wasm/{fast-text-encoding.txt → NOTICE.txt} +111 -0
  260. package/package.json +84 -34
  261. package/receipts.bound +12952 -10449
  262. package/samples/authority-preflight/no.json +6 -0
  263. package/samples/authority-preflight/yes.json +30 -0
  264. package/samples/engine-alphabet/reader.js +3 -1457
  265. package/samples/engine-alphabet/receipts.bound +7 -7
  266. package/samples/engine-interval/reader.js +3 -1457
  267. package/samples/engine-interval/receipts.bound +7 -7
  268. package/samples/installed-package/consumer.mjs +29 -0
  269. package/samples/installed-package/fixture.json +48 -0
  270. package/samples/installed-package/no.json +10 -0
  271. package/samples/installed-package/yes.json +52 -0
  272. package/samples/materialized-leaf-sequence/no.json +11 -0
  273. package/samples/materialized-leaf-sequence/yes.json +10 -0
  274. package/samples/module-inventory/yes.json +28 -0
  275. package/samples/native/physical-line-reader.mjs +1 -0
  276. package/samples/native/physical-line-reader.source.mjs +13 -0
  277. package/samples/native-host/no.json +6 -1
  278. package/samples/native-host/yes.json +18 -1
  279. package/samples/native-probes/inputs/inspection.json +28 -0
  280. package/samples/native-probes/no.json +7 -0
  281. package/samples/native-probes/yes.json +28 -0
  282. package/samples/native-view-batch/no.json +14 -0
  283. package/samples/native-view-batch/yes.json +10 -0
  284. package/samples/no/engine-order/reader.js +3 -1457
  285. package/samples/no/module-inventory/no.json +10 -0
  286. package/samples/physical-lines/no.json +5 -0
  287. package/samples/physical-lines/yes.json +9 -0
  288. package/samples/profile-composition/no.json +6 -0
  289. package/samples/profile-composition/yes.json +14 -0
  290. package/samples/reading-identity/no.json +26 -0
  291. package/samples/reading-identity/yes.json +69 -0
  292. package/vectors/native/authority-preflight.vector.json +55 -0
  293. package/vectors/native/installed-package.vector.json +31 -0
  294. package/vectors/native/materialized-leaf-sequence.vector.json +31 -0
  295. package/vectors/native/module-inventory.vector.json +56 -0
  296. package/vectors/native/native-host.vector.json +214 -0
  297. package/vectors/native/native-probes.vector.json +31 -0
  298. package/vectors/native/native-view-batch.vector.json +31 -0
  299. package/vectors/native/physical-lines.vector.json +105 -0
  300. package/vectors/native/profile-composition.vector.json +53 -0
  301. package/vectors/native/reading-identity.vector.json +139 -0
  302. package/vectors/native/refusals.vector.json +138 -0
  303. package/vendor/syntax/LICENSE.md +7 -0
  304. package/vendor/syntax/parser.js +1 -0
  305. package/.github/workflows/release.yml +0 -67
  306. package/.github/workflows/test.yml +0 -35
  307. package/dist/engine/object.d.ts +0 -17
  308. package/dist/engine/ports.d.ts +0 -37
  309. package/dist/fold/claims.d.ts +0 -29
  310. package/dist/host/call-context.d.ts +0 -20
  311. package/dist/host/commit-result.d.ts +0 -6
  312. package/dist/host/in-process-act.d.ts +0 -82
  313. package/dist/host/in-process-context.d.ts +0 -46
  314. package/dist/host/in-process-root.d.ts +0 -117
  315. package/dist/host/in-process.d.ts +0 -41
  316. package/dist/host/native/module-closure.d.ts +0 -35
  317. package/dist/host/native-receiver.d.ts +0 -19
  318. package/dist/host/place-act-transaction.d.ts +0 -24
  319. package/dist/host/place-clock-selection.d.ts +0 -55
  320. package/dist/host/ports/local-act.d.ts +0 -44
  321. package/dist/host/ports/place-act.d.ts +0 -49
  322. package/dist/host/ports/publication.d.ts +0 -10
  323. package/dist/host/reference-export.d.ts +0 -33
  324. package/dist/host/reference-native.d.ts +0 -30
  325. package/dist/host/reference-profile.d.ts +0 -23
  326. package/dist/host/refusals.d.ts +0 -14
  327. package/dist/host/root-clock-source.d.ts +0 -86
  328. package/licenses/wasm/jitl-quickjs-ffi-types.txt +0 -21
  329. package/licenses/wasm/jitl-quickjs-wasmfile-release-sync.txt +0 -47
  330. package/licenses/wasm/quickjs-emscripten-core.txt +0 -21
  331. package/licenses/wasm/topos.txt +0 -21
  332. /package/{licenses/wasm/bound.txt → dist/vendor/28cba430228db1c04f446c93f81b09a2705d6bf3e222d35adbe5a4cee4061884.LICENSE} +0 -0
  333. /package/{licenses/wasm/obligations.txt → dist/vendor/7aca161279d14bc0e054dcc281cd110aeb95be2e026b42fdf527a260e58b2aae.LICENSE} +0 -0
@@ -1,528 +1 @@
1
- import { sha256 } from "../hash.js";
2
- /** Fixed Root native preload. One parent custodian holds generated provenance
3
- * and counters. Original child APIs execute actual programs; nothing synthesizes
4
- * their results. This privileged native profile is not an adversarial sandbox. */
5
- import nativeChildProcess from 'node:child_process';
6
- import fs from 'node:fs';
7
- import { traverseGeneratedClosure } from "./generated.js";
8
- import nativeWorkerThreads from 'node:worker_threads';
9
- import { realpathSync, existsSync, statSync } from 'node:fs';
10
- import { resolve, dirname, extname } from 'node:path';
11
- import { fileURLToPath, pathToFileURL } from 'node:url';
12
- import * as nativeModule from "node:module";
13
- import { syncBuiltinESMExports, builtinModules } from 'node:module';
14
- import { nodeLaunch, projectNativeProgramLaunch, selectNativeProgramParent, nativeEvalParent, actualNodeEvalOptions } from "./node-launch.js";
15
- import { readBoundedFile } from "./bounded-file.js";
16
- import { createFixedControlBridge } from "./control-bridge.js";
17
- import { installNativeResolutionReuse } from "./loader.js";
18
- const childProcess = nativeChildProcess, workerThreads = nativeWorkerThreads;
19
- const registerHooks = nativeModule.registerHooks;
20
- export function installDescendantBoundary(config) {
21
- const sha = sha256, originalSync = childProcess.spawnSync;
22
- let red, transport, reporting = false;
23
- const fail = (why) => {
24
- red ?? (red = 'REFUSE·native descendant ' + why);
25
- if (transport && !reporting) {
26
- reporting = true;
27
- try {
28
- transport({ operation: 'violation', token: endpoint.token, why: red });
29
- }
30
- catch { }
31
- finally {
32
- reporting = false;
33
- }
34
- }
35
- throw Error(red);
36
- };
37
- const { contextFile, client, runtime, preload, runtimeDigest, clientDigest } = config.custodian ?? {};
38
- let execution;
39
- try {
40
- execution = JSON.parse(readBoundedFile(contextFile, config.contextBytes, contextFile).toString('utf8'));
41
- }
42
- catch {
43
- fail('Root execution custody absent');
44
- }
45
- const { endpoint, parentExecution } = execution;
46
- const programs = execution.programs ?? [];
47
- if (!parentExecution?.identity || endpoint?.parent !== parentExecution.identity)
48
- fail('Root custody parent differs');
49
- if (!endpoint || !runtime || !preload || !client || sha(readBoundedFile(runtime, config.runtimeBytes, runtime)) !== runtimeDigest || sha(readBoundedFile(client, config.clientBytes, client)) !== clientDigest)
50
- fail('Root custodian binding absent/different');
51
- // File validity is checked only at an actual disk-execution boundary, never cached.
52
- const runtimeForExecution = (path, why) => {
53
- let valid = false;
54
- try {
55
- valid = realpathSync(path) === realpathSync(runtime) && sha(readBoundedFile(path, config.runtimeBytes, path)) === runtimeDigest;
56
- }
57
- catch {
58
- return fail(why);
59
- }
60
- if (!valid)
61
- fail(why);
62
- };
63
- const known = new Map(config.members.map((m) => [realpathSync(m.path), m.digest])), executableDigests = new Set(config.executableDigests ?? []), metadataDigests = new Set(config.metadataDigests ?? config.members.filter((m) => m.path.endsWith('.json')).map((m) => m.digest)), native = new Set(config.builtins.map((n) => n.startsWith('node:') ? n : 'node:' + n)), library = new Map(config.libraries.map((l) => [l.name, l]));
64
- // Reuse this fixed resolver only after comparing every required library
65
- // member with the instrument's pins. The inherited input resource also
66
- // bounds metadata prepared for that comparison; no world supplies a checker.
67
- let resolutionBytes = 0;
68
- const resolutionMembers = config.members.map((member) => { const path = realpathSync(member.path), stat = statSync(path); if (!stat.isFile() || !Number.isSafeInteger(config.inputBytes) || config.inputBytes < 1 || (resolutionBytes += stat.size) > config.inputBytes)
69
- fail('fixed library resolution resource exceeded'); return { path, digest: member.digest, bytes: stat.size }; });
70
- installNativeResolutionReuse({ members: resolutionMembers, libraries: config.libraries, builtins: config.builtins, entry: resolutionMembers[0]?.path ?? '', platform: config.platform });
71
- let controlBridge;
72
- if (config.control && config.control.realm !== 'main-thread')
73
- fail('unknown Root control realm');
74
- // The signed host profile selects retention only in the actual main realm.
75
- // WorldWorker realms keep the same bounded fixed-client/checks, not a SAB verifier.
76
- if (config.control && nativeWorkerThreads.isMainThread) {
77
- const c = config.control;
78
- controlBridge = createFixedControlBridge({ endpoint, workerBytes: readBoundedFile(c.worker.path, c.worker.bytes, c.worker.coordinate), worker: c.worker, runtime: { path: runtime, digest: runtimeDigest, bytes: config.runtimeBytes }, resources: c.resources, deadlineMs: endpoint.deadlineMs });
79
- process.once('exit', () => { void controlBridge?.close(); });
80
- process.once('beforeExit', () => { void controlBridge?.close(); });
81
- }
82
- const exchange = (body) => {
83
- const frame = JSON.stringify({ protocol: 'command-lot/1', coordinate: endpoint.coordinate, implementation: endpoint.implementation, identity: endpoint.identity, requests: [JSON.stringify(body)] });
84
- if (Buffer.byteLength(frame) > endpoint.responseBytes)
85
- fail('custodian request bytes');
86
- let stdout;
87
- if (controlBridge) {
88
- try {
89
- stdout = controlBridge.exchange(frame);
90
- }
91
- catch (error) {
92
- void controlBridge.close();
93
- return fail(error instanceof Error ? error.message : String(error));
94
- }
95
- }
96
- else {
97
- // This branch executes disk bytes now; retention never stands in for this check.
98
- runtimeForExecution(runtime, 'Root sync bridge runtime bytes differ');
99
- let clientValid = false;
100
- try {
101
- clientValid = sha(readBoundedFile(client, config.clientBytes, client)) === clientDigest;
102
- }
103
- catch { /* A missing or oversized executable is a refusal too. */ }
104
- if (!clientValid)
105
- fail('Root sync bridge bytes differ');
106
- const got = Reflect.apply(originalSync, childProcess, [runtime, [client, String(config.contextBytes)], { input: JSON.stringify({ endpoint, frame }), encoding: 'utf8', timeout: endpoint.timeoutMs, maxBuffer: endpoint.responseBytes, env: { ...process.env }, shell: false }]);
107
- if (got.error || got.signal || got.status !== 0 || got.stderr)
108
- fail('custodian client interrupted/refused ' + (got.error?.message ?? got.stderr ?? got.signal ?? got.status));
109
- stdout = got.stdout;
110
- }
111
- let reply;
112
- try {
113
- reply = JSON.parse(stdout);
114
- }
115
- catch {
116
- return fail('custodian response malformed');
117
- }
118
- if (reply.protocol !== 'command-lot/1' || reply.coordinate !== endpoint.coordinate || reply.implementation !== endpoint.implementation || reply.identity !== endpoint.identity || !Array.isArray(reply.responses) || reply.responses.length !== 1)
119
- fail('custodian response identity/count');
120
- return reply.responses[0];
121
- };
122
- transport = exchange;
123
- const verifiedEdges = new Map();
124
- let candidateHandoff = () => [], candidateHanded = ignoreEmission;
125
- const request = (entry, operation = 'entry') => {
126
- if (red)
127
- throw Error(red);
128
- const candidates = operation === 'entry' ? candidateHandoff() : [];
129
- const one = exchange({ operation, token: endpoint.token, request: candidates.length ? { ...entry, candidates } : entry });
130
- if (one.kind === 'refuse')
131
- fail(one.why);
132
- if (one.kind !== 'entry-context' || !one.context?.identity)
133
- fail('custodian context absent');
134
- if (one.context.parent !== parentExecution.identity || one.context.producer !== endpoint.identity)
135
- fail('custodian context parent differs');
136
- candidateHanded(candidates);
137
- if (operation === 'entry' && Array.isArray(one.context.edges)) {
138
- for (const edge of one.context.edges) {
139
- if (typeof edge.target === 'string' && edge.target.startsWith('/') && /^sha256:[0-9a-f]{64}$/.test(edge.digest ?? '')) {
140
- const prior = verifiedEdges.get(edge.target);
141
- if (prior && prior !== edge.digest)
142
- fail('verified edge bytes changed ' + edge.target);
143
- verifiedEdges.set(edge.target, edge.digest);
144
- }
145
- }
146
- }
147
- return one.context;
148
- };
149
- const invocation = (args, cwd, env, options = {}) => ({ cwd: realpathSync(resolve(cwd ?? process.cwd())), argv: [...args], environment: Object.entries(env ?? process.env).sort(), runtime, timeoutMs: Math.min(options.timeout ?? endpoint.timeoutMs, endpoint.timeoutMs), responseBytes: Math.min(options.maxBuffer ?? endpoint.responseBytes, endpoint.responseBytes) });
150
- let evalParent;
151
- const actualEval = nativeWorkerThreads.isMainThread && actualNodeEvalOptions(process.execArgv);
152
- if (actualEval) {
153
- if (realpathSync(process.execPath) !== realpathSync(runtime))
154
- fail('actual eval runtime differs from Root selection');
155
- const actual = { argv: [...process.execArgv, ...process.argv.slice(1)], rootPrefix: ['--import', preload], cwd: process.cwd(), environment: Object.entries(process.env).sort(), runtime };
156
- const retained = request(actual, 'eval-context');
157
- evalParent = nativeEvalParent(retained, actual);
158
- }
159
- let flushEmissions = ignoreEmission;
160
- let flushExecutable = ignoreEmission;
161
- const interpretedMetadata = new Map();
162
- const modeOf = (path, call) => {
163
- const ext = extname(path);
164
- if (ext === '.mjs' || ext === '.mts')
165
- return 'module';
166
- if (ext === '.cjs' || ext === '.cts')
167
- return 'commonjs';
168
- if (ext !== '' && ext !== '.js' && ext !== '.ts')
169
- fail('executable extension unsupported ' + ext);
170
- let directory = dirname(path);
171
- for (;;) {
172
- const manifest = resolve(directory, 'package.json');
173
- if (existsSync(manifest)) {
174
- flushEmissions([realpathSync(manifest)]);
175
- if (statSync(manifest).size > (config.inputBytes ?? endpoint.responseBytes))
176
- fail('package interpretation bytes');
177
- const raw = readBoundedFile(manifest, config.inputBytes, manifest);
178
- const digest = sha(raw);
179
- if (!metadataDigests.has(digest)) {
180
- const key = JSON.stringify([manifest, digest, call]);
181
- if (!interpretedMetadata.has(key)) {
182
- const held = request({ path: manifest, interpretation: 'node-package-json@1', invocation: call }, 'interpretation');
183
- if (held.kind !== 'derived-interpretation/1' || held.path !== realpathSync(manifest) || held.digest !== digest || held.interpretation !== 'node-package-json@1' || sha(readBoundedFile(manifest, config.inputBytes, manifest)) !== digest)
184
- fail('package interpretation changed after custody');
185
- interpretedMetadata.set(key, held.identity);
186
- }
187
- }
188
- let pkg;
189
- try {
190
- pkg = JSON.parse(raw.toString('utf8'));
191
- }
192
- catch {
193
- fail('package interpretation invalid');
194
- }
195
- if (pkg.type === undefined || pkg.type === 'commonjs')
196
- return 'commonjs';
197
- if (pkg.type === 'module')
198
- return 'module';
199
- fail('package interpretation type unknown');
200
- }
201
- const parent = dirname(directory);
202
- if (parent === directory)
203
- return 'commonjs';
204
- directory = parent;
205
- }
206
- };
207
- const sealFile = (path, call, forceCustody = false, loaded = undefined) => {
208
- let actual;
209
- try {
210
- actual = realpathSync(path);
211
- }
212
- catch {
213
- return fail('executable target absent ' + path);
214
- }
215
- flushEmissions([actual]);
216
- const expected = known.get(actual);
217
- if (statSync(actual).size > (config.inputBytes ?? endpoint.responseBytes))
218
- fail('input bytes before hash');
219
- const bytes = readBoundedFile(actual, config.inputBytes, actual), digest = sha(bytes);
220
- if (actual.endsWith('.json')) {
221
- if (forceCustody)
222
- fail('JSON executable entry unsupported');
223
- if (!metadataDigests.has(digest))
224
- fail('JSON interpretation not Root-selected ' + actual);
225
- return actual;
226
- }
227
- if (expected && digest !== expected)
228
- fail('retained target bytes differ ' + actual);
229
- const priorEdge = verifiedEdges.get(actual);
230
- if (priorEdge && digest !== priorEdge)
231
- fail('verified edge bytes differ ' + actual);
232
- if (!forceCustody && priorEdge === digest && !(extname(actual) === '' && !loaded))
233
- return actual;
234
- if (extname(actual) === '' && !loaded)
235
- return actual;
236
- if (!forceCustody && !loaded && (executableDigests.has(digest) || (expected && extname(actual) === '.json')))
237
- return actual;
238
- const selectedMode = loaded?.format ?? modeOf(actual, call);
239
- flushExecutable(actual, selectedMode, bytes);
240
- const context = request({ kind: 'file', path: actual, mode: selectedMode, ...(loaded ? { interpretation: 'node-ambiguous-javascript@1' } : {}), invocation: call });
241
- if (context.path !== actual && context.target?.path !== actual)
242
- fail('custodian target changed');
243
- if (context.digest !== sha(readBoundedFile(actual, config.inputBytes, actual)))
244
- fail('derived target changed after seal');
245
- return actual;
246
- };
247
- const prepare = (program, args, options = {}) => {
248
- if (red)
249
- throw Error(red);
250
- if (options.shell)
251
- fail('shell target undeclared');
252
- let command = program;
253
- const native = programs.filter((p) => p.alias === program && p.kind === 'native-binary');
254
- if (native.length) {
255
- if (native.length !== 1)
256
- fail('native binary alias ambiguous');
257
- const selected = native[0], call = invocation(args, options.cwd, options.env, options), held = request({ alias: program, path: selected.entry, invocation: call }, 'native-program');
258
- if (held.kind !== 'native-program-transaction/1' || held.target !== selected.entry || held.digest !== selected.entryDigest || sha(readBoundedFile(selected.entry, selected.entryBytes, selected.entry)) !== held.digest)
259
- fail('native binary changed before entry');
260
- return { command: selected.entry, args: [...args], options: { ...options, timeout: call.timeoutMs, maxBuffer: call.responseBytes, shell: false } };
261
- }
262
- if (programs.some((p) => p.alias === program)) {
263
- let declared;
264
- try {
265
- declared = projectNativeProgramLaunch(programs, program, args, { path: realpathSync(runtime), digest: runtimeDigest });
266
- }
267
- catch (error) {
268
- return fail(error instanceof Error ? error.message : String(error));
269
- }
270
- command = declared.interpreter;
271
- args = [declared.entry, ...declared.args];
272
- }
273
- let selected;
274
- try {
275
- selected = realpathSync(command);
276
- }
277
- catch {
278
- return fail('native program undeclared ' + program);
279
- }
280
- runtimeForExecution(selected, 'native runtime target undeclared ' + program);
281
- const launch = nodeLaunch(args), call = invocation(args, options.cwd, options.env, options);
282
- // Root bootstrap prefix is instrumentation; the original argv/text stays exact.
283
- if (launch.kind === 'eval') {
284
- flushExecutable(resolve(call.cwd, launch.mode === 'module' ? '[eval1].js' : '[eval].cjs'), launch.mode, Buffer.from(launch.text));
285
- request({ kind: 'eval', argv: ['--import', preload, ...args], rootPrefix: ['--import', preload], mode: launch.mode, invocation: call });
286
- }
287
- else
288
- sealFile(resolve(call.cwd, launch.entry), call, true);
289
- for (const input of launch.imports)
290
- sealFile(input.startsWith('file:') ? fileURLToPath(input) : resolve(call.cwd, input), call);
291
- return { command, args: ['--import', preload, ...args], options: { ...options, timeout: call.timeoutMs, maxBuffer: call.responseBytes, shell: false } };
292
- };
293
- for (const name of ['spawn', 'spawnSync', 'execFile', 'execFileSync']) {
294
- const original = childProcess[name];
295
- childProcess[name] = function (program, args, options, ...tail) {
296
- if (!Array.isArray(args) || typeof options === 'function')
297
- fail('native call shape unsupported ' + name);
298
- const checked = prepare(program, args, options);
299
- return Reflect.apply(original, this, [checked.command, checked.args, checked.options, ...tail]);
300
- };
301
- }
302
- childProcess.exec = childProcess.execSync = () => fail('shell native profile absent');
303
- const originalFork = childProcess.fork;
304
- childProcess.fork = function (module, args = [], options = {}) {
305
- if (!Array.isArray(args))
306
- fail('fork argv shape');
307
- if (options.execPath && realpathSync(options.execPath) !== realpathSync(runtime))
308
- fail('fork runtime undeclared');
309
- const originalArgv = options.execArgv ?? process.execArgv, withoutRoot = originalArgv[0] === '--import' && originalArgv[1] === preload ? originalArgv.slice(2) : originalArgv;
310
- const launch = nodeLaunch([...withoutRoot, module, ...args]);
311
- if (launch.kind !== 'file' || launch.entry !== module)
312
- fail('fork executable mode unsupported');
313
- for (const input of launch.imports)
314
- sealFile(input.startsWith('file:') ? fileURLToPath(input) : resolve(options.cwd ?? process.cwd(), input), invocation([module, ...args], options.cwd, options.env, options));
315
- sealFile(resolve(options.cwd ?? process.cwd(), module), invocation([module, ...args], options.cwd, options.env, options), true);
316
- // Fork executes a runtime from disk, unlike a retained control message.
317
- const forkRuntime = options.execPath ?? process.execPath;
318
- runtimeForExecution(forkRuntime, 'fork runtime bytes differ from Root selection');
319
- return Reflect.apply(originalFork, this, [module, args, { ...options, execArgv: ['--import', preload, ...withoutRoot] }]);
320
- };
321
- const OriginalWorker = workerThreads.Worker;
322
- workerThreads.Worker = class extends OriginalWorker {
323
- constructor(target, options = {}) {
324
- const args = options.execArgv ?? process.execArgv, withoutRoot = args[0] === '--import' && args[1] === preload ? args.slice(2) : args;
325
- if (options.eval)
326
- fail('Worker string-eval profile absent');
327
- sealFile(target instanceof URL ? fileURLToPath(target) : resolve(target), invocation([String(target), ...withoutRoot], process.cwd(), options.env), true);
328
- super(target, { ...options, execArgv: ['--import', preload, ...withoutRoot] });
329
- }
330
- };
331
- // This fixed host observer is enabled only by the actual Root producer grant.
332
- // The original write completes first; failed writes produce no output evidence.
333
- if (endpoint.interpretations?.includes('host-file-emission@1')) {
334
- const write = fs.writeFileSync, append = fs.appendFileSync, acknowledged = new Set(), pending = new Map();
335
- const sentCandidates = new Map();
336
- candidateHandoff = () => { const groups = new Map(); for (const row of pending.values()) {
337
- const identity = JSON.stringify(row);
338
- if (sentCandidates.get(row.path) === identity)
339
- continue;
340
- const key = JSON.stringify(row.call), group = groups.get(key) ?? { invocation: row.call, outputs: [] };
341
- group.outputs.push({ path: row.path, ...(row.digest ? { digest: row.digest } : { reason: row.reason }) });
342
- groups.set(key, group);
343
- } return [...groups.values()]; };
344
- candidateHanded = groups => { for (const group of groups)
345
- for (const output of group.outputs) {
346
- const row = pending.get(output.path);
347
- if (row && JSON.stringify(row.call) === JSON.stringify(group.invocation) && row.digest === output.digest && row.reason === output.reason)
348
- sentCandidates.set(output.path, JSON.stringify(row));
349
- } };
350
- const limits = endpoint.limits;
351
- if (!limits || !['members', 'bytes', 'work', 'argvBytes', 'argvItems'].every(name => Number.isSafeInteger(limits[name]) && limits[name] >= 0))
352
- fail('producer selection limits absent');
353
- flushEmissions = (paths = []) => {
354
- const required = [...new Set(paths)].flatMap(path => { const row = pending.get(path); if (!row)
355
- return []; if (row.reason)
356
- fail('required emission unmeasured ' + path + ' ' + row.reason); return [row]; });
357
- const groups = new Map();
358
- for (const row of required) {
359
- const key = JSON.stringify(row.call), group = groups.get(key) ?? [];
360
- group.push(row);
361
- groups.set(key, group);
362
- }
363
- for (const rows of groups.values()) {
364
- const outputs = rows.map(({ path, digest }) => ({ path, digest })), held = request({ outputs, invocation: rows[0].call }, 'emission-batch');
365
- if (held.kind !== 'producer-emission-batch/1' || held.parent !== parentExecution.identity || held.producer !== endpoint.identity || !Array.isArray(held.outputs) || held.outputs.length !== outputs.length)
366
- fail('emission batch provenance differs');
367
- for (let i = 0; i < outputs.length; i++) {
368
- if (held.outputs[i].path !== outputs[i].path || held.outputs[i].digest !== outputs[i].digest || !held.outputs[i].identity)
369
- fail('emission batch output differs');
370
- acknowledged.add(outputs[i].digest);
371
- pending.delete(outputs[i].path);
372
- }
373
- }
374
- };
375
- flushExecutable = (path, mode, source) => {
376
- if (!pending.size || (source && executableDigests.has(sha(source))))
377
- return;
378
- const required = new Set(), readPaths = new Set(), derivedPaths = new Set();
379
- let bytes = 0, derivedBytes = 0, work = 0;
380
- const step = () => { if (++work > limits.work)
381
- fail('emission selection work exhausted ' + path); };
382
- const verify = (target) => { step(); const real = realpathSync(target), candidate = pending.get(real); if (candidate?.reason)
383
- fail('required emission unmeasured ' + real + ' ' + candidate.reason); const raw = readBoundedFile(real, config.inputBytes, real), digest = sha(raw); if (!readPaths.has(real)) {
384
- readPaths.add(real);
385
- bytes += raw.length;
386
- if (bytes > config.inputBytes)
387
- fail('emission selection input bytes ' + real);
388
- if (!known.has(real) && !executableDigests.has(digest) && !metadataDigests.has(digest)) {
389
- derivedPaths.add(real);
390
- derivedBytes += raw.length;
391
- if (derivedPaths.size > limits.members || derivedBytes > limits.bytes)
392
- fail('emission selection derived resources ' + real);
393
- }
394
- } if (candidate) {
395
- if (candidate.digest !== digest)
396
- fail('observed emission bytes differ ' + real);
397
- required.add(real);
398
- } return { real, bytes: raw, digest }; };
399
- const entry = source ? { real: path, bytes: source, digest: sha(source) } : verify(path);
400
- // The hint stops at sealed executable content. Root's custodian
401
- // still independently verifies the complete selected closure.
402
- if (!executableDigests.has(entry.digest))
403
- traverseGeneratedClosure({ source: entry.bytes, path: entry.real, mode, libs: new Map(config.libraries.map((l) => [l.name, l.manifest])), native: new Set(config.builtins.map((n) => n.startsWith('node:') ? n : 'node:' + n)), platform: config.platform, nativeImplementations: executableDigests, verify, step });
404
- flushEmissions([...required]);
405
- };
406
- const writtenDigest = (path) => {
407
- const fd = fs.openSync(path, 'r');
408
- try {
409
- const stat = fs.fstatSync(fd), size = stat.size, limit = Math.min(config.inputBytes ?? parentExecution.responseBytes, parentExecution.responseBytes);
410
- if (!stat.isFile() || !Number.isSafeInteger(size) || size < 0 || size > limit)
411
- throw Error('emission bytes before hash ' + path);
412
- const bytes = Buffer.alloc(size), tail = Buffer.alloc(1);
413
- let got = 0;
414
- while (got < size) {
415
- const n = fs.readSync(fd, bytes, got, size - got, got);
416
- if (!n)
417
- break;
418
- got += n;
419
- }
420
- if (got !== size || fs.readSync(fd, tail, 0, 1, size) !== 0)
421
- throw Error('emission changed during bounded read ' + path);
422
- return sha(bytes);
423
- }
424
- finally {
425
- fs.closeSync(fd);
426
- }
427
- };
428
- const observeWrite = (operation) => function (file, ...args) {
429
- const call = invocation([...process.execArgv, ...process.argv.slice(1)], process.cwd(), process.env);
430
- if (typeof file !== 'string' && !(file instanceof URL))
431
- fail('emission write route unsupported');
432
- const named = file instanceof URL ? fileURLToPath(file) : resolve(file);
433
- const result = Reflect.apply(operation, this, [file, ...args]);
434
- const actual = realpathSync(named);
435
- let digest, reason;
436
- try {
437
- digest = writtenDigest(actual);
438
- }
439
- catch (error) {
440
- reason = error instanceof Error ? error.message : String(error);
441
- }
442
- // Unstable operational data is an unmeasured candidate, never a
443
- // successful emission. Actual executable use must close it first.
444
- if (digest && (executableDigests.has(digest) || acknowledged.has(digest))) {
445
- pending.delete(actual);
446
- return result;
447
- }
448
- pending.set(actual, { path: actual, digest, reason, call });
449
- if (Buffer.byteLength(JSON.stringify([...pending.values()].map(({ path, digest, reason }) => ({ path, digest, reason })))) > parentExecution.responseBytes)
450
- fail('pending emission provenance bytes');
451
- return result;
452
- };
453
- fs.writeFileSync = observeWrite(write);
454
- fs.appendFileSync = observeWrite(append);
455
- }
456
- syncBuiltinESMExports();
457
- // Exact libraries are already verified by Root. Node supplies resolution, then
458
- // the actual target is checked BEFORE it executes. Computed ordinary code is
459
- // still screened by the custodian's strict generated-code gate.
460
- if (typeof registerHooks !== 'function')
461
- fail('runtime hooks absent');
462
- registerHooks({ resolve(specifier, context, next) {
463
- if (red)
464
- throw Error(red);
465
- const builtin = specifier.startsWith('node:') ? specifier : 'node:' + specifier;
466
- if (builtinModules.includes(specifier) || specifier.startsWith('node:')) {
467
- if (!native.has(builtin))
468
- fail('native ABI undeclared ' + specifier);
469
- return next(builtin, context);
470
- }
471
- let selected = context, programParent;
472
- if (context.parentURL?.startsWith('file:') && context.parentURL !== evalParent?.url) {
473
- const parent = realpathSync(fileURLToPath(context.parentURL)), expected = known.get(parent);
474
- if (programs.some((p) => p.kind !== 'native-binary' && p.members.some((m) => m.path === parent))) {
475
- if (!expected || sha(readBoundedFile(parent, config.inputBytes, parent)) !== expected)
476
- fail('program parent bytes differ');
477
- try {
478
- programParent = selectNativeProgramParent(programs.filter((p) => p.kind !== 'native-binary'), { path: parent, digest: expected });
479
- }
480
- catch (error) {
481
- fail(error instanceof Error ? error.message : String(error));
482
- }
483
- }
484
- }
485
- if (!programParent && !specifier.startsWith('.') && !specifier.startsWith('/') && !specifier.includes(':')) {
486
- const name = specifier.startsWith('@') ? specifier.split('/').slice(0, 2).join('/') : specifier.split('/')[0], lib = library.get(name);
487
- if (!lib)
488
- fail('library undeclared ' + name);
489
- selected = { ...context, parentURL: pathToFileURL(lib.manifest).href };
490
- }
491
- const got = next(specifier, selected);
492
- if (!got.url.startsWith('file:'))
493
- fail('module scheme undeclared ' + got.url);
494
- sealFile(fileURLToPath(got.url), invocation([...process.execArgv, ...process.argv.slice(1)], process.cwd(), process.env));
495
- return got;
496
- }, load(url, context, nextLoad) {
497
- if (!url.startsWith('file:'))
498
- return nextLoad(url, context);
499
- const actual = realpathSync(fileURLToPath(url));
500
- if (statSync(actual).size > (config.inputBytes ?? endpoint.responseBytes))
501
- fail('ambiguous input bytes before load');
502
- const call = invocation([...process.execArgv, ...process.argv.slice(1)], process.cwd(), process.env);
503
- // Seal controlling package interpretation before Node reads it. Its returned
504
- // default is deliberately ignored: only Node's actual load result supplies mode.
505
- const ambiguous = extname(actual) === '';
506
- if (ambiguous)
507
- modeOf(actual, call);
508
- const before = readBoundedFile(actual, config.inputBytes, actual), digest = sha(before), loaded = nextLoad(url, context);
509
- if (ambiguous && !['module', 'commonjs'].includes(loaded.format))
510
- fail('ambiguous Node interpretation unsupported ' + loaded.format);
511
- if (loaded.source === null || loaded.source === undefined)
512
- fail('ambiguous Node source absent before execution');
513
- const source = typeof loaded.source === 'string' ? Buffer.from(loaded.source, 'utf8') : loaded.source instanceof ArrayBuffer ? Buffer.from(loaded.source) : Buffer.from(loaded.source.buffer, loaded.source.byteOffset, loaded.source.byteLength);
514
- if (sha(source) !== digest || sha(readBoundedFile(actual, config.inputBytes, actual)) !== digest)
515
- fail('ambiguous Node source differs before execution');
516
- const processEntry = process.argv[1] && realpathSync(resolve(process.argv[1])) === actual;
517
- sealFile(actual, call, Boolean(processEntry) && ambiguous, ambiguous ? loaded : undefined);
518
- return loaded;
519
- } });
520
- if (process.argv[1])
521
- sealFile(resolve(process.argv[1]), invocation([...process.execArgv, ...process.argv.slice(1)], process.cwd(), process.env), true);
522
- process.once('beforeExit', () => {
523
- if (red)
524
- throw Error(red);
525
- });
526
- }
527
- /** An optional observer does nothing until fixed custody is installed. */
528
- const ignoreEmission = (..._args) => { };
1
+ var Re=Object.defineProperty;var v=(c,b)=>Re(c,"name",{value:b,configurable:!0});import{sha256 as Ne}from"../hash.js";import Ae from"node:child_process";import A from"node:fs";import{traverseGeneratedClosure as Oe}from"./generated.js";import ie from"node:worker_threads";import{realpathSync as w,existsSync as je,statSync as Q}from"node:fs";import{resolve as M,dirname as he,extname as H}from"node:path";import{fileURLToPath as L,pathToFileURL as We}from"node:url";import*as Pe from"node:module";import{syncBuiltinESMExports as Fe,builtinModules as Je}from"node:module";import{nodeLaunch as ge,projectNativeProgramLaunch as Le,selectNativeProgramParent as Ue,nativeEvalParent as ze,actualNodeEvalOptions as De}from"./node-launch.js";import{readBoundedFile as B}from"./bounded-file.js";import{createFixedControlBridge as qe}from"./control-bridge.js";import{installNativeResolutionReuse as Ie}from"./loader.js";const P=Ae,ve=ie,be=Pe.registerHooks;function st(c){const b=Ne,we=P.spawnSync;let S,X,Y=!1;const i=v(e=>{if(S??(S="REFUSE\xB7native descendant "+e),X&&!Y){Y=!0;try{X({operation:"violation",token:m.token,why:S})}catch{}finally{Y=!1}}throw Error(S)},"fail"),{contextFile:ae,client:U,runtime:E,preload:R,runtimeDigest:C,clientDigest:ce}=c.custodian??{};let Z;try{Z=JSON.parse(B(ae,c.contextBytes,ae).toString("utf8"))}catch{i("Root execution custody absent")}const{endpoint:m,parentExecution:F}=Z,I=Z.programs??[];(!F?.identity||m?.parent!==F.identity)&&i("Root custody parent differs"),(!m||!E||!R||!U||b(B(E,c.runtimeBytes,E))!==C||b(B(U,c.clientBytes,U))!==ce)&&i("Root custodian binding absent/different");const ee=v((e,o)=>{let n=!1;try{n=w(e)===w(E)&&b(B(e,c.runtimeBytes,e))===C}catch{return i(o)}n||i(o)},"runtimeForExecution"),te=new Map(c.members.map(e=>[w(e.path),e.digest])),z=new Set(c.executableDigests??[]),re=new Set(c.metadataDigests??c.members.filter(e=>e.path.endsWith(".json")).map(e=>e.digest)),xe=new Set(c.builtins.map(e=>e.startsWith("node:")?e:"node:"+e)),Be=new Map(c.libraries.map(e=>[e.name,e]));let ke=0;const de=c.members.map(e=>{const o=w(e.path),n=Q(o);return(!n.isFile()||!Number.isSafeInteger(c.inputBytes)||c.inputBytes<1||(ke+=n.size)>c.inputBytes)&&i("fixed library resolution resource exceeded"),{path:o,digest:e.digest,bytes:n.size}});Ie({members:de,libraries:c.libraries,builtins:c.builtins,entry:de[0]?.path??"",platform:c.platform});let D;if(c.control&&c.control.realm!=="main-thread"&&i("unknown Root control realm"),c.control&&ie.isMainThread){const e=c.control;D=qe({endpoint:m,workerBytes:B(e.worker.path,e.worker.bytes,e.worker.coordinate),worker:e.worker,runtime:{path:E,digest:C,bytes:c.runtimeBytes},resources:e.resources,deadlineMs:m.deadlineMs}),process.once("exit",()=>{D?.close()}),process.once("beforeExit",()=>{D?.close()})}const ue=v(e=>{const o=JSON.stringify({protocol:"command-lot/1",coordinate:m.coordinate,implementation:m.implementation,identity:m.identity,requests:[JSON.stringify(e)]});Buffer.byteLength(o)>m.responseBytes&&i("custodian request bytes");let n;if(D)try{n=D.exchange(o)}catch(t){return D.close(),i(t instanceof Error?t.message:String(t))}else{ee(E,"Root sync bridge runtime bytes differ");let t=!1;try{t=b(B(U,c.clientBytes,U))===ce}catch{}t||i("Root sync bridge bytes differ");const d=Reflect.apply(we,P,[E,[U,String(c.contextBytes)],{input:JSON.stringify({endpoint:m,frame:o}),encoding:"utf8",timeout:m.timeoutMs,maxBuffer:m.responseBytes,env:{...process.env},shell:!1}]);(d.error||d.signal||d.status!==0||d.stderr)&&i("custodian client interrupted/refused "+(d.error?.message??d.stderr??d.signal??d.status)),n=d.stdout}let s;try{s=JSON.parse(n)}catch{return i("custodian response malformed")}return(s.protocol!=="command-lot/1"||s.coordinate!==m.coordinate||s.implementation!==m.implementation||s.identity!==m.identity||!Array.isArray(s.responses)||s.responses.length!==1)&&i("custodian response identity/count"),s.responses[0]},"exchange");X=ue;const se=new Map;let le=v(()=>[],"candidateHandoff"),fe=oe;const q=v((e,o="entry")=>{if(S)throw Error(S);const n=o==="entry"?le():[],s=ue({operation:o,token:m.token,request:n.length?{...e,candidates:n}:e});if(s.kind==="refuse"&&i(s.why),(s.kind!=="entry-context"||!s.context?.identity)&&i("custodian context absent"),(s.context.parent!==F.identity||s.context.producer!==m.identity)&&i("custodian context parent differs"),fe(n),o==="entry"&&Array.isArray(s.context.edges)){for(const t of s.context.edges)if(typeof t.target=="string"&&t.target.startsWith("/")&&/^sha256:[0-9a-f]{64}$/.test(t.digest??"")){const d=se.get(t.target);d&&d!==t.digest&&i("verified edge bytes changed "+t.target),se.set(t.target,t.digest)}}return s.context},"request"),N=v((e,o,n,s={})=>({cwd:w(M(o??process.cwd())),argv:[...e],environment:Object.entries(n??process.env).sort(),runtime:E,timeoutMs:Math.min(s.timeout??m.timeoutMs,m.timeoutMs),responseBytes:Math.min(s.maxBuffer??m.responseBytes,m.responseBytes)}),"invocation");let pe;if(ie.isMainThread&&De(process.execArgv)){w(process.execPath)!==w(E)&&i("actual eval runtime differs from Root selection");const e={argv:[...process.execArgv,...process.argv.slice(1)],rootPrefix:["--import",R],cwd:process.cwd(),environment:Object.entries(process.env).sort(),runtime:E},o=q(e,"eval-context");pe=ze(o,e)}let G=oe,ne=oe;const me=new Map,ye=v((e,o)=>{const n=H(e);if(n===".mjs"||n===".mts")return"module";if(n===".cjs"||n===".cts")return"commonjs";n!==""&&n!==".js"&&n!==".ts"&&i("executable extension unsupported "+n);let s=he(e);for(;;){const t=M(s,"package.json");if(je(t)){G([w(t)]),Q(t).size>(c.inputBytes??m.responseBytes)&&i("package interpretation bytes");const p=B(t,c.inputBytes,t),l=b(p);if(!re.has(l)){const a=JSON.stringify([t,l,o]);if(!me.has(a)){const u=q({path:t,interpretation:"node-package-json@1",invocation:o},"interpretation");(u.kind!=="derived-interpretation/1"||u.path!==w(t)||u.digest!==l||u.interpretation!=="node-package-json@1"||b(B(t,c.inputBytes,t))!==l)&&i("package interpretation changed after custody"),me.set(a,u.identity)}}let r;try{r=JSON.parse(p.toString("utf8"))}catch{i("package interpretation invalid")}if(r.type===void 0||r.type==="commonjs")return"commonjs";if(r.type==="module")return"module";i("package interpretation type unknown")}const d=he(s);if(d===s)return"commonjs";s=d}},"modeOf"),O=v((e,o,n=!1,s=void 0)=>{let t;try{t=w(e)}catch{return i("executable target absent "+e)}G([t]);const d=te.get(t);Q(t).size>(c.inputBytes??m.responseBytes)&&i("input bytes before hash");const p=B(t,c.inputBytes,t),l=b(p);if(t.endsWith(".json"))return n&&i("JSON executable entry unsupported"),re.has(l)||i("JSON interpretation not Root-selected "+t),t;d&&l!==d&&i("retained target bytes differ "+t);const r=se.get(t);if(r&&l!==r&&i("verified edge bytes differ "+t),!n&&r===l&&!(H(t)===""&&!s)||H(t)===""&&!s||!n&&!s&&(z.has(l)||d&&H(t)===".json"))return t;const a=s?.format??ye(t,o);ne(t,a,p);const u=q({kind:"file",path:t,mode:a,...s?{interpretation:"node-ambiguous-javascript@1"}:{},invocation:o});return u.path!==t&&u.target?.path!==t&&i("custodian target changed"),u.digest!==b(B(t,c.inputBytes,t))&&i("derived target changed after seal"),t},"sealFile"),Se=v((e,o,n={})=>{if(S)throw Error(S);n.shell&&i("shell target undeclared");let s=e;const t=I.filter(r=>r.alias===e&&r.kind==="native-binary");if(t.length){t.length!==1&&i("native binary alias ambiguous");const r=t[0],a=N(o,n.cwd,n.env,n),u=q({alias:e,path:r.entry,invocation:a},"native-program");return(u.kind!=="native-program-transaction/1"||u.target!==r.entry||u.digest!==r.entryDigest||b(B(r.entry,r.entryBytes,r.entry))!==u.digest)&&i("native binary changed before entry"),{command:r.entry,args:[...o],options:{...n,timeout:a.timeoutMs,maxBuffer:a.responseBytes,shell:!1}}}if(I.some(r=>r.alias===e)){let r;try{r=Le(I,e,o,{path:w(E),digest:C})}catch(a){return i(a instanceof Error?a.message:String(a))}s=r.interpreter,o=[r.entry,...r.args]}let d;try{d=w(s)}catch{return i("native program undeclared "+e)}ee(d,"native runtime target undeclared "+e);const p=ge(o),l=N(o,n.cwd,n.env,n);p.kind==="eval"?(ne(M(l.cwd,p.mode==="module"?"[eval1].js":"[eval].cjs"),p.mode,Buffer.from(p.text)),q({kind:"eval",argv:["--import",R,...o],rootPrefix:["--import",R],mode:p.mode,invocation:l})):O(M(l.cwd,p.entry),l,!0);for(const r of p.imports)O(r.startsWith("file:")?L(r):M(l.cwd,r),l);return{command:s,args:["--import",R,...o],options:{...n,timeout:l.timeoutMs,maxBuffer:l.responseBytes,shell:!1}}},"prepare");for(const e of["spawn","spawnSync","execFile","execFileSync"]){const o=P[e];P[e]=function(n,s,t,...d){(!Array.isArray(s)||typeof t=="function")&&i("native call shape unsupported "+e);const p=Se(n,s,t);return Reflect.apply(o,this,[p.command,p.args,p.options,...d])}}P.exec=P.execSync=()=>i("shell native profile absent");const Ee=P.fork;P.fork=function(e,o=[],n={}){Array.isArray(o)||i("fork argv shape"),n.execPath&&w(n.execPath)!==w(E)&&i("fork runtime undeclared");const s=n.execArgv??process.execArgv,t=s[0]==="--import"&&s[1]===R?s.slice(2):s,d=ge([...t,e,...o]);(d.kind!=="file"||d.entry!==e)&&i("fork executable mode unsupported");for(const l of d.imports)O(l.startsWith("file:")?L(l):M(n.cwd??process.cwd(),l),N([e,...o],n.cwd,n.env,n));O(M(n.cwd??process.cwd(),e),N([e,...o],n.cwd,n.env,n),!0);const p=n.execPath??process.execPath;return ee(p,"fork runtime bytes differ from Root selection"),Reflect.apply(Ee,this,[e,o,{...n,execArgv:["--import",R,...t]}])};const Me=ve.Worker;if(ve.Worker=class extends Me{constructor(e,o={}){const n=o.execArgv??process.execArgv,s=n[0]==="--import"&&n[1]===R?n.slice(2):n;o.eval&&i("Worker string-eval profile absent"),O(e instanceof URL?L(e):M(e),N([String(e),...s],process.cwd(),o.env),!0),super(e,{...o,execArgv:["--import",R,...s]})}},m.interpretations?.includes("host-file-emission@1")){const e=A.writeFileSync,o=A.appendFileSync,n=new Set,s=new Map,t=new Map;le=v(()=>{const r=new Map;for(const a of s.values()){const u=JSON.stringify(a);if(t.get(a.path)===u)continue;const f=JSON.stringify(a.call),y=r.get(f)??{invocation:a.call,outputs:[]};y.outputs.push({path:a.path,...a.digest?{digest:a.digest}:{reason:a.reason}}),r.set(f,y)}return[...r.values()]},"candidateHandoff"),fe=v(r=>{for(const a of r)for(const u of a.outputs){const f=s.get(u.path);f&&JSON.stringify(f.call)===JSON.stringify(a.invocation)&&f.digest===u.digest&&f.reason===u.reason&&t.set(u.path,JSON.stringify(f))}},"candidateHanded");const d=m.limits;(!d||!["members","bytes","work","argvBytes","argvItems"].every(r=>Number.isSafeInteger(d[r])&&d[r]>=0))&&i("producer selection limits absent"),G=v((r=[])=>{const a=[...new Set(r)].flatMap(f=>{const y=s.get(f);return y?(y.reason&&i("required emission unmeasured "+f+" "+y.reason),[y]):[]}),u=new Map;for(const f of a){const y=JSON.stringify(f.call),g=u.get(y)??[];g.push(f),u.set(y,g)}for(const f of u.values()){const y=f.map(({path:h,digest:x})=>({path:h,digest:x})),g=q({outputs:y,invocation:f[0].call},"emission-batch");(g.kind!=="producer-emission-batch/1"||g.parent!==F.identity||g.producer!==m.identity||!Array.isArray(g.outputs)||g.outputs.length!==y.length)&&i("emission batch provenance differs");for(let h=0;h<y.length;h++)(g.outputs[h].path!==y[h].path||g.outputs[h].digest!==y[h].digest||!g.outputs[h].identity)&&i("emission batch output differs"),n.add(y[h].digest),s.delete(y[h].path)}},"flushEmissions"),ne=v((r,a,u)=>{if(!s.size||u&&z.has(b(u)))return;const f=new Set,y=new Set,g=new Set;let h=0,x=0,J=0;const j=v(()=>{++J>d.work&&i("emission selection work exhausted "+r)},"step"),V=v(W=>{j();const k=w(W),_=s.get(k);_?.reason&&i("required emission unmeasured "+k+" "+_.reason);const $=B(k,c.inputBytes,k),K=b($);return y.has(k)||(y.add(k),h+=$.length,h>c.inputBytes&&i("emission selection input bytes "+k),!te.has(k)&&!z.has(K)&&!re.has(K)&&(g.add(k),x+=$.length,(g.size>d.members||x>d.bytes)&&i("emission selection derived resources "+k))),_&&(_.digest!==K&&i("observed emission bytes differ "+k),f.add(k)),{real:k,bytes:$,digest:K}},"verify"),T=u?{real:r,bytes:u,digest:b(u)}:V(r);z.has(T.digest)||Oe({source:T.bytes,path:T.real,mode:a,libs:new Map(c.libraries.map(W=>[W.name,W.manifest])),native:new Set(c.builtins.map(W=>W.startsWith("node:")?W:"node:"+W)),platform:c.platform,nativeImplementations:z,verify:V,step:j}),G([...f])},"flushExecutable");const p=v(r=>{const a=A.openSync(r,"r");try{const u=A.fstatSync(a),f=u.size,y=Math.min(c.inputBytes??F.responseBytes,F.responseBytes);if(!u.isFile()||!Number.isSafeInteger(f)||f<0||f>y)throw Error("emission bytes before hash "+r);const g=Buffer.alloc(f),h=Buffer.alloc(1);let x=0;for(;x<f;){const J=A.readSync(a,g,x,f-x,x);if(!J)break;x+=J}if(x!==f||A.readSync(a,h,0,1,f)!==0)throw Error("emission changed during bounded read "+r);return b(g)}finally{A.closeSync(a)}},"writtenDigest"),l=v(r=>function(a,...u){const f=N([...process.execArgv,...process.argv.slice(1)],process.cwd(),process.env);typeof a!="string"&&!(a instanceof URL)&&i("emission write route unsupported");const y=a instanceof URL?L(a):M(a),g=Reflect.apply(r,this,[a,...u]),h=w(y);let x,J;try{x=p(h)}catch(j){J=j instanceof Error?j.message:String(j)}return x&&(z.has(x)||n.has(x))?(s.delete(h),g):(s.set(h,{path:h,digest:x,reason:J,call:f}),Buffer.byteLength(JSON.stringify([...s.values()].map(({path:j,digest:V,reason:T})=>({path:j,digest:V,reason:T}))))>F.responseBytes&&i("pending emission provenance bytes"),g)},"observeWrite");A.writeFileSync=l(e),A.appendFileSync=l(o)}Fe(),typeof be!="function"&&i("runtime hooks absent"),be({resolve(e,o,n){if(S)throw Error(S);const s=e.startsWith("node:")?e:"node:"+e;if(Je.includes(e)||e.startsWith("node:"))return xe.has(s)||i("native ABI undeclared "+e),n(s,o);let t=o,d;if(o.parentURL?.startsWith("file:")&&o.parentURL!==pe?.url){const l=w(L(o.parentURL)),r=te.get(l);if(I.some(a=>a.kind!=="native-binary"&&a.members.some(u=>u.path===l))){(!r||b(B(l,c.inputBytes,l))!==r)&&i("program parent bytes differ");try{d=Ue(I.filter(a=>a.kind!=="native-binary"),{path:l,digest:r})}catch(a){i(a instanceof Error?a.message:String(a))}}}if(!d&&!e.startsWith(".")&&!e.startsWith("/")&&!e.includes(":")){const l=e.startsWith("@")?e.split("/").slice(0,2).join("/"):e.split("/")[0],r=Be.get(l);r||i("library undeclared "+l),t={...o,parentURL:We(r.manifest).href}}const p=n(e,t);return p.url.startsWith("file:")||i("module scheme undeclared "+p.url),O(L(p.url),N([...process.execArgv,...process.argv.slice(1)],process.cwd(),process.env)),p},load(e,o,n){if(!e.startsWith("file:"))return n(e,o);const s=w(L(e));Q(s).size>(c.inputBytes??m.responseBytes)&&i("ambiguous input bytes before load");const t=N([...process.execArgv,...process.argv.slice(1)],process.cwd(),process.env),d=H(s)==="";d&&ye(s,t);const p=B(s,c.inputBytes,s),l=b(p),r=n(e,o);d&&!["module","commonjs"].includes(r.format)&&i("ambiguous Node interpretation unsupported "+r.format),(r.source===null||r.source===void 0)&&i("ambiguous Node source absent before execution");const a=typeof r.source=="string"?Buffer.from(r.source,"utf8"):r.source instanceof ArrayBuffer?Buffer.from(r.source):Buffer.from(r.source.buffer,r.source.byteOffset,r.source.byteLength);(b(a)!==l||b(B(s,c.inputBytes,s))!==l)&&i("ambiguous Node source differs before execution");const u=process.argv[1]&&w(M(process.argv[1]))===s;return O(s,t,!!u&&d,d?r:void 0),r}}),process.argv[1]&&O(M(process.argv[1]),N([...process.execArgv,...process.argv.slice(1)],process.cwd(),process.env),!0),process.once("beforeExit",()=>{if(S)throw Error(S)})}v(st,"installDescendantBoundary");const oe=v((...c)=>{},"ignoreEmission");export{st as installDescendantBoundary};