@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,72 +1 @@
1
- import { retainedProjection } from "./reading.js";
2
- import { fieldNames } from "./reading.js";
3
- import { sha256 as sha } from "../hash.js";
4
- /** A program alias is a Root selection, never PATH.
5
- * This verifies a finite implementation before entry; it executes nothing.
6
- * The runtime hook must still verify each reached member before loading it. */
7
- import { isAbsolute, resolve, relative } from 'node:path';
8
- import { realpathSync } from 'node:fs';
9
- import { authenticateSignedPort, nativeParentInputBytes, canonicalJson } from "./reading.js";
10
- import { readBounded } from "./generated.js";
11
- const fail = (why) => { throw Error('REFUSE·native program ' + why); };
12
- const keys = fieldNames;
13
- const verified = new WeakMap();
14
- export function verifyNativeProgram(root, coordinate, parent, runtimeBinding) {
15
- const authenticated = authenticateSignedPort(root, coordinate), p = authenticated.profile;
16
- if (!p || keys(p) !== 'alias,condition,coordinate,entry,interpreter,limits,members,profile,root,selector' || p.profile !== 'host-native-program@1' || p.coordinate !== coordinate || typeof p.alias !== 'string' || !p.alias.length || p.alias.includes('\0') || typeof p.condition !== 'string' || !p.condition.length)
17
- fail('selection absent/unknown');
18
- if (keys(p.selector ?? {}) !== 'binding,implementation,port' || canonicalJson(p.selector) !== canonicalJson({ port: parent.port, binding: parent.binding, implementation: parent.implementation }))
19
- fail('selection differs from parent');
20
- if (keys(p.limits ?? {}) !== 'bytes,members' || !Number.isSafeInteger(p.limits.members) || p.limits.members < 1 || !Number.isSafeInteger(p.limits.bytes) || p.limits.bytes < 1 || p.limits.bytes > nativeParentInputBytes(root, parent))
21
- fail('implementation resource absent/exceeds Root');
22
- if ([parent.identity, parent.instrument, parent.policy, parent.authority, parent.implementation].some(d => typeof d !== 'string' || !/^sha256:[0-9a-f]{64}$/.test(d)))
23
- fail('parent identity absent');
24
- if (!Array.isArray(p.members) || p.members.length > p.limits.members || typeof p.root !== 'string' || isAbsolute(p.root) || p.root.split('/').some(s => !s || s === '.' || s === '..') || !p.interpreter || typeof p.interpreter.path !== 'string' || isAbsolute(p.interpreter.path) || p.interpreter.path !== runtimeBinding.coordinate || keys(p.interpreter) !== 'bytes,digest,path' || !Number.isSafeInteger(p.interpreter.bytes) || p.interpreter.bytes < 1)
25
- fail('interpreter/implementation context absent');
26
- // This binding comes from the private prepared host image, not the program's
27
- // declaration. Matching a path alone cannot identify an implementation.
28
- if (!runtimeBinding || runtimeBinding.path !== parent.runtime || runtimeBinding.digest !== p.interpreter.digest || !parent.inputs.some(p => p[1] === runtimeBinding.digest))
29
- fail('interpreter differs from parent image');
30
- let bytes = p.interpreter.bytes;
31
- if (bytes > p.limits.bytes)
32
- fail('interpreter byte resource');
33
- const coordinates = new Set();
34
- for (const m of p.members) {
35
- if (!m || keys(m) !== 'bytes,coordinate,digest' || typeof m.coordinate !== 'string' || !m.coordinate.length || isAbsolute(m.coordinate) || m.coordinate.includes('\\') || m.coordinate.split('/').some(x => !x || x === '.' || x === '..') || coordinates.has(m.coordinate) || !/^sha256:[0-9a-f]{64}$/.test(m.digest) || !Number.isSafeInteger(m.bytes) || m.bytes < 0)
36
- fail('member identity ambiguous');
37
- coordinates.add(m.coordinate);
38
- bytes += m.bytes;
39
- if (bytes > p.limits.bytes)
40
- fail('implementation byte resource');
41
- }
42
- // All declarations and aggregate resources are checked before reading files.
43
- if (!coordinates.has(p.entry) || !/^sha256:[0-9a-f]{64}$/.test(p.interpreter.digest))
44
- fail('entry/interpreter digest absent');
45
- const physical = (path) => { try {
46
- return realpathSync(path);
47
- }
48
- catch {
49
- return fail('selected member absent ' + path);
50
- } };
51
- const entryMount = runtimeBinding.members.find(m => m.coordinate === p.root + '/' + p.entry);
52
- if (!entryMount)
53
- return fail('entry mount absent from host image');
54
- const levels = p.entry.split('/').length;
55
- let physicalRoot = physical(entryMount.path);
56
- for (let i = 0; i < levels; i++)
57
- physicalRoot = resolve(physicalRoot, '..');
58
- const interpreter = physical(runtimeBinding.path);
59
- const interpreterBytes = readBounded(interpreter, p.interpreter.bytes);
60
- if (interpreterBytes.length !== p.interpreter.bytes || sha(interpreterBytes) !== p.interpreter.digest)
61
- fail('interpreter bytes differ');
62
- const members = p.members.map(m => { const mounted = runtimeBinding.members.find(one => one.coordinate === p.root + '/' + m.coordinate); if (!mounted)
63
- return fail('member absent from actual host image ' + m.coordinate); const path = physical(mounted.path), r = relative(physicalRoot, path); if (r === '..' || r.startsWith('../') || isAbsolute(r))
64
- fail('member outside selected implementation'); const b = readBounded(path, m.bytes); if (b.length !== m.bytes || sha(b) !== m.digest)
65
- fail('member bytes differ ' + m.coordinate); return { path, digest: m.digest }; });
66
- const handle = Object.freeze({ identity: sha(canonicalJson([authenticated.line, parent.identity])) });
67
- verified.set(handle, { alias: p.alias, interpreter, interpreterDigest: p.interpreter.digest, entry: physical(resolve(physicalRoot, p.entry)), root: physicalRoot, members, condition: p.condition });
68
- return handle;
69
- }
70
- /** Only the guarded instrument can obtain this from a verified opaque handle.
71
- * Put it in the signed native image; never accept it from a world proposal. */
72
- export const nativeProgramProjection = retainedProjection(verified, fail);
1
+ var x=Object.defineProperty;var l=(s,c)=>x(s,"name",{value:c,configurable:!0});import{retainedProjection as M}from"./reading.js";import{fieldNames as W}from"./reading.js";import{sha256 as h}from"../hash.js";import{isAbsolute as f,resolve as j,relative as z}from"node:path";import{realpathSync as D}from"node:fs";import{authenticateSignedPort as F,nativeParentInputBytes as J,canonicalJson as u}from"./reading.js";import{readBounded as k}from"./generated.js";const r=l(s=>{throw Error("REFUSE\xB7native program "+s)},"fail"),m=W,A=new WeakMap;function Q(s,c,i,o){const v=F(s,c),e=v.profile;(!e||m(e)!=="alias,condition,coordinate,entry,interpreter,limits,members,profile,root,selector"||e.profile!=="host-native-program@1"||e.coordinate!==c||typeof e.alias!="string"||!e.alias.length||e.alias.includes("\0")||typeof e.condition!="string"||!e.condition.length)&&r("selection absent/unknown"),(m(e.selector??{})!=="binding,implementation,port"||u(e.selector)!==u({port:i.port,binding:i.binding,implementation:i.implementation}))&&r("selection differs from parent"),(m(e.limits??{})!=="bytes,members"||!Number.isSafeInteger(e.limits.members)||e.limits.members<1||!Number.isSafeInteger(e.limits.bytes)||e.limits.bytes<1||e.limits.bytes>J(s,i))&&r("implementation resource absent/exceeds Root"),[i.identity,i.instrument,i.policy,i.authority,i.implementation].some(t=>typeof t!="string"||!/^sha256:[0-9a-f]{64}$/.test(t))&&r("parent identity absent"),(!Array.isArray(e.members)||e.members.length>e.limits.members||typeof e.root!="string"||f(e.root)||e.root.split("/").some(t=>!t||t==="."||t==="..")||!e.interpreter||typeof e.interpreter.path!="string"||f(e.interpreter.path)||e.interpreter.path!==o.coordinate||m(e.interpreter)!=="bytes,digest,path"||!Number.isSafeInteger(e.interpreter.bytes)||e.interpreter.bytes<1)&&r("interpreter/implementation context absent"),(!o||o.path!==i.runtime||o.digest!==e.interpreter.digest||!i.inputs.some(t=>t[1]===o.digest))&&r("interpreter differs from parent image");let b=e.interpreter.bytes;b>e.limits.bytes&&r("interpreter byte resource");const d=new Set;for(const t of e.members)(!t||m(t)!=="bytes,coordinate,digest"||typeof t.coordinate!="string"||!t.coordinate.length||f(t.coordinate)||t.coordinate.includes("\\")||t.coordinate.split("/").some(n=>!n||n==="."||n==="..")||d.has(t.coordinate)||!/^sha256:[0-9a-f]{64}$/.test(t.digest)||!Number.isSafeInteger(t.bytes)||t.bytes<0)&&r("member identity ambiguous"),d.add(t.coordinate),b+=t.bytes,b>e.limits.bytes&&r("implementation byte resource");(!d.has(e.entry)||!/^sha256:[0-9a-f]{64}$/.test(e.interpreter.digest))&&r("entry/interpreter digest absent");const p=l(t=>{try{return D(t)}catch{return r("selected member absent "+t)}},"physical"),S=o.members.find(t=>t.coordinate===e.root+"/"+e.entry);if(!S)return r("entry mount absent from host image");const E=e.entry.split("/").length;let a=p(S.path);for(let t=0;t<E;t++)a=j(a,"..");const N=p(o.path),P=k(N,e.interpreter.bytes);(P.length!==e.interpreter.bytes||h(P)!==e.interpreter.digest)&&r("interpreter bytes differ");const R=e.members.map(t=>{const n=o.members.find($=>$.coordinate===e.root+"/"+t.coordinate);if(!n)return r("member absent from actual host image "+t.coordinate);const y=p(n.path),g=z(a,y);(g===".."||g.startsWith("../")||f(g))&&r("member outside selected implementation");const w=k(y,t.bytes);return(w.length!==t.bytes||h(w)!==t.digest)&&r("member bytes differ "+t.coordinate),{path:y,digest:t.digest}}),I=Object.freeze({identity:h(u([v.line,i.identity]))});return A.set(I,{alias:e.alias,interpreter:N,interpreterDigest:e.interpreter.digest,entry:p(j(a,e.entry)),root:a,members:R,condition:e.condition}),I}l(Q,"verifyNativeProgram");const T=M(A,r);export{T as nativeProgramProjection,Q as verifyNativeProgram};
@@ -1,187 +1,3 @@
1
- import { sha256 as digest } from "../hash.js";
2
- /** Host-only controlled Node adapter; pure planning remains in planner.ts. */
3
- import { realpathSync } from 'node:fs';
4
- import { isAbsolute } from 'node:path';
5
- import { readBoundedFile } from "./bounded-file.js";
6
- import { executeLot } from "./command.js";
7
- import { moduleClosure } from "./module-closure.js";
8
- import { planJobs } from "./jobs.js";
9
- const refuse = (why) => { throw Error('REFUSE·job adapter ' + why); };
10
- const fileDigest = (path, limit) => { try {
11
- return digest(readBoundedFile(path, limit, path));
12
- }
13
- catch {
14
- return refuse('image member absent ' + path);
15
- } };
16
- const capturedCommand = (value) => { if (!value || typeof value !== 'object' || Array.isArray(value))
17
- return false; const v = value; return Object.keys(v).sort().join(',') === 'exitStatus,stderr,stdout' && Number.isSafeInteger(v.exitStatus) && v.exitStatus >= 0 && typeof v.stdout === 'string' && typeof v.stderr === 'string'; };
18
- const admittedImages = new WeakMap();
19
- /** Image/runtime condition and locations are instrument-admitted inputs, selected
20
- * before requests. Condition includes trusted Node builtins/platform libraries;
21
- * a binary's file digest alone does not seal every dynamic platform library. */
22
- export function prepareNodeImage(input, inputImage) {
23
- if (!inputImage?.commandPort)
24
- refuse('missing admitted command port');
25
- if (!inputImage || !isAbsolute(inputImage.cwd) || !inputImage.condition)
26
- refuse('missing admitted Node image condition');
27
- const host = { ...input, budget: { ...input.budget }, members: input.members.map(m => ({ ...m, bytes: new Uint8Array(m.bytes) })), loads: input.loads.map(e => ({ ...e, target: typeof e.target === 'string' ? e.target : { ...e.target } })), bindings: input.bindings.map(b => ({ ...b, places: [...b.places], args: [...b.args], inputs: [...b.inputs], environment: b.environment.map(p => [...p]), limits: { ...b.limits } })) };
28
- // Validate all declarations and member bytes without any world proposal/launch.
29
- planJobs(host, new TextEncoder().encode('[]'), digest);
30
- const members = new Map(host.members.map(m => [m.coordinate, m])), locations = new Map();
31
- let actualBytes = 0;
32
- for (const member of host.members) {
33
- actualBytes += member.bytes.length;
34
- if (actualBytes > host.budget.bytes)
35
- refuse('image byte resources');
36
- }
37
- const runtimeLocation = inputImage.locations.find(l => l.member === inputImage.runtime);
38
- if (!runtimeLocation || realpathSync(runtimeLocation.path) !== realpathSync(process.execPath))
39
- refuse('runtime differs from executing interpreter');
40
- for (const location of inputImage.locations) {
41
- if (locations.has(location.member) || !members.has(location.member) || !isAbsolute(location.path) || !['binary', 'module', 'data'].includes(location.kind))
42
- refuse('unknown/duplicate image location ' + location.member);
43
- if (fileDigest(location.path, host.budget.bytes) !== members.get(location.member).digest)
44
- refuse('image bytes differ ' + location.member);
45
- locations.set(location.member, { ...location });
46
- }
47
- if (locations.size !== members.size)
48
- refuse('image omitted handed member');
49
- const texts = new Map([...members].filter(([c]) => locations.get(c).kind === 'module' || c.endsWith('.json')).map(([c, m]) => { let source; try {
50
- source = new TextDecoder('utf-8', { fatal: true, ignoreBOM: true }).decode(m.bytes);
51
- }
52
- catch {
53
- return refuse('invalid text member ' + c);
54
- } return [c, { source, digest: m.digest }]; }));
55
- const snapshot = { identity: digest(new TextEncoder().encode(JSON.stringify([...members].map(([c, m]) => [c, m.digest]).sort()) + '\n')), entry: '', members: texts };
56
- if (!inputImage.runtime || locations.get(inputImage.runtime)?.kind !== 'binary')
57
- refuse('selected Node runtime absent');
58
- if (inputImage.preload !== undefined && locations.get(inputImage.preload)?.kind !== 'module')
59
- refuse('selected Node preloader absent');
60
- if (!Array.isArray(inputImage.nativePreloadMembers) || (inputImage.preload !== undefined && !inputImage.nativePreloadMembers.includes(inputImage.preload)) || new Set(inputImage.nativePreloadMembers).size !== inputImage.nativePreloadMembers.length || inputImage.nativePreloadMembers.some(c => !members.has(c)))
61
- refuse('native preloader members not handed');
62
- const nativePreloadMembers = [...inputImage.nativePreloadMembers];
63
- const proofs = new Map();
64
- for (const binding of host.bindings) {
65
- if (locations.get(binding.program)?.kind !== 'module' || binding.interpreter !== inputImage.runtime)
66
- refuse('unsupported raw binary profile ' + binding.id);
67
- if (binding.kind === 'process' && binding.entry !== undefined)
68
- refuse('process entry unsupported ' + binding.id);
69
- const roots = [binding.program, ...(binding.entry ? [binding.entry] : [])].filter(c => locations.get(c).kind === 'module');
70
- if (!roots.length && locations.get(binding.program).kind !== 'binary')
71
- refuse('unsupported program member ' + binding.program);
72
- if (binding.interpreter && locations.get(binding.interpreter).kind !== 'binary')
73
- refuse('interpreter is not a selected binary');
74
- if (binding.kind === 'worker' && (!binding.entry || locations.get(binding.entry).kind !== 'module'))
75
- refuse('worker entry is not a selected module');
76
- const reached = roots.flatMap(entry => moduleClosure({ ...snapshot, entry }, () => undefined));
77
- const declaredTargets = new Set([inputImage.preload, binding.program, binding.interpreter, binding.entry, ...binding.inputs, ...host.loads.map(e => typeof e.target === 'string' ? e.target : '')].filter(Boolean));
78
- for (const reading of reached)
79
- if (!declaredTargets.has(reading.coordinate))
80
- refuse('literal module dependency not declared ' + reading.coordinate);
81
- proofs.set(binding.id, JSON.stringify(reached));
82
- }
83
- host.policy = digest(new TextEncoder().encode(JSON.stringify([host.policy, 'captured-command/1', inputImage.condition, inputImage.runtime, inputImage.preload, nativePreloadMembers.map(c => [c, members.get(c).digest]), snapshot.identity, inputImage.commandPort ?? null, [...proofs]]) + '\n'));
84
- const handle = Object.freeze({ identity: digest(new TextEncoder().encode(JSON.stringify([host.place, host.policy, snapshot.identity]))) });
85
- admittedImages.set(handle, { handoff: host, image: { cwd: inputImage.cwd, condition: inputImage.condition, runtime: inputImage.runtime, preload: inputImage.preload, nativePreloadMembers, ...(inputImage.hostLoader ? { hostLoader: inputImage.hostLoader } : {}), ...(inputImage.commandPort ? { commandPort: { ...inputImage.commandPort, closure: [...inputImage.commandPort.closure], environment: [...inputImage.commandPort.environment] } } : {}), locations: [...locations.values()] }, locations, proofs, snapshot });
86
- return handle;
87
- }
88
- /** Exact expectations from the same opaque host image used by execution. */
89
- export function plannedJobs(handle, request) { const ready = admittedImages.get(handle); if (!ready)
90
- return refuse('unknown prepared host image'); return planJobs(ready.handoff, request, digest).map(({ id, identity }) => ({ id, identity })); }
91
- function parentExecution(ready, job) { const port = ready.image.commandPort; if (!port)
92
- return refuse('producer requires declared parent port'); return { identity: job.identity, port: port.coordinate, binding: job.id, implementation: job.program[1], instrument: ready.handoff.instrument, policy: ready.handoff.policy, authority: ready.handoff.authoritySnapshot, inputs: job.edges.map(e => [e.target, e.digest]).filter((p, i, all) => all.findIndex(q => q[0] === p[0]) === i), environment: job.environment, argv: invocation(ready, job).args, cwd: ready.image.cwd, runtime: ready.locations.get(ready.image.runtime).path, timeoutMs: Math.min(port.timeoutMs, job.limits.timeMs), responseBytes: Math.min(port.responseBytes, job.limits.responseBytes) }; }
93
- export function plannedParentExecutions(handle, request) { const ready = admittedImages.get(handle); if (!ready)
94
- return refuse('unknown prepared host image'); return planJobs(ready.handoff, request, digest).map(job => parentExecution(ready, job)); }
95
- const invocation = (ready, job) => {
96
- const program = ready.locations.get(job.program[0]), interpreter = job.interpreter && ready.locations.get(job.interpreter[0]);
97
- if (!interpreter)
98
- return { command: program.path, args: [...job.args], cwd: ready.image.cwd };
99
- const host = ready.image.hostLoader;
100
- if (!host)
101
- return refuse('fixed loader envelope absent');
102
- const url = new URL(host.preload);
103
- url.searchParams.set('bytes', String(ready.handoff.budget.bytes));
104
- const envelope = Buffer.from(JSON.stringify({ format: 'native-image-envelope/1', entries: host.entries, declaration: host.declaration, execution: { runtime: ready.locations.get(ready.image.runtime).path, cwd: ready.image.cwd, mounts: ready.image.locations.map(location => ({ coordinate: location.member, path: location.path, kind: location.kind })) } }));
105
- return { command: interpreter.path, args: ['--import', url.href, ...(ready.image.preload ? ['--import', ready.locations.get(ready.image.preload).path] : []), program.path, ...(job.kind === 'worker' ? [ready.locations.get(job.entry[0]).path] : []), ...job.args], cwd: ready.image.cwd, hostEnvelope: envelope, envelopeBytes: ready.handoff.budget.bytes };
106
- };
107
- /** No partial member escapes a failed batch. Uses the existing bounded async
108
- * child-group executor; worker launcher is itself an exact selected module. */
109
- export async function executeJobs(handle, request, options) {
110
- const ready = admittedImages.get(handle);
111
- if (!ready)
112
- return refuse('unknown prepared host image');
113
- const { phase, signal, trace } = options;
114
- if (phase !== 'act')
115
- refuse('invocation forbidden during ' + phase);
116
- if (signal?.aborted)
117
- refuse('interrupted before batch');
118
- const jobs = planJobs(ready.handoff, request, digest);
119
- // Complete batch and all locations are verified before invoking any program.
120
- for (const member of ready.handoff.members) {
121
- const loc = ready.locations.get(member.coordinate);
122
- if (fileDigest(loc.path, ready.handoff.budget.bytes) !== member.digest)
123
- refuse('image bytes differ ' + member.coordinate);
124
- }
125
- if (!jobs.length)
126
- return [];
127
- const slots = Math.min(...jobs.map(j => j.limits.slots)), controller = new AbortController(), abort = controller.abort.bind(controller, undefined);
128
- signal?.addEventListener('abort', abort, { once: true });
129
- if (signal?.aborted)
130
- abort();
131
- const results = new Array(jobs.length);
132
- let next = 0;
133
- let primary;
134
- const work = async () => {
135
- while (!controller.signal.aborted) {
136
- const index = next++;
137
- if (index >= jobs.length)
138
- return;
139
- const job = jobs[index], fixed = invocation(ready, job), implementation = job.program[1], port = { ...ready.image.commandPort, timeoutMs: Math.min(ready.image.commandPort.timeoutMs, job.limits.timeMs), responseBytes: Math.min(ready.image.commandPort.responseBytes, job.limits.responseBytes) };
140
- const proofFor = () => { for (const edge of job.edges) {
141
- const loc = ready.locations.get(edge.target);
142
- if (!loc || fileDigest(loc.path, ready.handoff.budget.bytes) !== edge.digest)
143
- return 'unmeasured';
144
- } const roots = [job.program[0], ...(job.entry ? [job.entry[0]] : [])].filter(c => ready.locations.get(c).kind === 'module'); const actual = JSON.stringify(roots.flatMap(entry => moduleClosure({ ...ready.snapshot, entry }, () => undefined))); return actual === ready.proofs.get(job.id) ? 'verified' : 'unmeasured'; };
145
- trace?.({ id: job.id, phase: 'start' });
146
- let custody;
147
- try {
148
- if (options.custody)
149
- custody = await options.custody.open(parentExecution(ready, job));
150
- if (!custody)
151
- return refuse('native descendant custody missing ' + job.id);
152
- const envelope = JSON.parse(Buffer.from(fixed.hostEnvelope).toString('utf8'));
153
- envelope.descendant = custody.descendant;
154
- if (!envelope.descendant)
155
- return refuse('fixed descendant envelope absent ' + job.id);
156
- const guarded = { ...fixed, hostEnvelope: Buffer.from(JSON.stringify(envelope)) };
157
- const result = await executeLot({ port, lot: { identity: job.identity, requests: [new TextDecoder().decode(job.payload)] }, phase, signal: controller.signal, environment: Object.fromEntries(job.environment), host: { admitsDeclaration: p => JSON.stringify(p) === JSON.stringify(port), covers: c => c === port.coordinate && ready.handoff.bindings.find(b => b.id === job.id).places.includes(ready.handoff.place), verifies: d => ready.handoff.members.some(m => m.digest === d && fileDigest(ready.locations.get(m.coordinate).path, ready.handoff.budget.bytes) === d), resolve: () => guarded, loaderClosure: (_p, actual) => JSON.stringify(actual) === JSON.stringify(guarded) ? proofFor() : 'unmeasured' }, accepts: (response, index) => index === 0 && capturedCommand(response) });
158
- custody?.assertClosed();
159
- results[index] = { id: job.id, identity: job.identity, responses: result.members };
160
- }
161
- catch (error) {
162
- if (primary === undefined)
163
- primary = error;
164
- controller.abort();
165
- throw error;
166
- }
167
- finally {
168
- await custody?.close();
169
- trace?.({ id: job.id, phase: 'end' });
170
- }
171
- }
172
- };
173
- try {
174
- const settled = await Promise.allSettled(Array.from({ length: Math.min(slots, jobs.length) }, work));
175
- if (primary !== undefined)
176
- throw primary;
177
- const failed = settled.find(x => x.status === 'rejected');
178
- if (failed?.status === 'rejected')
179
- throw failed.reason;
180
- if (controller.signal.aborted || results.some(x => x === undefined) || results.filter(Boolean).length !== jobs.length)
181
- refuse('interrupted/incomplete batch');
182
- return results;
183
- }
184
- finally {
185
- signal?.removeEventListener('abort', abort);
186
- }
187
- }
1
+ var F=Object.defineProperty;var d=(r,t)=>F(r,"name",{value:t,configurable:!0});import{sha256 as w}from"../hash.js";import{realpathSync as A}from"node:fs";import{isAbsolute as L}from"node:path";import{readBoundedFile as U}from"./bounded-file.js";import{executeLot as q}from"./command.js";import{moduleClosure as T}from"./module-closure.js";import{planJobs as N}from"./jobs.js";const s=d(r=>{throw Error("REFUSE\xB7job adapter "+r)},"refuse"),O=d((r,t)=>{try{return w(U(r,t,r))}catch{return s("image member absent "+r)}},"fileDigest"),R=d(r=>{if(!r||typeof r!="object"||Array.isArray(r))return!1;const t=r;return Object.keys(t).sort().join(",")==="exitStatus,stderr,stdout"&&Number.isSafeInteger(t.exitStatus)&&t.exitStatus>=0&&typeof t.stdout=="string"&&typeof t.stderr=="string"},"capturedCommand"),B=new WeakMap;function Z(r,t){t?.commandPort||s("missing admitted command port"),(!t||!L(t.cwd)||!t.condition)&&s("missing admitted Node image condition");const i={...r,budget:{...r.budget},members:r.members.map(e=>({...e,bytes:new Uint8Array(e.bytes)})),loads:r.loads.map(e=>({...e,target:typeof e.target=="string"?e.target:{...e.target}})),bindings:r.bindings.map(e=>({...e,places:[...e.places],args:[...e.args],inputs:[...e.inputs],environment:e.environment.map(c=>[...c]),limits:{...e.limits}}))};N(i,new TextEncoder().encode("[]"),w);const n=new Map(i.members.map(e=>[e.coordinate,e])),a=new Map;let l=0;for(const e of i.members)l+=e.bytes.length,l>i.budget.bytes&&s("image byte resources");const g=t.locations.find(e=>e.member===t.runtime);(!g||A(g.path)!==A(process.execPath))&&s("runtime differs from executing interpreter");for(const e of t.locations)(a.has(e.member)||!n.has(e.member)||!L(e.path)||!["binary","module","data"].includes(e.kind))&&s("unknown/duplicate image location "+e.member),O(e.path,i.budget.bytes)!==n.get(e.member).digest&&s("image bytes differ "+e.member),a.set(e.member,{...e});a.size!==n.size&&s("image omitted handed member");const m=new Map([...n].filter(([e])=>a.get(e).kind==="module"||e.endsWith(".json")).map(([e,c])=>{let M;try{M=new TextDecoder("utf-8",{fatal:!0,ignoreBOM:!0}).decode(c.bytes)}catch{return s("invalid text member "+e)}return[e,{source:M,digest:c.digest}]})),k={identity:w(new TextEncoder().encode(JSON.stringify([...n].map(([e,c])=>[e,c.digest]).sort())+`
2
+ `)),entry:"",members:m};(!t.runtime||a.get(t.runtime)?.kind!=="binary")&&s("selected Node runtime absent"),t.preload!==void 0&&a.get(t.preload)?.kind!=="module"&&s("selected Node preloader absent"),(!Array.isArray(t.nativePreloadMembers)||t.preload!==void 0&&!t.nativePreloadMembers.includes(t.preload)||new Set(t.nativePreloadMembers).size!==t.nativePreloadMembers.length||t.nativePreloadMembers.some(e=>!n.has(e)))&&s("native preloader members not handed");const u=[...t.nativePreloadMembers],v=new Map;for(const e of i.bindings){(a.get(e.program)?.kind!=="module"||e.interpreter!==t.runtime)&&s("unsupported raw binary profile "+e.id),e.kind==="process"&&e.entry!==void 0&&s("process entry unsupported "+e.id);const c=[e.program,...e.entry?[e.entry]:[]].filter(o=>a.get(o).kind==="module");!c.length&&a.get(e.program).kind!=="binary"&&s("unsupported program member "+e.program),e.interpreter&&a.get(e.interpreter).kind!=="binary"&&s("interpreter is not a selected binary"),e.kind==="worker"&&(!e.entry||a.get(e.entry).kind!=="module")&&s("worker entry is not a selected module");const M=c.flatMap(o=>T({...k,entry:o},()=>{})),f=new Set([t.preload,e.program,e.interpreter,e.entry,...e.inputs,...i.loads.map(o=>typeof o.target=="string"?o.target:"")].filter(Boolean));for(const o of M)f.has(o.coordinate)||s("literal module dependency not declared "+o.coordinate);v.set(e.id,JSON.stringify(M))}i.policy=w(new TextEncoder().encode(JSON.stringify([i.policy,"captured-command/1",t.condition,t.runtime,t.preload,u.map(e=>[e,n.get(e).digest]),k.identity,t.commandPort??null,[...v]])+`
3
+ `));const x=Object.freeze({identity:w(new TextEncoder().encode(JSON.stringify([i.place,i.policy,k.identity])))});return B.set(x,{handoff:i,image:{cwd:t.cwd,condition:t.condition,runtime:t.runtime,preload:t.preload,nativePreloadMembers:u,...t.hostLoader?{hostLoader:t.hostLoader}:{},...t.commandPort?{commandPort:{...t.commandPort,closure:[...t.commandPort.closure],environment:[...t.commandPort.environment]}}:{},locations:[...a.values()]},locations:a,proofs:v,snapshot:k}),x}d(Z,"prepareNodeImage");function $(r,t){const i=B.get(r);return i?N(i.handoff,t,w).map(({id:n,identity:a})=>({id:n,identity:a})):s("unknown prepared host image")}d($,"plannedJobs");function C(r,t){const i=r.image.commandPort;return i?{identity:t.identity,port:i.coordinate,binding:t.id,implementation:t.program[1],instrument:r.handoff.instrument,policy:r.handoff.policy,authority:r.handoff.authoritySnapshot,inputs:t.edges.map(n=>[n.target,n.digest]).filter((n,a,l)=>l.findIndex(g=>g[0]===n[0])===a),environment:t.environment,argv:z(r,t).args,cwd:r.image.cwd,runtime:r.locations.get(r.image.runtime).path,timeoutMs:Math.min(i.timeoutMs,t.limits.timeMs),responseBytes:Math.min(i.responseBytes,t.limits.responseBytes)}:s("producer requires declared parent port")}d(C,"parentExecution");function j(r,t){const i=B.get(r);return i?N(i.handoff,t,w).map(n=>C(i,n)):s("unknown prepared host image")}d(j,"plannedParentExecutions");const z=d((r,t)=>{const i=r.locations.get(t.program[0]),n=t.interpreter&&r.locations.get(t.interpreter[0]);if(!n)return{command:i.path,args:[...t.args],cwd:r.image.cwd};const a=r.image.hostLoader;if(!a)return s("fixed loader envelope absent");const l=new URL(a.preload);l.searchParams.set("bytes",String(r.handoff.budget.bytes));const g=Buffer.from(JSON.stringify({format:"native-image-envelope/1",entries:a.entries,declaration:a.declaration,execution:{runtime:r.locations.get(r.image.runtime).path,cwd:r.image.cwd,mounts:r.image.locations.map(m=>({coordinate:m.member,path:m.path,kind:m.kind}))}}));return{command:n.path,args:["--import",l.href,...r.image.preload?["--import",r.locations.get(r.image.preload).path]:[],i.path,...t.kind==="worker"?[r.locations.get(t.entry[0]).path]:[],...t.args],cwd:r.image.cwd,hostEnvelope:g,envelopeBytes:r.handoff.budget.bytes}},"invocation");async function I(r,t,i){const n=B.get(r);if(!n)return s("unknown prepared host image");const{phase:a,signal:l,trace:g}=i;a!=="act"&&s("invocation forbidden during "+a),l?.aborted&&s("interrupted before batch");const m=N(n.handoff,t,w);for(const f of n.handoff.members){const o=n.locations.get(f.coordinate);O(o.path,n.handoff.budget.bytes)!==f.digest&&s("image bytes differ "+f.coordinate)}if(!m.length)return[];const k=Math.min(...m.map(f=>f.limits.slots)),u=new AbortController,v=u.abort.bind(u,void 0);l?.addEventListener("abort",v,{once:!0}),l?.aborted&&v();const x=new Array(m.length);let e=0,c;const M=d(async()=>{for(;!u.signal.aborted;){const f=e++;if(f>=m.length)return;const o=m[f],S=z(n,o),W=o.program[1],E={...n.image.commandPort,timeoutMs:Math.min(n.image.commandPort.timeoutMs,o.limits.timeMs),responseBytes:Math.min(n.image.commandPort.responseBytes,o.limits.responseBytes)},D=d(()=>{for(const b of o.edges){const p=n.locations.get(b.target);if(!p||O(p.path,n.handoff.budget.bytes)!==b.digest)return"unmeasured"}const h=[o.program[0],...o.entry?[o.entry[0]]:[]].filter(b=>n.locations.get(b).kind==="module");return JSON.stringify(h.flatMap(b=>T({...n.snapshot,entry:b},()=>{})))===n.proofs.get(o.id)?"verified":"unmeasured"},"proofFor");g?.({id:o.id,phase:"start"});let P;try{if(i.custody&&(P=await i.custody.open(C(n,o))),!P)return s("native descendant custody missing "+o.id);const h=JSON.parse(Buffer.from(S.hostEnvelope).toString("utf8"));if(h.descendant=P.descendant,!h.descendant)return s("fixed descendant envelope absent "+o.id);const J={...S,hostEnvelope:Buffer.from(JSON.stringify(h))},b=await q({port:E,lot:{identity:o.identity,requests:[new TextDecoder().decode(o.payload)]},phase:a,signal:u.signal,environment:Object.fromEntries(o.environment),host:{admitsDeclaration:d(p=>JSON.stringify(p)===JSON.stringify(E),"admitsDeclaration"),covers:d(p=>p===E.coordinate&&n.handoff.bindings.find(y=>y.id===o.id).places.includes(n.handoff.place),"covers"),verifies:d(p=>n.handoff.members.some(y=>y.digest===p&&O(n.locations.get(y.coordinate).path,n.handoff.budget.bytes)===p),"verifies"),resolve:d(()=>J,"resolve"),loaderClosure:d((p,y)=>JSON.stringify(y)===JSON.stringify(J)?D():"unmeasured","loaderClosure")},accepts:d((p,y)=>y===0&&R(p),"accepts")});P?.assertClosed(),x[f]={id:o.id,identity:o.identity,responses:b.members}}catch(h){throw c===void 0&&(c=h),u.abort(),h}finally{await P?.close(),g?.({id:o.id,phase:"end"})}}},"work");try{const f=await Promise.allSettled(Array.from({length:Math.min(k,m.length)},M));if(c!==void 0)throw c;const o=f.find(S=>S.status==="rejected");if(o?.status==="rejected")throw o.reason;return(u.signal.aborted||x.some(S=>S===void 0)||x.filter(Boolean).length!==m.length)&&s("interrupted/incomplete batch"),x}finally{l?.removeEventListener("abort",v)}}d(I,"executeJobs");export{I as executeJobs,$ as plannedJobs,j as plannedParentExecutions,Z as prepareNodeImage};
@@ -1,159 +1 @@
1
- const refuse = (why) => { throw Error('REFUSE·native descendant ' + why); };
2
- export function nodeLaunch(args) {
3
- if (!Array.isArray(args) || args.some(s => typeof s !== 'string' || s.includes('\0')))
4
- refuse('argv invalid');
5
- let mode = 'commonjs', evalText, entry, test = false;
6
- const imports = [];
7
- for (let i = 0; i < args.length; i++) {
8
- const arg = args[i];
9
- if (arg === '--') {
10
- entry = args[++i];
11
- break;
12
- }
13
- if (arg === '--input-type=module') {
14
- mode = 'module';
15
- continue;
16
- }
17
- if (arg === '--input-type=commonjs') {
18
- mode = 'commonjs';
19
- continue;
20
- }
21
- if (arg === '--input-type') {
22
- const value = args[++i];
23
- if (value !== 'module' && value !== 'commonjs')
24
- refuse('input type unsupported');
25
- mode = value;
26
- continue;
27
- }
28
- if (arg === '-e' || arg === '--eval') {
29
- if (evalText !== undefined)
30
- refuse('eval ambiguous');
31
- evalText = args[++i];
32
- if (evalText === undefined)
33
- refuse('eval absent');
34
- continue;
35
- }
36
- if (arg.startsWith('--eval=')) {
37
- if (evalText !== undefined)
38
- refuse('eval ambiguous');
39
- evalText = arg.slice(7);
40
- continue;
41
- }
42
- if (arg === '--import' || arg === '--require' || arg === '-r') {
43
- const value = args[++i];
44
- if (value === undefined)
45
- refuse('preload absent');
46
- imports.push(value);
47
- continue;
48
- }
49
- if (arg.startsWith('--import=') || arg.startsWith('--require=')) {
50
- imports.push(arg.slice(arg.indexOf('=') + 1));
51
- continue;
52
- }
53
- if (arg === '--test') {
54
- test = true;
55
- continue;
56
- }
57
- if (arg.startsWith('--test-') || arg === '--experimental-strip-types' || arg === '--experimental-transform-types')
58
- continue;
59
- if (arg.startsWith('-'))
60
- refuse('option unsupported ' + arg);
61
- if (evalText !== undefined)
62
- break;
63
- entry = arg;
64
- break;
65
- }
66
- if (evalText !== undefined) {
67
- if (entry !== undefined)
68
- refuse('eval plus executable file');
69
- return { kind: 'eval', mode, text: evalText, args: [...args], imports };
70
- }
71
- if (!entry)
72
- refuse(test ? 'implicit test discovery unsupported' : 'executable target absent');
73
- return { kind: 'file', entry, args: [...args], imports, test };
74
- }
75
- /** Pure host glue. Inputs are projections obtained from verified opaque native
76
- * program handles under Root's guard, never accepted from a world proposal.
77
- * Selection names preserve argv; they confer no independent authority. */
78
- import { isAbsolute, resolve } from 'node:path';
79
- import { isSha256 } from "../hash.js";
80
- const programFail = (why) => { throw Error('REFUSE·native launch ' + why); };
81
- const digest = isSha256;
82
- const exactPath = (value) => typeof value === 'string' && isAbsolute(value) && resolve(value) === value;
83
- function graph(program) {
84
- if (!program || typeof program.alias !== 'string' || !program.alias.length || !exactPath(program.interpreter) || !digest(program.interpreterDigest) || !exactPath(program.entry) || !exactPath(program.root) || !Array.isArray(program.members))
85
- programFail('verified program projection absent');
86
- const paths = new Set();
87
- for (const member of program.members) {
88
- if (!member || !exactPath(member.path) || !digest(member.digest) || paths.has(member.path))
89
- programFail('program graph member ambiguous');
90
- paths.add(member.path);
91
- }
92
- if (!paths.has(program.entry))
93
- programFail('program entry not in selected graph');
94
- }
95
- /** Only an exact, unique declared alias selects a native program. No PATH,
96
- * filename heuristics, option rewriting or consumer-specific names occur here. */
97
- export function projectNativeProgramLaunch(programs, program, args, runtime) {
98
- if (!Array.isArray(programs) || typeof program !== 'string' || !program.length || !Array.isArray(args) || args.some(arg => typeof arg !== 'string' || arg.includes('\0')) || !runtime || !exactPath(runtime.path) || !digest(runtime.digest))
99
- programFail('invocation context absent');
100
- const matches = programs.filter(p => p?.alias === program);
101
- if (matches.length !== 1)
102
- programFail(matches.length ? 'program alias ambiguous ' + program : 'program alias undeclared ' + program);
103
- const selected = matches[0];
104
- graph(selected);
105
- if (selected.interpreter !== runtime.path || selected.interpreterDigest !== runtime.digest)
106
- programFail('selected interpreter differs');
107
- return Object.freeze({ interpreter: selected.interpreter, interpreterDigest: selected.interpreterDigest, entry: selected.entry, args: Object.freeze([...args]) });
108
- }
109
- /** Select a package-resolution context only for the exact reached parent member.
110
- * Root must validate the supplied parent digest against actual bytes first.
111
- * Node still performs actual resolution; Root checks the returned target digest
112
- * before handing it back. Merely sharing a path prefix grants no membership. */
113
- export function selectNativeProgramParent(programs, parent) {
114
- if (!Array.isArray(programs) || !parent || !exactPath(parent.path) || !digest(parent.digest))
115
- programFail('parent content context absent');
116
- const matches = programs.filter(p => Array.isArray(p?.members) && p.members.some((m) => m?.path === parent.path && m.digest === parent.digest));
117
- if (matches.length !== 1)
118
- programFail(matches.length ? 'parent graph ambiguous' : 'parent not in selected graph');
119
- const selected = matches[0];
120
- graph(selected);
121
- return Object.freeze({ parent: parent.path, root: selected.root, members: Object.freeze(selected.members.map((member) => Object.freeze({ ...member }))) });
122
- }
123
- import { createHash } from 'node:crypto';
124
- import { pathToFileURL } from 'node:url';
125
- import { canonicalJson } from "./reading.js";
126
- export function retainedNativeEvalMatches(record, actual) {
127
- if (!record || record.kind !== 'derived-executable/1' || record.target?.kind !== 'eval' || !actual || !Array.isArray(actual.argv) || !Array.isArray(actual.rootPrefix) || !exactPath(actual.cwd) || !exactPath(actual.runtime) || !Array.isArray(actual.environment))
128
- return false;
129
- if (actual.rootPrefix.some((arg, i) => actual.argv[i] !== arg) || canonicalJson(actual.argv) !== canonicalJson(record.target.argv) || actual.cwd !== record.target.cwd || actual.cwd !== record.invocation.cwd || actual.runtime !== record.invocation.runtime || canonicalJson(actual.environment) !== canonicalJson(record.invocation.environment) || canonicalJson(actual.argv.slice(actual.rootPrefix.length)) !== canonicalJson(record.invocation.argv))
130
- return false;
131
- let launch;
132
- try {
133
- launch = nodeLaunch(actual.argv);
134
- }
135
- catch {
136
- return false;
137
- }
138
- if (launch.kind !== 'eval' || launch.text !== record.target.text || launch.mode !== record.mode)
139
- return false;
140
- const bytes = Buffer.from(launch.text, 'utf8');
141
- return bytes.toString('utf8') === launch.text && bytes.length === record.byteLength && 'sha256:' + createHash('sha256').update(bytes).digest('hex') === record.digest;
142
- }
143
- /** Exact Node CLI eval origin, not a file-pattern exception. A different URL
144
- * continues through ordinary physical-parent verification and refuses if absent.
145
- * Node's module and CommonJS CLI forms have distinct observed synthetic names. */
146
- export function nativeEvalParent(record, actual) {
147
- if (!retainedNativeEvalMatches(record, actual))
148
- programFail('actual eval differs from Root-retained context');
149
- return Object.freeze({ url: record.mode === 'module' ? pathToFileURL(actual.cwd + '/').href + '[eval1]' : pathToFileURL(resolve(actual.cwd, '[eval]')).href, context: record.identity, digest: record.digest, mode: record.mode });
150
- }
151
- /** Non-authoritative discovery from Node's actual runtime options only. A false
152
- * result confers no permission: physical-parent/load checks remain unchanged.
153
- * Before-fork argv validation and exact retained-record matching are separate. */
154
- export function actualNodeEvalOptions(execArgv) { try {
155
- return nodeLaunch(execArgv).kind === 'eval';
156
- }
157
- catch {
158
- return false;
159
- } }
1
+ var b=Object.defineProperty;var f=(e,t)=>b(e,"name",{value:t,configurable:!0});const u=f(e=>{throw Error("REFUSE\xB7native descendant "+e)},"refuse");function h(e){(!Array.isArray(e)||e.some(o=>typeof o!="string"||o.includes("\0")))&&u("argv invalid");let t="commonjs",i,r,a=!1;const s=[];for(let o=0;o<e.length;o++){const n=e[o];if(n==="--"){r=e[++o];break}if(n==="--input-type=module"){t="module";continue}if(n==="--input-type=commonjs"){t="commonjs";continue}if(n==="--input-type"){const c=e[++o];c!=="module"&&c!=="commonjs"&&u("input type unsupported"),t=c;continue}if(n==="-e"||n==="--eval"){i!==void 0&&u("eval ambiguous"),i=e[++o],i===void 0&&u("eval absent");continue}if(n.startsWith("--eval=")){i!==void 0&&u("eval ambiguous"),i=n.slice(7);continue}if(n==="--import"||n==="--require"||n==="-r"){const c=e[++o];c===void 0&&u("preload absent"),s.push(c);continue}if(n.startsWith("--import=")||n.startsWith("--require=")){s.push(n.slice(n.indexOf("=")+1));continue}if(n==="--test"){a=!0;continue}if(!(n.startsWith("--test-")||n==="--experimental-strip-types"||n==="--experimental-transform-types")){if(n.startsWith("-")&&u("option unsupported "+n),i!==void 0)break;r=n;break}}return i!==void 0?(r!==void 0&&u("eval plus executable file"),{kind:"eval",mode:t,text:i,args:[...e],imports:s}):(r||u(a?"implicit test discovery unsupported":"executable target absent"),{kind:"file",entry:r,args:[...e],imports:s,test:a})}f(h,"nodeLaunch");import{isAbsolute as x,resolve as v}from"node:path";import{isSha256 as A}from"../hash.js";const d=f(e=>{throw Error("REFUSE\xB7native launch "+e)},"programFail"),m=A,p=f(e=>typeof e=="string"&&x(e)&&v(e)===e,"exactPath");function y(e){(!e||typeof e.alias!="string"||!e.alias.length||!p(e.interpreter)||!m(e.interpreterDigest)||!p(e.entry)||!p(e.root)||!Array.isArray(e.members))&&d("verified program projection absent");const t=new Set;for(const i of e.members)(!i||!p(i.path)||!m(i.digest)||t.has(i.path))&&d("program graph member ambiguous"),t.add(i.path);t.has(e.entry)||d("program entry not in selected graph")}f(y,"graph");function P(e,t,i,r){(!Array.isArray(e)||typeof t!="string"||!t.length||!Array.isArray(i)||i.some(o=>typeof o!="string"||o.includes("\0"))||!r||!p(r.path)||!m(r.digest))&&d("invocation context absent");const a=e.filter(o=>o?.alias===t);a.length!==1&&d(a.length?"program alias ambiguous "+t:"program alias undeclared "+t);const s=a[0];return y(s),(s.interpreter!==r.path||s.interpreterDigest!==r.digest)&&d("selected interpreter differs"),Object.freeze({interpreter:s.interpreter,interpreterDigest:s.interpreterDigest,entry:s.entry,args:Object.freeze([...i])})}f(P,"projectNativeProgramLaunch");function z(e,t){(!Array.isArray(e)||!t||!p(t.path)||!m(t.digest))&&d("parent content context absent");const i=e.filter(a=>Array.isArray(a?.members)&&a.members.some(s=>s?.path===t.path&&s.digest===t.digest));i.length!==1&&d(i.length?"parent graph ambiguous":"parent not in selected graph");const r=i[0];return y(r),Object.freeze({parent:t.path,root:r.root,members:Object.freeze(r.members.map(a=>Object.freeze({...a})))})}f(z,"selectNativeProgramParent");import{createHash as j}from"node:crypto";import{pathToFileURL as g}from"node:url";import{canonicalJson as l}from"./reading.js";function w(e,t){if(!e||e.kind!=="derived-executable/1"||e.target?.kind!=="eval"||!t||!Array.isArray(t.argv)||!Array.isArray(t.rootPrefix)||!p(t.cwd)||!p(t.runtime)||!Array.isArray(t.environment)||t.rootPrefix.some((a,s)=>t.argv[s]!==a)||l(t.argv)!==l(e.target.argv)||t.cwd!==e.target.cwd||t.cwd!==e.invocation.cwd||t.runtime!==e.invocation.runtime||l(t.environment)!==l(e.invocation.environment)||l(t.argv.slice(t.rootPrefix.length))!==l(e.invocation.argv))return!1;let i;try{i=h(t.argv)}catch{return!1}if(i.kind!=="eval"||i.text!==e.target.text||i.mode!==e.mode)return!1;const r=Buffer.from(i.text,"utf8");return r.toString("utf8")===i.text&&r.length===e.byteLength&&"sha256:"+j("sha256").update(r).digest("hex")===e.digest}f(w,"retainedNativeEvalMatches");function F(e,t){return w(e,t)||d("actual eval differs from Root-retained context"),Object.freeze({url:e.mode==="module"?g(t.cwd+"/").href+"[eval1]":g(v(t.cwd,"[eval]")).href,context:e.identity,digest:e.digest,mode:e.mode})}f(F,"nativeEvalParent");function L(e){try{return h(e).kind==="eval"}catch{return!1}}f(L,"actualNodeEvalOptions");export{L as actualNodeEvalOptions,F as nativeEvalParent,h as nodeLaunch,P as projectNativeProgramLaunch,w as retainedNativeEvalMatches,z as selectNativeProgramParent};
@@ -1,45 +1 @@
1
- /** Fixed instrument preload. FD3 is an instrument-created execution envelope,
2
- * never world stdin or workerData. It introduces no key or command grant.
3
- */
4
- import { readSync, closeSync } from 'node:fs';
5
- import { realpathSync } from 'node:fs';
6
- import { installDescendantBoundary } from "./descendants.js";
7
- import { installBoundary, installNativeResolutionReuse } from "./loader.js";
8
- const fail = (why) => { throw Error('REFUSE·native preload ' + why); };
9
- const limit = Number(new URL(import.meta.url).searchParams.get('bytes'));
10
- if (!Number.isSafeInteger(limit) || limit < 1)
11
- fail('missing admitted envelope resources');
12
- const header = Buffer.alloc(8);
13
- let read = 0;
14
- while (read < header.length) {
15
- const n = readSync(3, header, read, header.length - read, null);
16
- if (!n)
17
- fail('truncated host frame');
18
- read += n;
19
- }
20
- const size = header.readBigUInt64BE();
21
- if (size > BigInt(limit))
22
- fail('host envelope bytes exceeded');
23
- const raw = Buffer.alloc(Number(size));
24
- read = 0;
25
- while (read < raw.length) {
26
- const n = readSync(3, raw, read, raw.length - read, null);
27
- if (!n)
28
- fail('truncated host envelope');
29
- read += n;
30
- }
31
- if (readSync(3, Buffer.alloc(1), 0, 1, null) !== 0)
32
- fail('host envelope has trailing bytes');
33
- closeSync(3);
34
- const frame = JSON.parse(raw.toString('utf8'));
35
- if (frame.format !== 'native-image-envelope/1' || !Array.isArray(frame.entries) || !frame.entries.includes(realpathSync(process.argv[1])))
36
- fail('entry outside host image');
37
- if (frame.descendant)
38
- installDescendantBoundary(frame.descendant);
39
- installNativeResolutionReuse(frame.declaration);
40
- if (frame.execution) {
41
- const facade = Object.freeze({ ...frame.execution, preload: frame.descendant?.custodian?.preload, mounts: Object.freeze(frame.execution.mounts.map(mount => Object.freeze({ ...mount }))) });
42
- Object.defineProperty(globalThis, Symbol.for('bound.native.execution@1'), { value: facade, writable: false, configurable: false });
43
- }
44
- const boundary = installBoundary({ ...frame.declaration, entry: realpathSync(process.argv[1]) });
45
- process.once('beforeExit', () => boundary.assertClosed());
1
+ var u=Object.defineProperty;var c=(e,s)=>u(e,"name",{value:s,configurable:!0});import{readSync as i,closeSync as m}from"node:fs";import{realpathSync as f}from"node:fs";import{installDescendantBoundary as p}from"./descendants.js";import{installBoundary as b,installNativeResolutionReuse as g}from"./loader.js";const r=c(e=>{throw Error("REFUSE\xB7native preload "+e)},"fail"),l=Number(new URL(import.meta.url).searchParams.get("bytes"));(!Number.isSafeInteger(l)||l<1)&&r("missing admitted envelope resources");const o=Buffer.alloc(8);let n=0;for(;n<o.length;){const e=i(3,o,n,o.length-n,null);e||r("truncated host frame"),n+=e}const d=o.readBigUInt64BE();d>BigInt(l)&&r("host envelope bytes exceeded");const a=Buffer.alloc(Number(d));for(n=0;n<a.length;){const e=i(3,a,n,a.length-n,null);e||r("truncated host envelope"),n+=e}i(3,Buffer.alloc(1),0,1,null)!==0&&r("host envelope has trailing bytes"),m(3);const t=JSON.parse(a.toString("utf8"));if((t.format!=="native-image-envelope/1"||!Array.isArray(t.entries)||!t.entries.includes(f(process.argv[1])))&&r("entry outside host image"),t.descendant&&p(t.descendant),g(t.declaration),t.execution){const e=Object.freeze({...t.execution,preload:t.descendant?.custodian?.preload,mounts:Object.freeze(t.execution.mounts.map(s=>Object.freeze({...s})))});Object.defineProperty(globalThis,Symbol.for("bound.native.execution@1"),{value:e,writable:!1,configurable:!1})}const h=b({...t.declaration,entry:f(process.argv[1])});process.once("beforeExit",()=>h.assertClosed());
@@ -0,0 +1 @@
1
+ var c=Object.defineProperty;var s=(t,e)=>c(t,"name",{value:e,configurable:!0});import{prepareNativeViewIdentity as g,declaredReadingIdentityLimits as l}from"../reading-identity.js";import{authenticatedStanding as m}from"../admitted-place.js";import{withoutEffects as b}from"../read-only.js";import{BoundRefusal as p}from"../refusals.js";const i=s((t,e=t)=>{throw new p(t,"REFUSE\xB7"+e)},"refuse");function E(t){try{(!t||typeof t.place!="string"||!t.place||!t.instrument?.runtime)&&i("host/context"),t.view!=="lines"&&t.view!=="evidence"&&i("reading-identity/selection","reading-identity/selection unsupported probe form "+String(t.view)+"; supports lines and evidence");const{port:e,counter:n,signal:d}=t;(!e||!/^port\/[^\s]+$/.test(e.coordinate)||!n||!(n.used instanceof Map))&&i("host/context");for(const f of[e.probes,e.responseBytes])(!Number.isSafeInteger(f)||f<1)&&i("host/budget");d?.aborted&&i("host/cancelled");const o=n.used.get(e.coordinate)??0;(!Number.isSafeInteger(o)||o<0)&&i("host/budget");const u=b(()=>l(m(t.place)));o>=Math.min(e.probes,u.probes)&&i("host/budget"),n.used.set(e.coordinate,o+1);const r=g(t);if(d?.aborted&&i("host/cancelled"),r.kind==="refuse")return r;const a={kind:"fact",form:r.view,port:e.coordinate,identity:r.identity,text:r.text,probes:1};return Buffer.byteLength(JSON.stringify(a),"utf8")>e.responseBytes&&i("host/budget"),a}catch(e){return{kind:"refuse",code:e instanceof p?e.code:"reading-identity/failed",diagnostic:e instanceof Error?e.message:"REFUSE\xB7native probe failed"}}}s(E,"prepareNativeProbe");export{E as prepareNativeProbe};
@@ -0,0 +1,5 @@
1
+ var re=Object.defineProperty;var v=(a,t)=>re(a,"name",{value:t,configurable:!0});import{join as H}from"node:path";import{library14_canonical as K,library14_authorityAtEpoch as Q}from"../../vendor/runtime.js";import{library5_decodeReadingWitness as ne,library5_readingWitnessStatementBytes as oe,library5_readingIdentityBytes as se}from"../../vendor/runtime.js";import{fieldOf as i,fieldsOf as R}from"../../fold/claims.js";import{isCeiling as ae}from"../../fold/configures.js";import{lockLines as ce}from"../../fold/keys.js";import{authorityFor as ue,rootSigner as de}from"../../fold/signers.js";import{signaturesOf as pe}from"../../fold/digests.js";import{storeOf as le}from"../../land/ledger.js";import{widenedWithoutWitness as fe}from"../../judge/widening.js";import{sha256 as p,isSha256 as ge}from"../hash.js";import{readPlacePhysicalLines as ye,authenticatePhysicalLinesWitness as me}from"../physical-lines.js";import{verifiedReadingReceipts as he}from"../reading-closures.js";import{canonicalJson as z,authenticateNativeProfile as ve}from"./reading.js";import{readBoundedFile as we}from"./bounded-file.js";const be="bound-reading-witness-admission@1",r=v(a=>{throw Error("REFUSE\xB7reading-witness/"+a)},"fail"),y=v(a=>typeof a=="string"&&a.length>0&&!/[\\\u0000-\u0020\u007f]/.test(a)&&a.split("/").every(t=>t!==""&&t!=="."&&t!==".."),"path");function Se(a){let t;try{t=JSON.parse(i(a,"about"))}catch{return r("policy-json")}return!t||t.profile!=="bound-reading-witness-policy@1"||t.unit!=="physical-lines/utf8-lf@1"||!y(t.scope)||!(t.place==="."||y(t.place))||!y(t.producer)||!y(t.port)||!y(t.readerMapping)||!Array.isArray(t.inventory)||!t.inventory.length||!t.inventory.every(y)||!Array.isArray(t.selectors)||!t.selectors.length||!t.selectors.every(y)?r("policy-fields"):!/^(0|[1-9][0-9]*)$/.test(t.byteBudget)||!/^(0|[1-9][0-9]*)$/.test(t.rowBudget)||[t.entryBudget,t.evidenceBytes,t.receiptRows,t.authorityBytes,t.authorityLines].some(w=>!Number.isSafeInteger(w)||w<1)?r("policy-budgets"):z(t)!==i(a,"about")?r("policy-canonical"):t}v(Se,"policyOf");function je(a,t,w,k=w,V="."){const m=[];try{const l=k.filter(c=>i(c,"scope")==="wire/reading-witness-admission"&&i(c,"value")!=="withdraw");if(!l.length)return{kind:"allow",evidence:m};if(l.length!==1||i(l[0],"value")!==be)return r("profile-selection");const P=fe(t.map(c=>K({...R(c),at:"policy:unverified"})),w,ae,"witness");if(!P.length)return{kind:"allow",evidence:m};const X=k.filter(c=>i(c,"role")==="writes"&&i(c,"measure")==="reading-witness"&&i(c,"value")==="lock").map(c=>({line:c,policy:Se(c)}));for(const c of P){const B=i(c,"scope"),J=X.filter(e=>e.policy.scope===B&&e.policy.place===V);if(!J.length)continue;if(J.length!==1)return r("policy-ambiguous/"+B);const{line:Y,policy:n}=J[0],Z=t.find(e=>K({...R(e),at:"policy:unverified"})===c),D=i(Z,"at"),b=D.startsWith("witness:")?D.slice(8):"";if(!ge(b))return{kind:"ask",code:"reading-witness",needs:["reading-witness/"+B],evidence:m};const x=le(a),T=we(H(x,"cas","blobs",b.slice(7)),n.evidenceBytes,b);if(p(T)!==b)return r("evidence-integrity");const j=new TextDecoder("utf-8",{fatal:!0}).decode(T),s=JSON.parse(j);if(!s||s.profile!=="bound-reading-witness-proof@1"||z(s)+`
2
+ `!==j||typeof s.witness!="string"||typeof s.authorization!="string"||!Array.isArray(s.receipts)||s.receipts.length>n.receiptRows||!s.receipts.every(e=>typeof e=="string"))return r("evidence-profile");const o=ne(s.witness);if(o.authentication!=="key-covered"||o.key!==n.producer||o.unit!==n.unit)return r("producer-policy");const S=ce(x);if(S.length>n.authorityLines||S.reduce((e,u)=>e+Buffer.byteLength(u),0)>n.authorityBytes)return r("authority-budget");const U=pe(x).admitted,L=de(a),h=ue(S,L,U),I=S.reduce((e,u)=>Math.max(e,Number(i(u,"epoch"))||0),0);if(h.of(Y).kind!=="admitted"||h.of(l[0]).kind!=="admitted")return r("policy-not-admitted");const f=R(s.authorization),$=h.of(s.authorization),_=h.admitted.find(e=>e.id===n.producer);if($.kind!=="admitted"||$.signer!==n.producer||!_||Q(f,_,I,n.scope,"authority").kind!=="admitted")return r("producer-not-current");if(f.scope!==n.scope||f.role!=="writes"||f.form!=="alphabet"||f.measure!=="reading-witness"||f.value!==p(oe(o))||f.restsOn!==p(z(n)+`
3
+ `)||o.evidence!==p(s.authorization+`
4
+ `)||o.coverage!==p(JSON.stringify(_.coverage)))return r("authorization-binding");const ee={history:S,live:k,signer:L,eras:U,epoch:I,budget:{lines:n.authorityLines,bytes:n.authorityBytes}},F=ve(ee,n.port),O=k.filter(e=>i(e,"scope")===n.readerMapping&&i(e,"value")===n.port);if(O.length!==1||o.implementation!==F.profile.selection.archive||o.reader!==F.profile.selection.archive)return r("current-native-reader");const A=h.of(O[0]),q=A.kind==="admitted"?h.admitted.find(e=>e.id===A.signer):void 0;if(A.kind!=="admitted"||A.signer!==L.id||!q||Q(R(O[0]),q,I,n.readerMapping,"authority").kind!=="admitted")return r("current-native-mapping-authority");const N=s.receipts.filter(e=>i(e,"measure")==="bytes"&&i(e,"value")===o.context&&i(e,"scope").startsWith("receipts/readings/"));if(N.length!==1||!i(N[0],"about"))return r("native-context-required");const M=i(N[0],"about"),d=JSON.parse(M);if(!Array.isArray(d)||d.length!==6||d[0]!=="reading-context@1"||p(M)!==o.context||d[2]!==o.implementation)return r("native-context-binding");if(new TextDecoder().decode(se({instrument:d[1],implementation:d[2],policy:d[3],inputs:d[4],environment:d[5]}))!==M)return r("native-context-canonical");for(const e of s.receipts.filter(u=>i(u,"measure")==="bytes"&&i(u,"scope").startsWith("receipts/readings/"))){const u=s.receipts.filter(G=>i(G,"scope")===i(e,"scope")&&i(G,"measure")==="count");if(!i(e,"about")||u.length!==1||!i(u[0],"about"))return r("native-carrier-inline")}if(!he(x,s.receipts,p,void 0,!0))return r("native-receipt");const W=new Map(d[4]);for(const e of F.profile.selection.members)if(W.get(JSON.stringify(["context","native/"+e.coordinate]))!==e.digest)return r("current-native-members");if(W.get(JSON.stringify(["context","native/reader-mapping"]))!==p(O[0]))return r("current-native-mapping");const g=ye({root:n.place==="."?a:H(a,n.place),inventory:n.inventory,regions:[{scope:n.scope,selectors:n.selectors}],policy:{entryBudget:n.entryBudget,byteBudget:n.byteBudget,rowBudget:n.rowBudget},context:o.context,reader:o.reader,implementation:o.implementation,run:o.run});if(g.status!=="read"||g.stray.length||g.reading.regions.some(e=>e.selections.some(u=>u.status!=="selected")))return r("actual-reading-unmeasured");for(const e of g.reading.inputFiles)if(W.get(JSON.stringify(["file",e.name]))!==e.digest)return r("native-input-binding");if([...W.keys()].filter(e=>{try{return JSON.parse(e)[0]==="file"}catch{return!1}}).length!==g.reading.inputFiles.length)return r("native-input-inventory");me(g,s.witness,{producers:[{authentication:"key-covered",key:n.producer,coverage:o.coverage}],verify:v(()=>!0,"verify")});const C=i(N[0],"scope");if(o.run!==C)return r("native-run-binding");const te=s.receipts.filter(e=>i(e,"scope")===C&&i(e,"measure")==="count"),ie=i(te[0],"about"),E=g.reading.regions[0];if(!E||E.status!=="measured"||!ie.split(`
5
+ `).some(e=>i(e,"scope")===B&&i(e,"measure")==="lines"&&i(e,"value")===E.value.numerator+".."+E.value.numerator))return r("native-result-binding");m.push(b,o.context,o.reading)}return{kind:"allow",evidence:m}}catch(l){return{kind:"refuse",code:"reading-witness",why:l instanceof Error?l.message:"REFUSE\xB7reading-witness/invalid",evidence:m}}}v(je,"readingWitnessAdmission");export{be as READING_WITNESS_ADMISSION_PROFILE,je as readingWitnessAdmission};