@lapxo/bound 0.2.4 → 0.2.5

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 (250) hide show
  1. package/CITATION.cff +1 -1
  2. package/TARGET.bound +44 -39
  3. package/dist/cli/accept.js +72 -590
  4. package/dist/cli/act-result.js +3 -103
  5. package/dist/cli/args.js +3 -44
  6. package/dist/cli/custodian.js +2 -29
  7. package/dist/cli/host.js +4 -32
  8. package/dist/cli/names.js +1 -12
  9. package/dist/cli/native-descendant.js +1 -19
  10. package/dist/cli/native.js +3 -60
  11. package/dist/cli/observe.js +1 -13
  12. package/dist/cli/owner.js +3 -139
  13. package/dist/cli/pass.js +21 -321
  14. package/dist/cli/place.js +6 -282
  15. package/dist/cli/release-result.js +3 -80
  16. package/dist/cli/retained-judgment.js +1 -25
  17. package/dist/cli/standing-result.js +4 -19
  18. package/dist/cli/takes.js +10 -112
  19. package/dist/cli/verb.d.ts +1 -2
  20. package/dist/cli/verb.js +83 -684
  21. package/dist/engine/computation.js +2 -0
  22. package/dist/engine/conformance.js +4 -0
  23. package/dist/engine/encoding.js +1 -2
  24. package/dist/engine/index.d.ts +1 -13
  25. package/dist/engine/index.js +2 -11
  26. package/dist/engine/object.js +1 -38
  27. package/dist/engine/ports.js +2 -117
  28. package/dist/fold/admission-history.js +1 -17
  29. package/dist/fold/bootstrap-anchor.js +1 -28
  30. package/dist/fold/ceilings.js +1 -142
  31. package/dist/fold/claims.js +2 -132
  32. package/dist/fold/closed.js +24 -235
  33. package/dist/fold/configures.js +1 -25
  34. package/dist/fold/digests.js +10 -226
  35. package/dist/fold/evidence.js +1 -22
  36. package/dist/fold/fold-worker.js +1 -13
  37. package/dist/fold/kept.js +12 -173
  38. package/dist/fold/keys.js +3 -91
  39. package/dist/fold/laid.js +3 -90
  40. package/dist/fold/nos.js +1 -48
  41. package/dist/fold/object.js +1 -2
  42. package/dist/fold/observed.js +27 -534
  43. package/dist/fold/opened.js +1 -33
  44. package/dist/fold/own.js +3 -217
  45. package/dist/fold/paid.js +1 -92
  46. package/dist/fold/place-inputs.js +1 -70
  47. package/dist/fold/places.js +3 -100
  48. package/dist/fold/rank.js +1 -9
  49. package/dist/fold/reach.js +1 -83
  50. package/dist/fold/readers.js +6 -142
  51. package/dist/fold/receipts.js +1 -47
  52. package/dist/fold/region-declarations.js +1 -13
  53. package/dist/fold/region.js +8 -286
  54. package/dist/fold/release-policy.js +1 -101
  55. package/dist/fold/resolved.js +6 -145
  56. package/dist/fold/roles.js +2 -59
  57. package/dist/fold/second.js +4 -71
  58. package/dist/fold/shards.js +12 -100
  59. package/dist/fold/signed.js +3 -81
  60. package/dist/fold/signers.js +1 -54
  61. package/dist/fold/stranger.js +6 -24
  62. package/dist/fold/views.js +1 -66
  63. package/dist/fold/wire.js +1 -46
  64. package/dist/fold/zoom.js +3 -81
  65. package/dist/host/act-cost.js +1 -25
  66. package/dist/host/adapters/keys/ed25519.js +1 -30
  67. package/dist/host/adapters/modules/javascript.js +1 -50
  68. package/dist/host/adapters/transport/http.js +1 -28
  69. package/dist/host/admitted-place.js +1 -35
  70. package/dist/host/archive.js +1 -152
  71. package/dist/host/call-context.js +1 -14
  72. package/dist/host/capsule-process.js +2 -62
  73. package/dist/host/capsule.js +9 -171
  74. package/dist/host/cell-receipts.js +12 -128
  75. package/dist/host/commit-result.js +1 -5
  76. package/dist/host/content-needed.js +1 -8
  77. package/dist/host/content-store.js +1 -31
  78. package/dist/host/contextual-place.js +2 -72
  79. package/dist/host/digest.js +2 -15
  80. package/dist/host/hash.js +1 -9
  81. package/dist/host/host-controls.js +1 -19
  82. package/dist/host/in-process-act.js +3 -84
  83. package/dist/host/in-process-context.js +3 -91
  84. package/dist/host/in-process-root.js +6 -84
  85. package/dist/host/in-process.js +4 -55
  86. package/dist/host/index.d.ts +1 -15
  87. package/dist/host/index.js +1 -7
  88. package/dist/host/io.js +1 -11
  89. package/dist/host/lifetime.js +1 -79
  90. package/dist/host/located.js +6 -105
  91. package/dist/host/native/bounded-file.js +1 -32
  92. package/dist/host/native/command.js +1 -91
  93. package/dist/host/native/control-bridge-worker.js +2 -88
  94. package/dist/host/native/control-bridge.js +1 -110
  95. package/dist/host/native/control-selection.js +1 -32
  96. package/dist/host/native/custody.js +1 -91
  97. package/dist/host/native/deadline.js +1 -28
  98. package/dist/host/native/descendants.js +1 -528
  99. package/dist/host/native/generated-custodian.js +5 -267
  100. package/dist/host/native/generated.js +1 -379
  101. package/dist/host/native/image.js +1 -45
  102. package/dist/host/native/jobs.js +2 -148
  103. package/dist/host/native/loader.js +1 -269
  104. package/dist/host/native/materialize.js +1 -175
  105. package/dist/host/native/module-closure.js +1 -130
  106. package/dist/host/native/module-delivery.d.ts +1 -62
  107. package/dist/host/native/module-delivery.js +1 -151
  108. package/dist/host/native/module-syntax.js +1 -69
  109. package/dist/host/native/native-binary.js +1 -115
  110. package/dist/host/native/native-program.js +1 -72
  111. package/dist/host/native/node-jobs.js +3 -187
  112. package/dist/host/native/node-launch.js +1 -159
  113. package/dist/host/native/preload.js +1 -45
  114. package/dist/host/native/reading.js +1 -249
  115. package/dist/host/native/receipt-environment.js +1 -41
  116. package/dist/host/native/references.js +1 -30
  117. package/dist/host/native/root.js +1 -37
  118. package/dist/host/native/route.js +1 -216
  119. package/dist/host/native/runtime.js +1 -9
  120. package/dist/host/native-reader-context.js +1 -8
  121. package/dist/host/native-receiver.js +1 -25
  122. package/dist/host/objects.js +1 -38
  123. package/dist/host/order.js +1 -2
  124. package/dist/host/place-act-transaction.js +4 -78
  125. package/dist/host/place-clock-selection.js +5 -124
  126. package/dist/host/ports/ingress.js +2 -57
  127. package/dist/host/ports/local-act.js +5 -183
  128. package/dist/host/ports/place-act.js +1 -134
  129. package/dist/host/ports/publication.js +1 -56
  130. package/dist/host/ports/signing.js +1 -74
  131. package/dist/host/ports/store.js +1 -18
  132. package/dist/host/ports/transport.js +1 -48
  133. package/dist/host/process-lifetime.js +1 -17
  134. package/dist/host/provide.js +1 -183
  135. package/dist/host/read-only.js +1 -9
  136. package/dist/host/reading-closures.js +7 -227
  137. package/dist/host/reading-context.js +1 -53
  138. package/dist/host/reading-identity-types.js +0 -0
  139. package/dist/host/reading-identity.js +3 -0
  140. package/dist/host/reading-preparation.js +6 -0
  141. package/dist/host/reference-authenticated.d.ts +1 -40
  142. package/dist/host/reference-authenticated.js +3 -100
  143. package/dist/host/reference-contracts.js +1 -6
  144. package/dist/host/reference-export.js +6 -81
  145. package/dist/host/reference-native-api.d.ts +1 -3
  146. package/dist/host/reference-native-api.js +1 -3
  147. package/dist/host/reference-native.js +1 -74
  148. package/dist/host/reference-profile.js +1 -63
  149. package/dist/host/reference-standing.js +2 -18
  150. package/dist/host/reference.js +1 -24
  151. package/dist/host/refusals.js +2 -43
  152. package/dist/host/release.js +4 -256
  153. package/dist/host/root-clock-source.js +1 -307
  154. package/dist/host/selected-capsules.js +1 -50
  155. package/dist/host/selected-topos.js +1 -80
  156. package/dist/host/signature-era.js +1 -12
  157. package/dist/host/signing.js +2 -48
  158. package/dist/host/source-content.js +2 -111
  159. package/dist/host/standing-carrier.js +1 -18
  160. package/dist/host/standing-projection.js +1 -50
  161. package/dist/host/timing.js +1 -7
  162. package/dist/host/walk.js +20 -193
  163. package/dist/judge/late.js +1 -33
  164. package/dist/judge/take.js +2 -75
  165. package/dist/judge/widening.js +1 -25
  166. package/dist/land/act.js +8 -336
  167. package/dist/land/alias.js +1 -41
  168. package/dist/land/held.js +1 -23
  169. package/dist/land/inert.js +1 -33
  170. package/dist/land/leaving.js +1 -55
  171. package/dist/land/ledger.js +7 -188
  172. package/dist/land/owned.js +4 -66
  173. package/dist/land/sign.js +1 -53
  174. package/dist/land/standing-pin.js +1 -49
  175. package/dist/land/vouched.js +1 -112
  176. package/dist/land/withdraw.js +1 -24
  177. package/dist/observe/files.js +1 -88
  178. package/dist/observe/identity.js +1 -61
  179. package/dist/observe/match.js +1 -8
  180. package/dist/observe/regions.js +7 -306
  181. package/dist/observe/run.js +2 -41
  182. package/dist/observe/runner.js +4 -101
  183. package/dist/public-types.d.ts +1114 -0
  184. package/dist/render/capsule.js +1 -30
  185. package/dist/render/field.js +1 -40
  186. package/dist/render/names.js +1 -4
  187. package/dist/render/open.js +1 -61
  188. package/dist/render/page.js +1 -7
  189. package/dist/render/receipts.js +1 -47
  190. package/dist/render/shape.js +1 -74
  191. package/dist/render/target.js +4 -52
  192. package/dist/render/view.js +7 -197
  193. package/dist/vendor/50086958553b9376d600583f7dff354196bfeb41170fc6d1482ca7bea7c493e2.LICENSE +21 -0
  194. package/dist/vendor/b3e938d28f88a1851af303a40c749e12ebd5a686daac4f0b343b5cdd2e040419.LICENSE +21 -0
  195. package/dist/vendor/bundle.json +1 -0
  196. package/dist/vendor/library11.js +1 -0
  197. package/dist/vendor/object-provider.js +42 -0
  198. package/dist/vendor/runtime.js +38 -0
  199. package/dist/vendor/sources.json +1 -0
  200. package/dist/wasm/adapter.d.ts +1 -51
  201. package/dist/wasm/adapter.js +1 -180
  202. package/dist/wasm/node-worker.js +1 -13
  203. package/dist/wasm/object.js +1 -76
  204. package/dist/wasm/worker.js +1 -7
  205. package/docs/contracts/closure-delivery.md +1 -1
  206. package/docs/contracts/closure-delivery.publication.json +1 -1
  207. package/docs/contracts/conformance.json +142 -0
  208. package/docs/contracts/determinism.bound +9 -0
  209. package/docs/contracts/engine-object-projection.publication.json +1 -1
  210. package/docs/contracts/engine.md +21 -1
  211. package/docs/contracts/native-publication.inventory.json +2 -1
  212. package/docs/contracts/optional-wasm-adapter.publication.json +1 -1
  213. package/docs/contracts/reading-identity.md +37 -0
  214. package/docs/contracts/reading-identity.publication.json +25 -0
  215. package/docs/contracts/refusals.bound +51 -0
  216. package/docs/contracts/refusals.md +18 -3
  217. package/docs/contracts/refusals.publication.json +2 -2
  218. package/docs/contracts/views.md +8 -0
  219. package/docs/reference.md +1 -0
  220. package/package.json +23 -34
  221. package/receipts.bound +11627 -10323
  222. package/samples/reading-identity/no.json +20 -0
  223. package/samples/reading-identity/yes.json +46 -0
  224. package/vectors/native/reading-identity.vector.json +101 -0
  225. package/vectors/native/refusals.vector.json +104 -0
  226. package/vendor/syntax/LICENSE.md +7 -0
  227. package/vendor/syntax/parser.js +1 -0
  228. package/.github/workflows/release.yml +0 -67
  229. package/.github/workflows/test.yml +0 -35
  230. package/dist/engine/object.d.ts +0 -17
  231. package/dist/engine/ports.d.ts +0 -37
  232. package/dist/fold/claims.d.ts +0 -29
  233. package/dist/host/call-context.d.ts +0 -20
  234. package/dist/host/commit-result.d.ts +0 -6
  235. package/dist/host/in-process-act.d.ts +0 -82
  236. package/dist/host/in-process-context.d.ts +0 -46
  237. package/dist/host/in-process-root.d.ts +0 -117
  238. package/dist/host/in-process.d.ts +0 -41
  239. package/dist/host/native/module-closure.d.ts +0 -35
  240. package/dist/host/native-receiver.d.ts +0 -19
  241. package/dist/host/place-act-transaction.d.ts +0 -24
  242. package/dist/host/place-clock-selection.d.ts +0 -55
  243. package/dist/host/ports/local-act.d.ts +0 -44
  244. package/dist/host/ports/place-act.d.ts +0 -49
  245. package/dist/host/ports/publication.d.ts +0 -10
  246. package/dist/host/reference-export.d.ts +0 -33
  247. package/dist/host/reference-native.d.ts +0 -30
  248. package/dist/host/reference-profile.d.ts +0 -23
  249. package/dist/host/refusals.d.ts +0 -14
  250. package/dist/host/root-clock-source.d.ts +0 -86
@@ -1,130 +1 @@
1
- import { builtinModules } from 'node:module';
2
- import { createHash } from 'node:crypto';
3
- import { posix } from 'node:path';
4
- import { moduleImportSyntax } from "./module-syntax.js";
5
- import { members } from "../archive.js";
6
- /** Host-selected archive and entry, never a verifier assertion from the program.
7
- * This proves content identity only; standing admission and runtime capabilities
8
- * are separate prerequisites. Binary resources are not executable text members.
9
- */
10
- export function moduleSnapshot(archive, expected, entry) {
11
- const identity = 'sha256:' + createHash('sha256').update(archive).digest('hex');
12
- if (!/^sha256:[0-9a-f]{64}$/.test(expected) || identity !== expected)
13
- throw Error('REFUSE·module closure archive bytes differ');
14
- const textMembers = new Map();
15
- for (const member of members(archive)) {
16
- // Platform archive metadata remains covered by the archive digest. Its
17
- // binary header, rather than a filename convention, identifies data.
18
- if (member.bytes.length >= 4 && new DataView(member.bytes.buffer, member.bytes.byteOffset, 4).getUint32(0) === 0x00051607)
19
- continue;
20
- if (!['.js', '.mjs', '.cjs', '.ts', '.json'].includes(posix.extname(member.name)))
21
- continue;
22
- let source;
23
- try {
24
- source = new TextDecoder('utf-8', { fatal: true, ignoreBOM: true }).decode(member.bytes);
25
- }
26
- catch {
27
- throw Error('REFUSE·module closure invalid UTF-8 bytes ' + member.name);
28
- }
29
- textMembers.set(member.name, { source, digest: 'sha256:' + createHash('sha256').update(member.bytes).digest('hex') });
30
- }
31
- return { identity, entry, members: textMembers };
32
- }
33
- /** The host supplies authenticated snapshot identities and its library resolver.
34
- * Each reached text member is verified here against its exact UTF-8 bytes.
35
- * Authentication of the snapshot envelope remains a separate host prerequisite.
36
- * A capsule cannot select either verifier or resolver.
37
- * This reads declared module edges, not arbitrary I/O or a JavaScript sandbox. Computed edges are unpaid, never absent.
38
- * Activation requires an admitted host policy; existing inventory callers are not silently changed.
39
- */
40
- export function moduleClosure(snapshot, library) {
41
- return moduleClosures([snapshot], library);
42
- }
43
- /** Multiple needs share the existing traversal and one optional act budget. */
44
- export function moduleClosures(snapshots, library, limits) {
45
- if (limits && (!Number.isSafeInteger(limits.members) || limits.members < 1 || !Number.isSafeInteger(limits.bytes) || limits.bytes < 1))
46
- throw Error('REFUSE·module closure missing input resources');
47
- const seen = new Map();
48
- let totalBytes = 0;
49
- const coordinate = (name) => {
50
- const normalized = posix.normalize(name);
51
- if (!name || name.includes('\0') || name.includes('\\') || posix.isAbsolute(name) || normalized === '..' || normalized.startsWith('../'))
52
- throw Error('REFUSE·module closure coordinate leaves snapshot ' + name);
53
- return normalized;
54
- };
55
- const walk = (one, name) => {
56
- if (limits?.signal?.aborted)
57
- throw Error('REFUSE·module closure cancelled');
58
- const at = coordinate(name), key = JSON.stringify([one.identity, at]);
59
- if (limits?.portableESM && /[%?#]/.test(at))
60
- throw Error('REFUSE·module closure unsupported URL coordinate ' + at);
61
- const member = one.members.get(at);
62
- if (member === undefined)
63
- throw Error('REFUSE·module closure missing ' + one.identity + ' ' + at);
64
- if (typeof member.source !== 'string' || !/^sha256:[0-9a-f]{64}$/.test(member.digest))
65
- throw Error('REFUSE·module closure unnamed bytes ' + one.identity + ' ' + at);
66
- const size = Buffer.byteLength(member.source, 'utf8');
67
- if (limits && !seen.has(key) && (seen.size >= limits.members || size > limits.bytes - totalBytes))
68
- throw Error('REFUSE·module closure input resources');
69
- const bytes = Buffer.from(member.source, 'utf8');
70
- if (bytes.toString('utf8') !== member.source)
71
- throw Error('REFUSE·module closure invalid UTF-8 text ' + one.identity + ' ' + at);
72
- if ('sha256:' + createHash('sha256').update(bytes).digest('hex') !== member.digest)
73
- throw Error('REFUSE·module closure bytes differ ' + one.identity + ' ' + at);
74
- const kept = seen.get(key);
75
- if (kept) {
76
- if (kept.digest !== member.digest)
77
- throw Error('REFUSE·module closure conflicting member ' + one.identity + ' ' + at);
78
- return;
79
- }
80
- totalBytes += size;
81
- seen.set(key, { snapshot: one.identity, coordinate: at, digest: member.digest });
82
- if (limits?.portableESM && !['.js', '.json'].includes(posix.extname(at)))
83
- throw Error('REFUSE·module closure unsupported ESM member ' + at);
84
- // JSON is data under the loader contract, not module syntax.
85
- if (posix.extname(at) === '.json') {
86
- if (limits?.portableESM) {
87
- try {
88
- JSON.parse(member.source);
89
- }
90
- catch {
91
- throw Error('REFUSE·module closure invalid JSON member ' + at);
92
- }
93
- }
94
- return;
95
- }
96
- const syntax = moduleImportSyntax(member.source, at, limits?.portableESM ? { esmOnly: true } : undefined);
97
- if (syntax.unresolved.length)
98
- throw Error('REFUSE·module closure unresolved ' + at + ' ' + syntax.unresolved.join(' · '));
99
- for (const specifier of syntax.imports) {
100
- if (limits?.portableESM && /[%?#\\]/.test(specifier))
101
- throw Error('REFUSE·module closure unsupported URL specifier ' + specifier + ' from ' + at);
102
- // createRequire/registerHooks can select executable edges not present in this graph.
103
- // Their runtime closure needs its own host contract; an arbitrary alias is not a literal edge.
104
- if (specifier === 'node:module' || specifier === 'module')
105
- throw Error('REFUSE·module closure runtime loader requires declared closure ' + specifier + ' from ' + at);
106
- if (limits?.portableESM && (specifier.startsWith('node:') || builtinModules.includes(specifier)))
107
- throw Error('REFUSE·module closure host builtin in portable delivery ' + specifier + ' from ' + at);
108
- if (specifier.startsWith('node:')) {
109
- if (!builtinModules.includes(specifier) && !builtinModules.includes(specifier.slice(5)))
110
- throw Error('REFUSE·module closure unknown builtin ' + specifier + ' from ' + at);
111
- continue;
112
- }
113
- if (builtinModules.includes(specifier))
114
- continue;
115
- if (specifier.startsWith('.')) {
116
- walk(one, posix.join(posix.dirname(at), specifier));
117
- continue;
118
- }
119
- if (specifier.includes(':') || posix.isAbsolute(specifier))
120
- throw Error('REFUSE·module closure unsupported location ' + specifier + ' from ' + at);
121
- const pinned = library(specifier, one);
122
- if (pinned === undefined)
123
- throw Error('REFUSE·module closure unpinned library ' + specifier + ' from ' + at);
124
- walk(pinned, pinned.entry);
125
- }
126
- };
127
- for (const snapshot of snapshots)
128
- walk(snapshot, snapshot.entry);
129
- return [...seen.values()];
130
- }
1
+ var F=Object.defineProperty;var c=(u,i)=>F(u,"name",{value:i,configurable:!0});import{builtinModules as m}from"node:module";import{createHash as S}from"node:crypto";import{posix as l}from"node:path";import{moduleImportSyntax as R}from"./module-syntax.js";import{members as x}from"../archive.js";function B(u,i,t){const E="sha256:"+S("sha256").update(u).digest("hex");if(!/^sha256:[0-9a-f]{64}$/.test(i)||E!==i)throw Error("REFUSE\xB7module closure archive bytes differ");const d=new Map;for(const s of x(u)){if(s.bytes.length>=4&&new DataView(s.bytes.buffer,s.bytes.byteOffset,4).getUint32(0)===333319||![".js",".mjs",".cjs",".ts",".json"].includes(l.extname(s.name)))continue;let a;try{a=new TextDecoder("utf-8",{fatal:!0,ignoreBOM:!0}).decode(s.bytes)}catch{throw Error("REFUSE\xB7module closure invalid UTF-8 bytes "+s.name)}d.set(s.name,{source:a,digest:"sha256:"+S("sha256").update(s.bytes).digest("hex")})}return{identity:E,entry:t,members:d}}c(B,"moduleSnapshot");function W(u,i,t){return M([u],i,void 0,t)}c(W,"moduleClosure");function M(u,i,t,E){if(t&&(!Number.isSafeInteger(t.members)||t.members<1||!Number.isSafeInteger(t.bytes)||t.bytes<1))throw Error("REFUSE\xB7module closure missing input resources");const d=new Map;let s=0;const a=c(r=>{const f=l.normalize(r);if(!r||r.includes("\0")||r.includes("\\")||l.isAbsolute(r)||f===".."||f.startsWith("../"))throw Error("REFUSE\xB7module closure coordinate leaves snapshot "+r);return f},"coordinate"),h=c((r,f)=>{if(t?.signal?.aborted)throw Error("REFUSE\xB7module closure cancelled");const e=a(f),b=JSON.stringify([r.identity,e]);if(t?.portableESM&&/[%?#]/.test(e))throw Error("REFUSE\xB7module closure unsupported URL coordinate "+e);const n=r.members.get(e);if(n===void 0)throw Error("REFUSE\xB7module closure missing "+r.identity+" "+e);if(typeof n.source!="string"||!/^sha256:[0-9a-f]{64}$/.test(n.digest))throw Error("REFUSE\xB7module closure unnamed bytes "+r.identity+" "+e);const w=Buffer.byteLength(n.source,"utf8");if(t&&!d.has(b)&&(d.size>=t.members||w>t.bytes-s))throw Error("REFUSE\xB7module closure input resources");const g=Buffer.from(n.source,"utf8");if(g.toString("utf8")!==n.source)throw Error("REFUSE\xB7module closure invalid UTF-8 text "+r.identity+" "+e);if("sha256:"+S("sha256").update(g).digest("hex")!==n.digest)throw Error("REFUSE\xB7module closure bytes differ "+r.identity+" "+e);const U=d.get(b);if(U){if(U.digest!==n.digest)throw Error("REFUSE\xB7module closure conflicting member "+r.identity+" "+e);return}if(s+=w,d.set(b,{snapshot:r.identity,coordinate:e,digest:n.digest}),t?.portableESM&&![".js",".json"].includes(l.extname(e)))throw Error("REFUSE\xB7module closure unsupported ESM member "+e);if(l.extname(e)===".json"){if(t?.portableESM)try{JSON.parse(n.source)}catch{throw Error("REFUSE\xB7module closure invalid JSON member "+e)}return}const p=R(n.source,e,t?.portableESM||E?.esmOnly?{esmOnly:!0}:void 0);if(p.unresolved.length)throw Error("REFUSE\xB7module closure unresolved "+e+" "+p.unresolved.join(" \xB7 "));for(const o of p.imports){if(t?.portableESM&&/[%?#\\]/.test(o))throw Error("REFUSE\xB7module closure unsupported URL specifier "+o+" from "+e);if(o==="node:module"||o==="module")throw Error("REFUSE\xB7module closure runtime loader requires declared closure "+o+" from "+e);if(t?.portableESM&&(o.startsWith("node:")||m.includes(o)))throw Error("REFUSE\xB7module closure host builtin in portable delivery "+o+" from "+e);if(o.startsWith("node:")){if(!m.includes(o)&&!m.includes(o.slice(5)))throw Error("REFUSE\xB7module closure unknown builtin "+o+" from "+e);continue}if(m.includes(o))continue;if(o.startsWith(".")){h(r,l.join(l.dirname(e),o));continue}if(o.includes(":")||l.isAbsolute(o))throw Error("REFUSE\xB7module closure unsupported location "+o+" from "+e);const y=i(o,r);if(y===void 0)throw Error("REFUSE\xB7module closure unpinned library "+o+" from "+e);h(y,y.entry)}},"walk");for(const r of u)h(r,r.entry);return[...d.values()]}c(M,"moduleClosures");export{W as moduleClosure,M as moduleClosures,B as moduleSnapshot};
@@ -1,62 +1 @@
1
- import { type ModuleClosureSnapshot, type ModuleClosureLimits } from './module-closure.ts';
2
- export { moduleSnapshot, type ModuleClosureSnapshot } from './module-closure.ts';
3
- export interface ClosureDeliveryLimits extends Omit<ModuleClosureLimits, 'portableESM'> {
4
- readonly responseBytes: number;
5
- }
6
- export interface ClosureNotice {
7
- readonly snapshot: string;
8
- readonly coordinate: string;
9
- readonly digest: string;
10
- readonly source: string;
11
- }
12
- export interface ClosureDeliveryManifest {
13
- readonly format: 'esm-file-closure/1';
14
- readonly needs: readonly {
15
- name: string;
16
- snapshot: string;
17
- entry: string;
18
- }[];
19
- readonly modules: readonly {
20
- snapshot: string;
21
- coordinate: string;
22
- digest: string;
23
- path: string;
24
- }[];
25
- readonly libraries: readonly {
26
- parent: string;
27
- specifier: string;
28
- snapshot: string;
29
- entry: string;
30
- }[];
31
- readonly notices: readonly {
32
- snapshot: string;
33
- coordinate: string;
34
- digest: string;
35
- path: string;
36
- }[];
37
- }
38
- export interface ClosureDelivery {
39
- readonly closure: string;
40
- readonly digest: string;
41
- readonly bytes: Uint8Array;
42
- readonly manifest: ClosureDeliveryManifest;
43
- readonly files: readonly {
44
- path: string;
45
- source: string;
46
- }[];
47
- readonly importMap: {
48
- imports: Record<string, string>;
49
- scopes: Record<string, Record<string, string>>;
50
- };
51
- }
52
- type Library = (specifier: string, parent: ModuleClosureSnapshot) => ModuleClosureSnapshot | undefined;
53
- /** The host selects already authenticated snapshots and resolution, never the
54
- * offered program. This prepares unchanged ESM files, not a JS sandbox, signer,
55
- * browser host or symbol-pruning bundler. Existing native/Acorn routes remain.
56
- */
57
- export declare function deliverModuleClosure(needs: readonly string[], entries: ReadonlyMap<string, ModuleClosureSnapshot>, library: Library, limits: ClosureDeliveryLimits, notices?: readonly ClosureNotice[]): ClosureDelivery;
58
- /** Verify exact pinned delivery bytes and run the same pre-execution closure
59
- * verifier again over the delivered set. No callbacks, install paths or verifier
60
- * chosen by the payload. The returned import map is derived, never trusted input.
61
- */
62
- export declare function verifyModuleDelivery(bytes: Uint8Array, expected: string, limits: ClosureDeliveryLimits): ClosureDelivery;
1
+ export {public3_ClosureDelivery as ClosureDelivery,public3_ClosureDeliveryLimits as ClosureDeliveryLimits,public3_ClosureDeliveryManifest as ClosureDeliveryManifest,public3_ClosureNotice as ClosureNotice,public3_ModuleClosureSnapshot as ModuleClosureSnapshot,public3_deliverModuleClosure as deliverModuleClosure,public3_moduleSnapshot as moduleSnapshot,public3_verifyModuleDelivery as verifyModuleDelivery} from "../../public-types.js";
@@ -1,151 +1 @@
1
- import { posix } from 'node:path';
2
- import { sha256, isSha256 } from "../hash.js";
3
- import { archiveCoordinate } from "../archive.js";
4
- import { compareStrings as compare } from "../order.js";
5
- import { moduleClosures } from "./module-closure.js";
6
- export { moduleSnapshot } from "./module-closure.js";
7
- const fail = (why) => { throw Error('REFUSE·closure delivery ' + why); };
8
- const key = (identity, coordinate) => JSON.stringify([identity, coordinate]);
9
- const pathOf = (identity, coordinate) => {
10
- if (!isSha256(identity))
11
- return fail('snapshot identity is not SHA-256');
12
- return 'modules/' + identity.slice(7) + '/' + coordinate;
13
- };
14
- const urlOf = (path) => './' + path.split('/').map(encodeURIComponent).join('/');
15
- const resourceLimits = (limits) => {
16
- if (!limits || !Number.isSafeInteger(limits.members) || limits.members < 1 || !Number.isSafeInteger(limits.bytes) || limits.bytes < 1 || !Number.isSafeInteger(limits.responseBytes) || limits.responseBytes < 1)
17
- fail('missing resources');
18
- if (limits.signal?.aborted)
19
- fail('cancelled');
20
- };
21
- /** The host selects already authenticated snapshots and resolution, never the
22
- * offered program. This prepares unchanged ESM files, not a JS sandbox, signer,
23
- * browser host or symbol-pruning bundler. Existing native/Acorn routes remain.
24
- */
25
- export function deliverModuleClosure(needs, entries, library, limits, notices = []) {
26
- resourceLimits(limits);
27
- if (!Array.isArray(notices) || notices.length >= limits.members)
28
- fail('notice resources');
29
- let noticeBytes = 0;
30
- const noticePaths = new Set();
31
- const retainedNotices = notices.map(n => {
32
- if (!n || typeof n.coordinate !== 'string' || archiveCoordinate(n.coordinate) !== n.coordinate || typeof n.source !== 'string' || !isSha256(n.digest) || sha256(n.source) !== n.digest || (noticeBytes += Buffer.byteLength(n.source)) >= limits.bytes)
33
- fail('notice bytes/resources');
34
- const path = 'notices/' + pathOf(n.snapshot, n.coordinate).slice('modules/'.length);
35
- if (noticePaths.has(path))
36
- fail('duplicate notice');
37
- noticePaths.add(path);
38
- return { snapshot: n.snapshot, coordinate: n.coordinate, digest: n.digest, path };
39
- }).sort((a, b) => compare(a.path, b.path));
40
- if (!Array.isArray(needs) || !needs.length || needs.length > limits.members || needs.some(n => typeof n !== 'string' || !n || Buffer.byteLength(n) > limits.bytes))
41
- fail('missing/oversized needs');
42
- const requested = [...new Set(needs)].sort(compare), snapshots = new Map(), bindings = new Map();
43
- const hold = (one) => {
44
- if (!one || !isSha256(one.identity))
45
- return fail('snapshot identity is not SHA-256');
46
- const old = snapshots.get(one.identity);
47
- // Different entry points may share one immutable snapshot, not different members.
48
- if (old && old.members !== one.members)
49
- fail('ambiguous snapshot members');
50
- snapshots.set(one.identity, one);
51
- return one;
52
- };
53
- const roots = requested.map(name => { const one = entries.get(name); if (!one)
54
- return fail('unknown need ' + name); return hold(one); });
55
- const reached = moduleClosures(roots, (specifier, parent) => {
56
- const found = library(specifier, parent);
57
- if (!found)
58
- return;
59
- const one = hold(found), at = key(parent.identity, specifier), binding = { parent: parent.identity, specifier, snapshot: one.identity, entry: one.entry }, old = bindings.get(at);
60
- if (old && (old.snapshot !== one.identity || old.entry !== one.entry))
61
- fail('ambiguous library resolution');
62
- if (!old && bindings.size >= limits.members)
63
- fail('library resources');
64
- bindings.set(at, binding);
65
- return one;
66
- }, { ...limits, members: limits.members - notices.length, bytes: limits.bytes - noticeBytes, portableESM: true });
67
- if (notices.some(n => !reached.some(r => r.snapshot === n.snapshot)))
68
- fail('notice outside reached snapshots');
69
- const modules = [...reached].sort((a, b) => compare(key(a.snapshot, a.coordinate), key(b.snapshot, b.coordinate))).map(r => ({ ...r, path: pathOf(r.snapshot, r.coordinate) }));
70
- const files = modules.map(r => {
71
- const source = snapshots.get(r.snapshot)?.members.get(r.coordinate)?.source;
72
- if (source === undefined || sha256(source) !== r.digest)
73
- fail('snapshot changed during delivery');
74
- return { path: r.path, source: source };
75
- });
76
- for (const n of retainedNotices)
77
- files.push({ path: n.path, source: notices.find(one => one.snapshot === n.snapshot && one.coordinate === n.coordinate).source });
78
- const manifest = { format: 'esm-file-closure/1', needs: requested.map((name, i) => ({ name, snapshot: roots[i].identity, entry: posix.normalize(roots[i].entry) })), modules, libraries: [...bindings.values()].sort((a, b) => compare(key(a.parent, a.specifier), key(b.parent, b.specifier))), notices: retainedNotices };
79
- const closure = sha256(JSON.stringify(manifest));
80
- const bytes = Buffer.from(JSON.stringify({ manifest, files }), 'utf8');
81
- if (bytes.length > limits.responseBytes)
82
- fail('response resources');
83
- if (limits.signal?.aborted)
84
- fail('cancelled');
85
- const imports = Object.fromEntries(manifest.needs.map(n => [n.name, urlOf(pathOf(n.snapshot, n.entry))]));
86
- const scopes = {};
87
- for (const b of manifest.libraries) {
88
- const scope = './modules/' + b.parent.slice(7) + '/';
89
- const values = scopes[scope] ?? (scopes[scope] = Object.create(null));
90
- values[b.specifier] = urlOf(pathOf(b.snapshot, posix.normalize(b.entry)));
91
- }
92
- return { closure, digest: sha256(bytes), bytes: new Uint8Array(bytes), manifest, files, importMap: { imports, scopes } };
93
- }
94
- /** Verify exact pinned delivery bytes and run the same pre-execution closure
95
- * verifier again over the delivered set. No callbacks, install paths or verifier
96
- * chosen by the payload. The returned import map is derived, never trusted input.
97
- */
98
- export function verifyModuleDelivery(bytes, expected, limits) {
99
- resourceLimits(limits);
100
- if (!(bytes instanceof Uint8Array) || bytes.byteLength > limits.responseBytes || !isSha256(expected) || sha256(bytes) !== expected)
101
- fail('bundle bytes differ or exceed resources');
102
- let value;
103
- try {
104
- value = JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(bytes));
105
- }
106
- catch {
107
- return fail('invalid JSON bytes');
108
- }
109
- const manifest = value?.manifest;
110
- if (manifest?.format !== 'esm-file-closure/1' || !Array.isArray(manifest.needs) || !Array.isArray(manifest.modules) || !Array.isArray(manifest.libraries) || !Array.isArray(manifest.notices) || !Array.isArray(value.files) || manifest.modules.length + manifest.notices.length > limits.members || value.files.length !== manifest.modules.length + manifest.notices.length || manifest.needs.length > limits.members || manifest.libraries.length > limits.members)
111
- fail('invalid manifest resources');
112
- const snapshots = new Map(), files = new Map();
113
- let size = 0;
114
- for (const file of value.files) {
115
- if (typeof file?.path !== 'string' || typeof file.source !== 'string' || files.has(file.path) || (size += Buffer.byteLength(file.source)) > limits.bytes)
116
- fail('invalid/duplicate file resources');
117
- files.set(file.path, file.source);
118
- }
119
- for (const m of manifest.modules) {
120
- if (!m || typeof m.coordinate !== 'string' || typeof m.path !== 'string' || m.path !== pathOf(m.snapshot, m.coordinate) || !isSha256(m.digest))
121
- fail('invalid module');
122
- const source = files.get(m.path);
123
- if (source === undefined || sha256(source) !== m.digest)
124
- fail('module bytes differ');
125
- const members = snapshots.get(m.snapshot) ?? new Map();
126
- if (members.has(m.coordinate))
127
- fail('duplicate module');
128
- members.set(m.coordinate, { source, digest: m.digest });
129
- snapshots.set(m.snapshot, members);
130
- }
131
- const snapshot = (identity, entry) => { const members = snapshots.get(identity); if (!members || typeof entry !== 'string')
132
- return fail('unknown snapshot/entry'); return { identity, entry, members }; };
133
- const entries = new Map();
134
- for (const n of manifest.needs) {
135
- if (typeof n?.name !== 'string' || entries.has(n.name))
136
- fail('invalid/duplicate need');
137
- entries.set(n.name, snapshot(n.snapshot, n.entry));
138
- }
139
- const bindings = new Map();
140
- for (const b of manifest.libraries) {
141
- if (typeof b?.parent !== 'string' || typeof b.specifier !== 'string' || bindings.has(key(b.parent, b.specifier)))
142
- fail('invalid/duplicate library');
143
- bindings.set(key(b.parent, b.specifier), snapshot(b.snapshot, b.entry));
144
- }
145
- const notices = manifest.notices.map(n => { if (!n || typeof n.path !== 'string' || !files.has(n.path))
146
- return fail('missing notice'); return { snapshot: n.snapshot, coordinate: n.coordinate, digest: n.digest, source: files.get(n.path) }; });
147
- const prepared = deliverModuleClosure([...entries.keys()], entries, (specifier, parent) => bindings.get(key(parent.identity, specifier)), limits, notices);
148
- if (prepared.digest !== expected)
149
- fail('noncanonical, extra or unresolved delivery members');
150
- return prepared;
151
- }
1
+ var H=Object.defineProperty;var f=(r,a)=>H(r,"name",{value:a,configurable:!0});import{posix as k}from"node:path";import{sha256 as b,isSha256 as w}from"../hash.js";import{archiveCoordinate as R}from"../archive.js";import{compareStrings as z}from"../order.js";import{moduleClosures as q}from"./module-closure.js";import{moduleSnapshot as Z}from"./module-closure.js";const o=f(r=>{throw Error("REFUSE\xB7closure delivery "+r)},"fail"),m=f((r,a)=>JSON.stringify([r,a]),"key"),M=f((r,a)=>w(r)?"modules/"+r.slice(7)+"/"+a:o("snapshot identity is not SHA-256"),"pathOf"),C=f(r=>"./"+r.split("/").map(encodeURIComponent).join("/"),"urlOf"),I=f(r=>{(!r||!Number.isSafeInteger(r.members)||r.members<1||!Number.isSafeInteger(r.bytes)||r.bytes<1||!Number.isSafeInteger(r.responseBytes)||r.responseBytes<1)&&o("missing resources"),r.signal?.aborted&&o("cancelled")},"resourceLimits");function F(r,a,d,i,n=[]){I(i),(!Array.isArray(n)||n.length>=i.members)&&o("notice resources");let l=0;const u=new Set,B=n.map(e=>{(!e||typeof e.coordinate!="string"||R(e.coordinate)!==e.coordinate||typeof e.source!="string"||!w(e.digest)||b(e.source)!==e.digest||(l+=Buffer.byteLength(e.source))>=i.bytes)&&o("notice bytes/resources");const s="notices/"+M(e.snapshot,e.coordinate).slice(8);return u.has(s)&&o("duplicate notice"),u.add(s),{snapshot:e.snapshot,coordinate:e.coordinate,digest:e.digest,path:s}}).sort((e,s)=>z(e.path,s.path));(!Array.isArray(r)||!r.length||r.length>i.members||r.some(e=>typeof e!="string"||!e||Buffer.byteLength(e)>i.bytes))&&o("missing/oversized needs");const v=[...new Set(r)].sort(z),h=new Map,y=new Map,N=f(e=>{if(!e||!w(e.identity))return o("snapshot identity is not SHA-256");const s=h.get(e.identity);return s&&s.members!==e.members&&o("ambiguous snapshot members"),h.set(e.identity,e),e},"hold"),g=v.map(e=>{const s=a.get(e);return s?N(s):o("unknown need "+e)}),t=q(g,(e,s)=>{const O=d(e,s);if(!O)return;const S=N(O),L=m(s.identity,e),D={parent:s.identity,specifier:e,snapshot:S.identity,entry:S.entry},x=y.get(L);return x&&(x.snapshot!==S.identity||x.entry!==S.entry)&&o("ambiguous library resolution"),!x&&y.size>=i.members&&o("library resources"),y.set(L,D),S},{...i,members:i.members-n.length,bytes:i.bytes-l,portableESM:!0});n.some(e=>!t.some(s=>s.snapshot===e.snapshot))&&o("notice outside reached snapshots");const c=[...t].sort((e,s)=>z(m(e.snapshot,e.coordinate),m(s.snapshot,s.coordinate))).map(e=>({...e,path:M(e.snapshot,e.coordinate)})),p=c.map(e=>{const s=h.get(e.snapshot)?.members.get(e.coordinate)?.source;return(s===void 0||b(s)!==e.digest)&&o("snapshot changed during delivery"),{path:e.path,source:s}});for(const e of B)p.push({path:e.path,source:n.find(s=>s.snapshot===e.snapshot&&s.coordinate===e.coordinate).source});const A={format:"esm-file-closure/1",needs:v.map((e,s)=>({name:e,snapshot:g[s].identity,entry:k.normalize(g[s].entry)})),modules:c,libraries:[...y.values()].sort((e,s)=>z(m(e.parent,e.specifier),m(s.parent,s.specifier))),notices:B},U=b(JSON.stringify(A)),E=Buffer.from(JSON.stringify({manifest:A,files:p}),"utf8");E.length>i.responseBytes&&o("response resources"),i.signal?.aborted&&o("cancelled");const j=Object.fromEntries(A.needs.map(e=>[e.name,C(M(e.snapshot,e.entry))])),J={};for(const e of A.libraries){const s="./modules/"+e.parent.slice(7)+"/",O=J[s]??(J[s]=Object.create(null));O[e.specifier]=C(M(e.snapshot,k.normalize(e.entry)))}return{closure:U,digest:b(E),bytes:new Uint8Array(E),manifest:A,files:p,importMap:{imports:j,scopes:J}}}f(F,"deliverModuleClosure");function W(r,a,d){I(d),(!(r instanceof Uint8Array)||r.byteLength>d.responseBytes||!w(a)||b(r)!==a)&&o("bundle bytes differ or exceed resources");let i;try{i=JSON.parse(new TextDecoder("utf-8",{fatal:!0}).decode(r))}catch{return o("invalid JSON bytes")}const n=i?.manifest;(n?.format!=="esm-file-closure/1"||!Array.isArray(n.needs)||!Array.isArray(n.modules)||!Array.isArray(n.libraries)||!Array.isArray(n.notices)||!Array.isArray(i.files)||n.modules.length+n.notices.length>d.members||i.files.length!==n.modules.length+n.notices.length||n.needs.length>d.members||n.libraries.length>d.members)&&o("invalid manifest resources");const l=new Map,u=new Map;let B=0;for(const t of i.files)(typeof t?.path!="string"||typeof t.source!="string"||u.has(t.path)||(B+=Buffer.byteLength(t.source))>d.bytes)&&o("invalid/duplicate file resources"),u.set(t.path,t.source);for(const t of n.modules){(!t||typeof t.coordinate!="string"||typeof t.path!="string"||t.path!==M(t.snapshot,t.coordinate)||!w(t.digest))&&o("invalid module");const c=u.get(t.path);(c===void 0||b(c)!==t.digest)&&o("module bytes differ");const p=l.get(t.snapshot)??new Map;p.has(t.coordinate)&&o("duplicate module"),p.set(t.coordinate,{source:c,digest:t.digest}),l.set(t.snapshot,p)}const v=f((t,c)=>{const p=l.get(t);return!p||typeof c!="string"?o("unknown snapshot/entry"):{identity:t,entry:c,members:p}},"snapshot"),h=new Map;for(const t of n.needs)(typeof t?.name!="string"||h.has(t.name))&&o("invalid/duplicate need"),h.set(t.name,v(t.snapshot,t.entry));const y=new Map;for(const t of n.libraries)(typeof t?.parent!="string"||typeof t.specifier!="string"||y.has(m(t.parent,t.specifier)))&&o("invalid/duplicate library"),y.set(m(t.parent,t.specifier),v(t.snapshot,t.entry));const N=n.notices.map(t=>!t||typeof t.path!="string"||!u.has(t.path)?o("missing notice"):{snapshot:t.snapshot,coordinate:t.coordinate,digest:t.digest,source:u.get(t.path)}),g=F([...h.keys()],h,(t,c)=>y.get(m(c.identity,t)),d,N);return g.digest!==a&&o("noncanonical, extra or unresolved delivery members"),g}f(W,"verifyModuleDelivery");export{F as deliverModuleClosure,Z as moduleSnapshot,W as verifyModuleDelivery};
@@ -1,69 +1 @@
1
- import { stringLiteral } from "../adapters/modules/javascript.js";
2
- import * as nodeModule from 'node:module';
3
- import { extname } from 'node:path';
4
- /** Host module syntax, never wire or domain interpretation. Reading imports executes no module. */
5
- // The package's minimum Node runtime provides this API; older build-only Node types do not.
6
- const require = nodeModule.createRequire(import.meta.url);
7
- const { parse } = require('acorn');
8
- const stripTypeScriptTypes = nodeModule.stripTypeScriptTypes;
9
- /** Syntax inventory is not an execution-closure certificate: unresolved expressions stay explicit. */
10
- export function moduleImportSyntax(source, coordinate, options) {
11
- const code = extname(coordinate) === '.ts' ? stripTypeScriptTypes(source, { mode: 'transform' }) : source;
12
- let tree;
13
- try {
14
- tree = parse(code, { ecmaVersion: 'latest', sourceType: 'module', allowReturnOutsideFunction: true, allowHashBang: true });
15
- }
16
- catch {
17
- throw Error('REFUSE·source module syntax cannot be read: ' + coordinate);
18
- }
19
- const found = new Set(), unresolved = new Set();
20
- const literal = stringLiteral;
21
- const visit = (node, parent, key, reexportSource = false) => {
22
- if (!node || typeof node !== 'object')
23
- return;
24
- if (Array.isArray(node)) {
25
- for (const child of node)
26
- visit(child, parent, key, reexportSource);
27
- return;
28
- }
29
- const n = node;
30
- // Escaped loader references do not become an empty inventory. This is
31
- // conservative syntax, not a complete JavaScript alias/data-flow proof.
32
- if (n['type'] === 'Identifier' && n['name'] === 'require') {
33
- const direct = parent?.['type'] === 'CallExpression' && key === 'callee';
34
- const namedProperty = (parent?.['type'] === 'MemberExpression' && key === 'property' && !parent['computed']) || ((parent?.['type'] === 'Property' || parent?.['type'] === 'MethodDefinition') && key === 'key' && !parent['computed'] && !parent['shorthand']);
35
- // Declaration names are not loader references. This does not resolve shadowing:
36
- // references to a binding named require remain conservative, including local calls.
37
- const declarationName = ((parent?.['type'] === 'ImportSpecifier' || parent?.['type'] === 'ImportDefaultSpecifier' || parent?.['type'] === 'ImportNamespaceSpecifier') && (key === 'imported' || key === 'local')) || (parent?.['type'] === 'FunctionDeclaration' && key === 'id');
38
- const reexportName = parent?.['type'] === 'ExportSpecifier' && (key === 'exported' || (key === 'local' && reexportSource));
39
- if (!direct && !namedProperty && !declarationName && !reexportName)
40
- unresolved.add('require reference at ' + String(n['start']));
41
- }
42
- let specifier;
43
- if (n['type'] === 'ImportDeclaration' || n['type'] === 'ExportNamedDeclaration' || n['type'] === 'ExportAllDeclaration' || n['type'] === 'ImportExpression') {
44
- specifier = literal(n['source']);
45
- if (n['type'] === 'ImportExpression' && specifier === undefined)
46
- unresolved.add('import expression at ' + String(n['start']));
47
- }
48
- if (n['type'] === 'CallExpression') {
49
- const callee = n['callee'];
50
- if (callee?.['type'] === 'Identifier' && callee['name'] === 'require') {
51
- if (options?.esmOnly)
52
- throw Error('REFUSE·module closure CommonJS load in ESM delivery ' + coordinate);
53
- specifier = literal(n['arguments'][0]);
54
- if (specifier === undefined)
55
- unresolved.add('require expression at ' + String(n['start']));
56
- }
57
- }
58
- if (specifier !== undefined)
59
- found.add(specifier);
60
- for (const [childKey, child] of Object.entries(n))
61
- visit(child, n, childKey, n['type'] === 'ExportNamedDeclaration' ? n['source'] !== null && n['source'] !== undefined : reexportSource);
62
- };
63
- visit(tree);
64
- return { imports: [...found], unresolved: [...unresolved] };
65
- }
66
- /** Existing inventory keeps its meaning; callers requiring closure must inspect unresolved edges. */
67
- export function moduleImports(source, coordinate) {
68
- return moduleImportSyntax(source, coordinate).imports;
69
- }
1
+ var g=Object.defineProperty;var l=(o,r)=>g(o,"name",{value:r,configurable:!0});import{parse as h}from"../../../vendor/syntax/parser.js";import*as D from"node:module";import{extname as b}from"node:path";const v=D.stripTypeScriptTypes,N=l(o=>{if(!o||typeof o!="object")return;const r=o;return r.type==="Literal"&&typeof r.value=="string"?r.value:void 0},"stringLiteral");function T(o,r,m){const E=b(r)===".ts"?v(o,{mode:"transform"}):o;let u;try{u=h(E,{sourceType:"module",next:!0,ranges:{start:!0,end:!1,range:!1},lexical:!0,globalReturn:!0})}catch{throw Error("REFUSE\xB7source module syntax cannot be read: "+r)}const y=new Set,a=new Set,x=N,c=l((p,t,i,f=!1)=>{if(!p||typeof p!="object")return;if(Array.isArray(p)){for(const n of p)c(n,t,i,f);return}const e=p;if(e.type==="Identifier"&&e.name==="require"){const n=t?.type==="CallExpression"&&i==="callee",d=t?.type==="MemberExpression"&&i==="property"&&!t.computed||(t?.type==="Property"||t?.type==="MethodDefinition")&&i==="key"&&!t.computed&&!t.shorthand,S=(t?.type==="ImportSpecifier"||t?.type==="ImportDefaultSpecifier"||t?.type==="ImportNamespaceSpecifier")&&(i==="imported"||i==="local")||t?.type==="FunctionDeclaration"&&i==="id",I=t?.type==="ExportSpecifier"&&(i==="exported"||i==="local"&&f);!n&&!d&&!S&&!I&&a.add("require reference at "+String(e.start))}let s;if((e.type==="ImportDeclaration"||e.type==="ExportNamedDeclaration"||e.type==="ExportAllDeclaration"||e.type==="ImportExpression")&&(s=x(e.source),e.type==="ImportExpression"&&s===void 0&&a.add("import expression at "+String(e.start))),e.type==="CallExpression"){const n=e.callee;if(n?.type==="Identifier"&&n.name==="require"){if(m?.esmOnly)throw Error("REFUSE\xB7module closure CommonJS load in ESM delivery "+r);s=x(e.arguments[0]),s===void 0&&a.add("require expression at "+String(e.start))}}s!==void 0&&(!m?.staticOnly||e.type!=="ImportExpression"&&e.type!=="CallExpression")&&y.add(s);for(const[n,d]of Object.entries(e))c(d,e,n,e.type==="ExportNamedDeclaration"?e.source!==null&&e.source!==void 0:f)},"visit");return c(u),{imports:[...y],unresolved:[...a]}}l(T,"moduleImportSyntax");function M(o,r){return T(o,r).imports}l(M,"moduleImports");export{T as moduleImportSyntax,M as moduleImports};
@@ -1,115 +1 @@
1
- import { retainedProjection } from "./reading.js";
2
- import { isSha256 } from "../hash.js";
3
- import { fieldNames } from "./reading.js";
4
- import { sha256 } from "../hash.js";
5
- /** Host-only native binary selection. No PATH lookup, Node impersonation,
6
- * transitive OS-library seal or arbitrary-process sandbox is claimed. */
7
- import { createHash } from 'node:crypto';
8
- import { isAbsolute } from 'node:path';
9
- import { realpathSync } from 'node:fs';
10
- import { fileURLToPath } from 'node:url';
11
- import { authorityAtEpoch } from '@lapxo/topos/wire';
12
- import { parsedLine as parse } from "../../fold/claims.js";
13
- import { authorityFor } from "../../fold/signers.js";
14
- import { authenticateSignedPort, nativeParentInputBytes, canonicalJson } from "./reading.js";
15
- import { readBounded } from "./generated.js";
16
- const sha = sha256, keys = fieldNames, validDigest = isSha256, fail = (why) => { throw Error('REFUSE·native binary ' + why); };
17
- /** A Root-selected local origin is a location constraint, not a World hint. */
18
- export function hostOriginPath(root, coordinate) {
19
- if (!/^region\/[^\s]+$/.test(coordinate))
20
- fail('origin is not a declared region');
21
- const rows = root.live.filter(line => { const row = parse(line); return row.kind === 'fact' && row.value.fields.scope === coordinate && row.value.fields.measure === 'origin' && row.value.fields.value !== 'withdraw'; });
22
- if (rows.length !== 1)
23
- fail('missing/conflicting origin ' + coordinate);
24
- const line = rows[0];
25
- if (!root.history.includes(line))
26
- fail('origin absent from authenticated history');
27
- const row = parse(line);
28
- if (row.kind !== 'fact')
29
- return fail('origin not a wire record');
30
- const f = row.value.fields;
31
- if (f.role !== 'writes' || f.form !== 'alphabet')
32
- fail('origin declaration meaning');
33
- const auth = authorityFor(root.history, root.signer, root.eras), signed = auth.of(line);
34
- if (signed.kind !== 'admitted' || signed.signer !== root.signer.id)
35
- fail('origin must be Root signed');
36
- const current = authorityAtEpoch(f, root.signer, root.epoch, coordinate, 'authority');
37
- if (current.kind !== 'admitted')
38
- fail('current origin authority ' + current.why);
39
- let url, path;
40
- try {
41
- url = new URL(f.value);
42
- }
43
- catch {
44
- return fail('origin URL invalid');
45
- }
46
- if (url.protocol !== 'file:' || url.username || url.password || url.search || url.hash || (url.hostname && url.hostname !== 'localhost'))
47
- fail('unsupported origin transport');
48
- try {
49
- path = fileURLToPath(url);
50
- if (!isAbsolute(path) || path.includes('\0'))
51
- return fail('origin path invalid');
52
- path = realpathSync(path);
53
- }
54
- catch {
55
- return fail('local origin absent/invalid');
56
- }
57
- return Object.freeze({ coordinate, line, path });
58
- }
59
- export function nativeBinaryOrigin(root, p, portLine) {
60
- if (p.profile !== 'host-native-binary-origin@1')
61
- return;
62
- const signed = authorityFor(root.history, root.signer, root.eras).of(portLine);
63
- if (signed.kind !== 'admitted' || signed.signer !== root.signer.id)
64
- fail('origin selection must be Root signed');
65
- const origin = hostOriginPath(root, p.origin);
66
- const bytes = readBounded(origin.path, p.entry.bytes);
67
- if (bytes.byteLength !== p.entry.bytes || sha(bytes) !== p.entry.digest)
68
- fail('origin bytes differ');
69
- return origin;
70
- }
71
- const verified = new WeakMap();
72
- /** Call under the existing Root guard; privateBinding is from the already
73
- * prepared host image, never the candidate profile's own expected digest. */
74
- export function verifyNativeBinary(root, coordinate, parent, privateBinding) {
75
- const auth = authenticateSignedPort(root, coordinate), p = auth.profile;
76
- if (!p || keys(p) !== (p.profile === 'host-native-binary-origin@1' ? 'alias,condition,coordinate,entry,limits,origin,profile,selector' : 'alias,condition,coordinate,entry,limits,profile,selector') || !['host-native-binary@1', 'host-native-binary-origin@1'].includes(p.profile) || p.coordinate !== coordinate || typeof p.alias !== 'string' || !p.alias.length || p.alias.includes('\0') || typeof p.condition !== 'string' || !p.condition.length)
77
- fail('selection absent/unknown');
78
- if (keys(p.selector ?? {}) !== 'binding,implementation,port' || canonicalJson(p.selector) !== canonicalJson({ port: parent.port, binding: parent.binding, implementation: parent.implementation }))
79
- fail('selection differs from parent');
80
- if (!validDigest(parent.identity) || !validDigest(parent.instrument) || !validDigest(parent.policy) || !validDigest(parent.authority) || !validDigest(parent.implementation) || !Array.isArray(parent.inputs))
81
- fail('parent identity absent');
82
- if (keys(p.entry ?? {}) !== 'bytes,digest,path' || typeof p.entry.path !== 'string' || isAbsolute(p.entry.path) || p.entry.path.split('/').some(s => !s || s === '.' || s === '..') || !validDigest(p.entry.digest) || !Number.isSafeInteger(p.entry.bytes) || p.entry.bytes < 1 || keys(p.limits ?? {}) !== 'bytes' || !Number.isSafeInteger(p.limits.bytes) || p.limits.bytes < 1 || p.entry.bytes > p.limits.bytes || p.limits.bytes > nativeParentInputBytes(root, parent))
83
- fail('entry byte resource absent/outside Root');
84
- if (!privateBinding || typeof privateBinding.path !== 'string' || !isAbsolute(privateBinding.path) || !validDigest(privateBinding.digest) || p.entry.path !== privateBinding.coordinate || p.entry.digest !== privateBinding.digest || !parent.inputs.some(([_, digest]) => digest === privateBinding.digest))
85
- fail('private image binding absent/differs');
86
- const origin = nativeBinaryOrigin(root, p, auth.line);
87
- let expected, actual;
88
- try {
89
- expected = realpathSync(privateBinding.path);
90
- actual = realpathSync(privateBinding.path);
91
- }
92
- catch {
93
- return fail('entry absent');
94
- }
95
- if (expected !== actual)
96
- fail('entry path differs from private image');
97
- let runtimePath;
98
- try {
99
- runtimePath = realpathSync(parent.runtime);
100
- }
101
- catch {
102
- return fail('runtime binding absent');
103
- }
104
- if (actual === runtimePath)
105
- fail('binary aliases actual runtime');
106
- if (origin && actual !== origin.path)
107
- fail('entry differs from declared origin');
108
- const bytes = readBounded(actual, p.entry.bytes);
109
- if (bytes.byteLength !== p.entry.bytes || sha(bytes) !== privateBinding.digest)
110
- fail('entry bytes differ');
111
- const handle = Object.freeze({ identity: 'sha256:' + createHash('sha256').update(canonicalJson([auth.line, parent.identity, ...(origin ? [origin.line] : [])])).digest('hex') });
112
- verified.set(handle, { kind: 'native-binary', alias: p.alias, entry: actual, entryDigest: privateBinding.digest, entryBytes: bytes.byteLength, condition: p.condition });
113
- return handle;
114
- }
115
- export const nativeBinaryProjection = retainedProjection(verified, fail);
1
+ var S=Object.defineProperty;var h=(e,s)=>S(e,"name",{value:s,configurable:!0});import{retainedProjection as A}from"./reading.js";import{isSha256 as E}from"../hash.js";import{fieldNames as j}from"./reading.js";import{sha256 as N}from"../hash.js";import{createHash as O}from"node:crypto";import{isAbsolute as p}from"node:path";import{realpathSync as u}from"node:fs";import{fileURLToPath as U}from"node:url";import{library11_authorityAtEpoch as I}from"../../vendor/runtime.js";import{parsedLine as w}from"../../fold/claims.js";import{authorityFor as k}from"../../fold/signers.js";import{authenticateSignedPort as z,nativeParentInputBytes as D,canonicalJson as v}from"./reading.js";import{readBounded as L}from"./generated.js";const P=N,b=j,c=E,i=h(e=>{throw Error("REFUSE\xB7native binary "+e)},"fail");function F(e,s){/^region\/[^\s]+$/.test(s)||i("origin is not a declared region");const r=e.live.filter(g=>{const f=w(g);return f.kind==="fact"&&f.value.fields.scope===s&&f.value.fields.measure==="origin"&&f.value.fields.value!=="withdraw"});r.length!==1&&i("missing/conflicting origin "+s);const n=r[0];e.history.includes(n)||i("origin absent from authenticated history");const y=w(n);if(y.kind!=="fact")return i("origin not a wire record");const t=y.value.fields;(t.role!=="writes"||t.form!=="alphabet")&&i("origin declaration meaning");const d=k(e.history,e.signer,e.eras),m=d.of(n);(m.kind!=="admitted"||m.signer!==e.signer.id)&&i("origin must be Root signed");const l=I(t,e.signer,e.epoch,s,"authority");l.kind!=="admitted"&&i("current origin authority "+l.why);let o,a;try{o=new URL(t.value)}catch{return i("origin URL invalid")}(o.protocol!=="file:"||o.username||o.password||o.search||o.hash||o.hostname&&o.hostname!=="localhost")&&i("unsupported origin transport");try{if(a=U(o),!p(a)||a.includes("\0"))return i("origin path invalid");a=u(a)}catch{return i("local origin absent/invalid")}return Object.freeze({coordinate:s,line:n,path:a})}h(F,"hostOriginPath");function _(e,s,r){if(s.profile!=="host-native-binary-origin@1")return;const n=k(e.history,e.signer,e.eras).of(r);(n.kind!=="admitted"||n.signer!==e.signer.id)&&i("origin selection must be Root signed");const y=F(e,s.origin),t=L(y.path,s.entry.bytes);return(t.byteLength!==s.entry.bytes||P(t)!==s.entry.digest)&&i("origin bytes differ"),y}h(_,"nativeBinaryOrigin");const R=new WeakMap;function Z(e,s,r,n){const y=z(e,s),t=y.profile;(!t||b(t)!==(t.profile==="host-native-binary-origin@1"?"alias,condition,coordinate,entry,limits,origin,profile,selector":"alias,condition,coordinate,entry,limits,profile,selector")||!["host-native-binary@1","host-native-binary-origin@1"].includes(t.profile)||t.coordinate!==s||typeof t.alias!="string"||!t.alias.length||t.alias.includes("\0")||typeof t.condition!="string"||!t.condition.length)&&i("selection absent/unknown"),(b(t.selector??{})!=="binding,implementation,port"||v(t.selector)!==v({port:r.port,binding:r.binding,implementation:r.implementation}))&&i("selection differs from parent"),(!c(r.identity)||!c(r.instrument)||!c(r.policy)||!c(r.authority)||!c(r.implementation)||!Array.isArray(r.inputs))&&i("parent identity absent"),(b(t.entry??{})!=="bytes,digest,path"||typeof t.entry.path!="string"||p(t.entry.path)||t.entry.path.split("/").some(f=>!f||f==="."||f==="..")||!c(t.entry.digest)||!Number.isSafeInteger(t.entry.bytes)||t.entry.bytes<1||b(t.limits??{})!=="bytes"||!Number.isSafeInteger(t.limits.bytes)||t.limits.bytes<1||t.entry.bytes>t.limits.bytes||t.limits.bytes>D(e,r))&&i("entry byte resource absent/outside Root"),(!n||typeof n.path!="string"||!p(n.path)||!c(n.digest)||t.entry.path!==n.coordinate||t.entry.digest!==n.digest||!r.inputs.some(([f,x])=>x===n.digest))&&i("private image binding absent/differs");const d=_(e,t,y.line);let m,l;try{m=u(n.path),l=u(n.path)}catch{return i("entry absent")}m!==l&&i("entry path differs from private image");let o;try{o=u(r.runtime)}catch{return i("runtime binding absent")}l===o&&i("binary aliases actual runtime"),d&&l!==d.path&&i("entry differs from declared origin");const a=L(l,t.entry.bytes);(a.byteLength!==t.entry.bytes||P(a)!==n.digest)&&i("entry bytes differ");const g=Object.freeze({identity:"sha256:"+O("sha256").update(v([y.line,r.identity,...d?[d.line]:[]])).digest("hex")});return R.set(g,{kind:"native-binary",alias:t.alias,entry:l,entryDigest:n.digest,entryBytes:a.byteLength,condition:t.condition}),g}h(Z,"verifyNativeBinary");const B=A(R,i);export{F as hostOriginPath,_ as nativeBinaryOrigin,B as nativeBinaryProjection,Z as verifyNativeBinary};