@lapxo/bound 0.2.3 → 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 (242) hide show
  1. package/CITATION.cff +19 -0
  2. package/TARGET.bound +95 -39
  3. package/dist/cli/accept.js +72 -558
  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 -281
  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 -21
  18. package/dist/cli/takes.js +10 -111
  19. package/dist/cli/verb.d.ts +1 -2
  20. package/dist/cli/verb.js +83 -683
  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 -103
  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 -131
  32. package/dist/fold/closed.js +24 -234
  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 -63
  70. package/dist/host/archive.js +1 -152
  71. package/dist/host/call-context.js +1 -0
  72. package/dist/host/capsule-process.js +2 -61
  73. package/dist/host/capsule.js +9 -168
  74. package/dist/host/cell-receipts.js +12 -128
  75. package/dist/host/commit-result.js +1 -0
  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 -77
  79. package/dist/host/digest.js +2 -15
  80. package/dist/host/hash.js +1 -9
  81. package/dist/host/host-controls.js +1 -0
  82. package/dist/host/in-process-act.js +3 -0
  83. package/dist/host/in-process-context.js +3 -0
  84. package/dist/host/in-process-root.js +6 -0
  85. package/dist/host/in-process.js +4 -0
  86. package/dist/host/index.d.ts +1 -0
  87. package/dist/host/index.js +1 -0
  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 -0
  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 -0
  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 -172
  128. package/dist/host/ports/place-act.js +1 -169
  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 -305
  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 -0
  157. package/dist/host/signing.js +2 -48
  158. package/dist/host/source-content.js +2 -110
  159. package/dist/host/standing-carrier.js +1 -0
  160. package/dist/host/standing-projection.js +1 -0
  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 -302
  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 -40
  182. package/dist/observe/runner.js +4 -93
  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-host.md +21 -0
  212. package/docs/contracts/native-host.publication.json +25 -0
  213. package/docs/contracts/native-publication.inventory.json +3 -1
  214. package/docs/contracts/optional-wasm-adapter.publication.json +1 -1
  215. package/docs/contracts/publication.inventory.json +29 -0
  216. package/docs/contracts/reading-identity.md +37 -0
  217. package/docs/contracts/reading-identity.publication.json +25 -0
  218. package/docs/contracts/refusals.bound +51 -0
  219. package/docs/contracts/refusals.md +18 -3
  220. package/docs/contracts/refusals.publication.json +2 -2
  221. package/docs/contracts/views.md +8 -0
  222. package/docs/guide.md +10 -0
  223. package/docs/reference.md +40 -0
  224. package/docs/why.md +109 -0
  225. package/package.json +37 -18
  226. package/receipts.bound +11675 -9725
  227. package/samples/native-host/no.json +10 -0
  228. package/samples/native-host/yes.json +20 -0
  229. package/samples/reading-identity/no.json +20 -0
  230. package/samples/reading-identity/yes.json +46 -0
  231. package/vectors/native/native-host.vector.json +62 -0
  232. package/vectors/native/reading-identity.vector.json +101 -0
  233. package/vectors/native/refusals.vector.json +104 -0
  234. package/vendor/syntax/LICENSE.md +7 -0
  235. package/vendor/syntax/parser.js +1 -0
  236. package/dist/engine/object.d.ts +0 -17
  237. package/dist/engine/ports.d.ts +0 -32
  238. package/dist/host/native/module-closure.d.ts +0 -35
  239. package/dist/host/reference-export.d.ts +0 -33
  240. package/dist/host/reference-native.d.ts +0 -30
  241. package/dist/host/reference-profile.d.ts +0 -23
  242. package/dist/host/refusals.d.ts +0 -14
@@ -1,183 +1 @@
1
- import * as nodeModule from 'node:module';
2
- import { realpathSync } from 'node:fs';
3
- import { join, relative, isAbsolute, sep } from 'node:path';
4
- import { pathToFileURL } from 'node:url';
5
- import { fieldOf } from "../fold/claims.js";
6
- import { observeText } from "../observe/files.js";
7
- import { ownLock, ownStore, ownRoot } from "../observe/runner.js";
8
- import { runtimeTreeAt } from "./release.js";
9
- import { ContentNeeded } from "./content-needed.js";
10
- import { theWord } from "../fold/wire.js";
11
- const findPackageJSON = nodeModule.findPackageJSON;
12
- const registerHooks = nodeModule.registerHooks;
13
- const taken = (exp) => (typeof exp === 'string' ? exp : exp && typeof exp === 'object' && 'default' in exp && typeof exp.default === 'string' ? exp.default : '');
14
- /**
15
- * Resolve declared library bytes for this host. A library's shape may select an
16
- * archive coordinate; world selection remains the standing contract.
17
- */
18
- export function pinPlace(name) {
19
- const lock = ownLock();
20
- const line = lock.find((one) => fieldOf(one, 'scope') === `dep/${name}` && fieldOf(one, 'role') === 'reads')
21
- ?? lock.find((one) => fieldOf(one, 'scope') === `uses/${name}`);
22
- if (line === undefined)
23
- return '';
24
- const digest = fieldOf(line, 'value');
25
- return digest ? runtimeTreeAt(ownStore(), ownRoot(), digest, ownStore(), fieldOf(line, 'role') === 'reads' ? fieldOf(line, 'shape') : '') ?? '' : '';
26
- }
27
- export function pinExport(name, sub) {
28
- const at = pinPlace(name);
29
- const file = taken(JSON.parse(observeText(join(at, manifestOf())) ?? '{}').exports?.[sub]);
30
- return at && file ? join(at, file) : '';
31
- }
32
- export function pinName(name) {
33
- const at = pinPlace(name);
34
- return at ? (JSON.parse(observeText(join(at, manifestOf())) ?? '{}').name ?? '') : '';
35
- }
36
- const manifestOf = () => `${theWord(ownLock(), 'pin-shape')}.json`;
37
- /** Node package resolution at a digest-laid library; exports remain authoritative. */
38
- export function resolvePinned(specifier, context, nextResolve, pin) {
39
- if (pin.exports)
40
- return nextResolve(specifier, { ...context, parentURL: pin.json });
41
- const sub = specifier === pin.pkg ? '' : specifier.slice(pin.pkg.length + 1);
42
- const requested = join(pin.at, sub);
43
- const coordinate = relative(pin.at, requested);
44
- if (isAbsolute(coordinate) || coordinate === '..' || coordinate.startsWith(`..${sep}`))
45
- throw new Error('REFUSE·pin library import leaves its laid tree');
46
- const file = nodeModule.createRequire(pin.json).resolve(requested);
47
- const entry = relative(realpathSync(pin.at), realpathSync(file));
48
- if (isAbsolute(entry) || entry === '..' || entry.startsWith(`..${sep}`))
49
- throw new Error('REFUSE·pin library entry leaves its laid tree');
50
- return nextResolve(pathToFileURL(file).href, context);
51
- }
52
- /**
53
- * A blob stays self-contained. The one thing it does not carry is the SDK the host provides: an import whose package
54
- * the instrument's own lock names at dep/<name> resolves at the place pinPlace delivers. Nothing is linked into the
55
- * blob's folder.
56
- */
57
- let hooked = false;
58
- function nativeResolution() {
59
- const installed = Object.getOwnPropertyDescriptor(globalThis, Symbol.for('bound.native.resolution@1'));
60
- if (!installed)
61
- return undefined;
62
- const capability = installed.value;
63
- if (installed.configurable !== false || installed.writable !== false || !capability || !Object.isFrozen(capability) || capability.profile !== 'fixed-native-resolution@1' || !Array.isArray(capability.libraryNames) || !Object.isFrozen(capability.libraryNames) || capability.libraryNames.some(name => typeof name !== 'string') || !Array.isArray(capability.libraries) || !Object.isFrozen(capability.libraries) || capability.libraries.some(lib => !lib || !Object.isFrozen(lib) || typeof lib.name !== 'string' || typeof lib.manifest !== 'string') || typeof capability.assertPins !== 'function')
64
- throw Error('REFUSE·pin fixed resolution capability invalid');
65
- return capability;
66
- }
67
- /** Fixed execution selects libraries by the instrument's explicit local mount,
68
- * before opening any artifact. An alias or package-name guess grants nothing. */
69
- export function selectNativeDependencies(root, dependencies, manifest) {
70
- const capability = nativeResolution();
71
- if (!capability)
72
- return undefined;
73
- if (dependencies.length && capability.libraries.some(library => typeof library.coordinate !== 'string' || !library.coordinate))
74
- throw Error('REFUSE·pin fixed resolution logical library coordinate missing');
75
- const selected = new Map(capability.libraries.map(library => [library.coordinate, library]));
76
- return dependencies.flatMap(line => {
77
- const mount = fieldOf(line, 'needs');
78
- if (!mount)
79
- return [];
80
- const library = selected.get(mount.replace(/\/+$/, '') + '/' + manifest);
81
- if (!library)
82
- return [];
83
- let actual;
84
- try {
85
- actual = realpathSync(join(root, mount, manifest));
86
- }
87
- catch {
88
- throw Error('REFUSE·pin selected library mount absent ' + library.name);
89
- }
90
- if (actual !== library.manifest)
91
- throw Error('REFUSE·pin selected library mount differs ' + library.name);
92
- return [{ line, library }];
93
- });
94
- }
95
- /** A declared artifact is not automatically an active Node library. This fixed
96
- * assertion reuses only the packages selected by the actual host boundary. */
97
- export function reuseNativeResolution(pins) {
98
- const capability = nativeResolution();
99
- if (!capability)
100
- return false;
101
- const selected = new Set(capability.libraryNames);
102
- // The fixed preload owns this closed assertion. Package names select which
103
- // declared pins participate; exact manifests and member bytes still decide.
104
- capability.assertPins(pins.filter(pin => selected.has(pin.pkg)).map(pin => ({ name: pin.pkg, at: pin.at })));
105
- return true;
106
- }
107
- /** Read one resolved archive's manifest; a selected fixed library cannot vanish
108
- * into the optional historical provider path when its archive is absent. */
109
- export function readProvidedPin(name, at, file, requiredName) {
110
- if (!at) {
111
- if (requiredName !== undefined)
112
- throw Error('REFUSE·pin fixed resolution requires declared library ' + name);
113
- return undefined;
114
- }
115
- const manifest = JSON.parse(observeText(join(at, file)) ?? '{}'), pkg = typeof manifest.name === 'string' ? manifest.name : '';
116
- if (requiredName !== undefined && pkg !== requiredName)
117
- throw Error('REFUSE·pin fixed resolution library name differs ' + name);
118
- return pkg ? { at, pkg, exports: Object.prototype.hasOwnProperty.call(manifest, 'exports'), href: pathToFileURL(at).href, json: pathToFileURL(join(at, file)).href } : undefined;
119
- }
120
- export function provide() {
121
- if (hooked)
122
- return;
123
- const dependencies = ownLock().filter((line) => fieldOf(line, 'scope').startsWith('dep/') && fieldOf(line, 'role') === 'reads');
124
- const file = manifestOf(), selected = selectNativeDependencies(ownRoot(), dependencies, file);
125
- const load = (line, requiredName) => {
126
- const name = fieldOf(line, 'scope').slice('dep/'.length), at = pinPlace(name);
127
- if (!at)
128
- throw new ContentNeeded(fieldOf(line, 'value'), 'REFUSE·pin declared library unavailable ' + name);
129
- const pin = readProvidedPin(name, at, file, requiredName);
130
- if (!pin)
131
- throw Error('REFUSE·pin declared library unavailable ' + name);
132
- return pin;
133
- };
134
- if (selected !== undefined) {
135
- reuseNativeResolution(selected.map(({ line, library }) => load(line, library.name)));
136
- hooked = true;
137
- return;
138
- }
139
- // A mount selects a library, but its manifest is only a routing hint until
140
- // an import requests it. The selected archive alone supplies executable bytes.
141
- const mounts = dependencies.filter(line => fieldOf(line, 'needs') !== '').map(line => {
142
- const mount = join(ownRoot(), fieldOf(line, 'needs'));
143
- const manifest = JSON.parse(observeText(join(mount, file)) ?? '{}');
144
- return { line, mount, pkg: typeof manifest.name === 'string' ? manifest.name : '' };
145
- });
146
- const verified = new Map();
147
- registerHooks({
148
- resolve(specifier, context, nextResolve) {
149
- if (specifier.startsWith('.') || specifier.startsWith('/') || specifier.includes(':'))
150
- return nextResolve(specifier, context);
151
- let selected = mounts.find(one => one.pkg && (specifier === one.pkg || specifier.startsWith(one.pkg + '/')));
152
- if (!selected) {
153
- // Identify the installed package before following its executable entry:
154
- // a renamed manifest and an escaping entry cannot bypass the declared mount.
155
- let manifest;
156
- try {
157
- manifest = findPackageJSON(specifier, pathToFileURL(join(ownRoot(), file)).href);
158
- }
159
- catch { }
160
- if (manifest)
161
- selected = mounts.find(one => {
162
- try {
163
- return realpathSync(join(one.mount, file)) === realpathSync(manifest);
164
- }
165
- catch {
166
- return false;
167
- }
168
- });
169
- }
170
- if (!selected)
171
- return nextResolve(specifier, context);
172
- let pin = verified.get(selected.line);
173
- if (!pin) {
174
- pin = load(selected.line);
175
- verified.set(selected.line, pin);
176
- }
177
- if (specifier !== pin.pkg && !specifier.startsWith(pin.pkg + '/'))
178
- throw Error('REFUSE·pin selected library name differs');
179
- return resolvePinned(specifier, context, nextResolve, pin);
180
- },
181
- });
182
- hooked = true;
183
- }
1
+ var P=Object.defineProperty;var f=(r,e)=>P(r,"name",{value:e,configurable:!0});import*as E from"node:module";import{realpathSync as y}from"node:fs";import{join as d,relative as F,isAbsolute as O,sep as R}from"node:path";import{pathToFileURL as h}from"node:url";import{fieldOf as c}from"../fold/claims.js";import{observeText as b}from"../observe/files.js";import{ownLock as w,ownStore as U,ownRoot as g}from"../observe/runner.js";import{runtimeTreeAt as W}from"./release.js";import{ContentNeeded as x}from"./content-needed.js";import{theWord as A}from"../fold/wire.js";const J=E.findPackageJSON,$=E.registerHooks,z=f(r=>typeof r=="string"?r:r&&typeof r=="object"&&"default"in r&&typeof r.default=="string"?r.default:"","taken");function S(r){const e=w(),o=e.find(l=>c(l,"scope")===`dep/${r}`&&c(l,"role")==="reads")??e.find(l=>c(l,"scope")===`uses/${r}`);if(o===void 0)return"";const n=c(o,"value");return n?W(U(),g(),n,U(),c(o,"role")==="reads"?c(o,"shape"):"")??"":""}f(S,"pinPlace");function Y(r,e){const o=S(r),n=z(JSON.parse(b(d(o,k()))??"{}").exports?.[e]);return o&&n?d(o,n):""}f(Y,"pinExport");function Z(r){const e=S(r);return e?JSON.parse(b(d(e,k()))??"{}").name??"":""}f(Z,"pinName");const k=f(()=>`${A(w(),"pin-shape")}.json`,"manifestOf");function M(r,e,o,n){if(n.exports)return o(r,{...e,parentURL:n.json});const l=r===n.pkg?"":r.slice(n.pkg.length+1),s=d(n.at,l),t=F(n.at,s);if(O(t)||t===".."||t.startsWith(`..${R}`))throw new Error("REFUSE\xB7pin library import leaves its laid tree");const i=E.createRequire(n.json).resolve(s),a=F(y(n.at),y(i));if(O(a)||a===".."||a.startsWith(`..${R}`))throw new Error("REFUSE\xB7pin library entry leaves its laid tree");return o(h(i).href,e)}f(M,"resolvePinned");let v=!1;function j(){const r=Object.getOwnPropertyDescriptor(globalThis,Symbol.for("bound.native.resolution@1"));if(!r)return;const e=r.value;if(r.configurable!==!1||r.writable!==!1||!e||!Object.isFrozen(e)||e.profile!=="fixed-native-resolution@1"||!Array.isArray(e.libraryNames)||!Object.isFrozen(e.libraryNames)||e.libraryNames.some(o=>typeof o!="string")||!Array.isArray(e.libraries)||!Object.isFrozen(e.libraries)||e.libraries.some(o=>!o||!Object.isFrozen(o)||typeof o.name!="string"||typeof o.manifest!="string")||typeof e.assertPins!="function")throw Error("REFUSE\xB7pin fixed resolution capability invalid");return e}f(j,"nativeResolution");function T(r,e,o){const n=j();if(!n)return;if(e.length&&n.libraries.some(s=>typeof s.coordinate!="string"||!s.coordinate))throw Error("REFUSE\xB7pin fixed resolution logical library coordinate missing");const l=new Map(n.libraries.map(s=>[s.coordinate,s]));return e.flatMap(s=>{const t=c(s,"needs");if(!t)return[];const i=l.get(t.replace(/\/+$/,"")+"/"+o);if(!i)return[];let a;try{a=y(d(r,t,o))}catch{throw Error("REFUSE\xB7pin selected library mount absent "+i.name)}if(a!==i.manifest)throw Error("REFUSE\xB7pin selected library mount differs "+i.name);return[{line:s,library:i}]})}f(T,"selectNativeDependencies");function L(r){const e=j();if(!e)return!1;const o=new Set(e.libraryNames);return e.assertPins(r.filter(n=>o.has(n.pkg)).map(n=>({name:n.pkg,at:n.at}))),!0}f(L,"reuseNativeResolution");function D(r,e,o,n){if(!e){if(n!==void 0)throw Error("REFUSE\xB7pin fixed resolution requires declared library "+r);return}const l=JSON.parse(b(d(e,o))??"{}"),s=typeof l.name=="string"?l.name:"";if(n!==void 0&&s!==n)throw Error("REFUSE\xB7pin fixed resolution library name differs "+r);return s?{at:e,pkg:s,exports:Object.prototype.hasOwnProperty.call(l,"exports"),href:h(e).href,json:h(d(e,o)).href}:void 0}f(D,"readProvidedPin");function _(){if(v)return;const r=w().filter(t=>c(t,"scope").startsWith("dep/")&&c(t,"role")==="reads"),e=k(),o=T(g(),r,e),n=f((t,i)=>{const a=c(t,"scope").slice(4),u=S(a);if(!u)throw new x(c(t,"value"),"REFUSE\xB7pin declared library unavailable "+a);const p=D(a,u,e,i);if(!p)throw Error("REFUSE\xB7pin declared library unavailable "+a);return p},"load");if(o!==void 0){L(o.map(({line:t,library:i})=>n(t,i.name))),v=!0;return}const l=r.filter(t=>c(t,"needs")!=="").map(t=>{const i=d(g(),c(t,"needs")),a=JSON.parse(b(d(i,e))??"{}");return{line:t,mount:i,pkg:typeof a.name=="string"?a.name:""}}),s=new Map;$({resolve(t,i,a){if(t.startsWith(".")||t.startsWith("/")||t.includes(":"))return a(t,i);let u=l.find(m=>m.pkg&&(t===m.pkg||t.startsWith(m.pkg+"/")));if(!u){let m;try{m=J(t,h(d(g(),e)).href)}catch{}m&&(u=l.find(N=>{try{return y(d(N.mount,e))===y(m)}catch{return!1}}))}if(!u)return a(t,i);let p=s.get(u.line);if(p||(p=n(u.line),s.set(u.line,p)),t!==p.pkg&&!t.startsWith(p.pkg+"/"))throw Error("REFUSE\xB7pin selected library name differs");return M(t,i,a,p)}}),v=!0}f(_,"provide");export{Y as pinExport,Z as pinName,S as pinPlace,_ as provide,D as readProvidedPin,M as resolvePinned,L as reuseNativeResolution,T as selectNativeDependencies};
@@ -1,9 +1 @@
1
- import { AsyncLocalStorage } from 'node:async_hooks';
2
- /** Prospective evaluation may read existing evidence and calculate values, but cannot acquire evidence or persist caches. */
3
- const mode = new AsyncLocalStorage();
4
- export const readOnly = () => mode.getStore() === true;
5
- export const withoutEffects = (evaluate) => mode.run(true, evaluate);
6
- export function requireEffects(operation) {
7
- if (readOnly())
8
- throw Error(`REFUSE·preview ${operation} requires an act; fold the declared inputs first`);
9
- }
1
+ var n=Object.defineProperty;var r=(e,o)=>n(e,"name",{value:o,configurable:!0});import{AsyncLocalStorage as c}from"node:async_hooks";const t=new c,f=r(()=>t.getStore()===!0,"readOnly"),u=r(e=>t.run(!0,e),"withoutEffects");function a(e){if(f())throw Error(`REFUSE\xB7preview ${e} requires an act; fold the declared inputs first`)}r(a,"requireEffects");export{f as readOnly,a as requireEffects,u as withoutEffects};
@@ -1,227 +1,7 @@
1
- import { actCosts } from "./act-cost.js";
2
- import { mkdirSync, readFileSync, existsSync } from 'node:fs';
3
- import { join, dirname } from 'node:path';
4
- import { canonical, parse, PROTOCOL, byBytes } from '@lapxo/topos/wire';
5
- import { replaceWhole, landShard, shardLines } from "../land/ledger.js";
6
- import { fieldOf } from "../fold/claims.js";
7
- import { readOnly } from "./read-only.js";
8
- import { readingIdentityBytes, readingReceiptIdentity, responseIdentity, snapshotAccess, placeInputs, withPlaceInputs } from '@lapxo/topos/contract';
9
- import { withReadingBoundary } from "./reading-context.js";
10
- const receiptScope = (scope) => [scope, 'identity'].join('/');
11
- const fields = (line) => { const got = parse(line); if (got.kind !== 'fact')
12
- throw Error('REFUSE·input projection contains a non-wire line'); return got.value.fields; };
13
- export const inputLines = (files) => files.map(file => canonical({ scope: file.place, form: 'alphabet', measure: 'text', role: 'writes', value: 'lock', shape: file.place, about: file.text, by: 'host', at: 'policy:handed-input' }));
14
- /** One portable native receipt carrier shared by file plans and native capsule batches. */
15
- export function portableReadingReceipt(scope, by, closure, output, hash, modern = true, costs = []) {
16
- const input = hash(closure), payload = hash(output), rows = output.split('\n').filter(Boolean);
17
- return [...(modern ? [canonical({ scope: receiptScope(scope), role: 'writes', form: 'alphabet', measure: 'digest', value: readingReceiptIdentity(input, payload, bytes => hash(new TextDecoder().decode(bytes))), by, at: 'place:' + input })] : []), canonical({ scope, role: 'writes', form: 'alphabet', measure: 'observed', value: payload, by, at: 'place:' + payload }), canonical({ scope, role: 'writes', form: 'alphabet', measure: 'bytes', value: input, by, at: 'place:' + input, about: closure }), canonical({ scope, role: 'writes', form: 'interval', measure: 'count', value: `${rows.length}..${rows.length}`, by, at: 'place:' + payload, about: output }), ...costs];
18
- }
19
- /** The selected world owns input projection and reading. The host only verifies closures and keeps native count/bytes receipts. */
20
- export function readingClosures(options) {
21
- const { root, store, reader, speaker, digest: hash, capsule, region, projection, files } = options, emit = options.emit ?? (() => { });
22
- options.assertCurrent?.();
23
- if (options.context)
24
- readingIdentityBytes(options.context);
25
- let access = [];
26
- if (options.current) {
27
- if (!options.context)
28
- throw Error('REFUSE·current reading requires a declared identity');
29
- const { snapshot, kept, current, permission } = options.current;
30
- if (current.implementation !== options.context.implementation)
31
- throw Error('REFUSE·current reading implementation differs from its verified context');
32
- const response = responseIdentity(snapshot, current, hash), allowed = snapshotAccess(snapshot, kept, current, permission, hash);
33
- if (!allowed.inspect || !allowed.reuse)
34
- throw Error('REFUSE·current reading is not admitted for reuse');
35
- access = [['response', response], ['permission', hash(JSON.stringify([permission.inspect, permission.reuse, permission.freshness]))]];
36
- }
37
- if (options.execution && (!options.context || JSON.stringify(readingIdentityBytes(options.execution.context)) !== JSON.stringify(readingIdentityBytes(options.context))))
38
- throw Error('REFUSE·reading execution differs from declared context');
39
- const projectionFor = (name) => {
40
- if (!capsule.selectedWorld)
41
- return undefined;
42
- const { standing, offer } = capsule.selectedWorld;
43
- const selectors = standing.parts.some(part => part.scope === `${offer}/place-inputs/${name}` && part.measure === 'reads');
44
- if (!selectors)
45
- return undefined;
46
- if (!options.context || !options.execution || !options.livePlace)
47
- throw Error('REFUSE·place inputs require authenticated shadow and reading context ' + name);
48
- return placeInputs(standing, offer, name, options.livePlace(), bytes => hash(new TextDecoder().decode(bytes)));
49
- };
50
- const projectedPlace = projectionFor(projection), readingPlace = projectionFor(region);
51
- const commit = (context, name, place) => place && context ? withPlaceInputs(context, JSON.stringify(['place-inputs', capsule.selectedWorld.offer, name]), place) : context;
52
- const ask = (identity, requests, context = options.context) => withReadingBoundary(identity, options.execution && context ? { ...options.execution, context } : options.execution, () => capsule.ask(requests, options.readerReference));
53
- const projectionContext = commit(options.context, projection, projectedPlace);
54
- const base = projectionContext ? hash(new TextDecoder().decode(readingIdentityBytes(projectionContext))) : '';
55
- const algorithm = hash('').split(':')[0], handed = new Map(files.map(file => [file.place, file.text]));
56
- if (handed.size !== files.length)
57
- throw Error('REFUSE·input projection has duplicate handed coordinates');
58
- const verify = () => { for (const file of files)
59
- if (!readFileSync(join(root, file.place)).equals(Buffer.from(file.text)))
60
- throw Error('REFUSE·input changed ' + file.place); };
61
- verify();
62
- const projected = ask(base, [{ ...(projectedPlace ? { place: projectedPlace } : {}), protocol: PROTOCOL, verb: 'render', rootScope: '', region: projection, at: 1, reads: ['**'], lines: inputLines(files), files: [] }], projectionContext)[0];
63
- if (projected?.kind !== 'fact' || !Array.isArray(projected.lines))
64
- throw Error('REFUSE·input projection ' + (projected?.why ?? 'no lines'));
65
- const plans = new Map();
66
- for (const line of projected.lines) {
67
- const f = fields(line), scope = f.scope ?? '', resolution = /^receipt:(\d+)$/.exec(f.at ?? '');
68
- if (!scope || plans.has(scope) || f.form !== 'alphabet' || f.measure !== 'reads' || f.role !== 'reads' || !resolution)
69
- throw Error('REFUSE·input projection ambiguous reading ' + scope);
70
- const inputs = (f.value ?? '').split('|').filter(Boolean), needs = (f.needs ?? '').split('|').filter(Boolean);
71
- // An aggregate reads its declared receipts; it need not reread a leaf file.
72
- if ((!inputs.length && !needs.length) || new Set(inputs).size !== inputs.length || inputs.some(input => !handed.has(input)) || new Set(needs).size !== needs.length)
73
- throw Error('REFUSE·input projection has unhanded or duplicate dependencies ' + scope);
74
- const n = Number(resolution[1]);
75
- if (!Number.isSafeInteger(n))
76
- throw Error('REFUSE·input projection invalid resolution ' + scope);
77
- plans.set(scope, { scope, inputs, needs, resolution: n, line: canonical({ scope, form: f.form, measure: f.measure, role: f.role, value: inputs.join('|'), needs: needs.join('|'), at: f.at }) });
78
- }
79
- if (!plans.size)
80
- throw Error('REFUSE·input projection returned no readings');
81
- const ordered = [], visiting = new Set(), done = new Set();
82
- const visit = (scope) => { if (done.has(scope))
83
- return; if (visiting.has(scope))
84
- throw Error('REFUSE·input projection dependency cycle ' + scope); const p = plans.get(scope); if (!p)
85
- throw Error('REFUSE·input projection missing reading ' + scope); visiting.add(scope); for (const need of p.needs)
86
- visit(need); visiting.delete(scope); done.add(scope); ordered.push(p); };
87
- for (const scope of plans.keys())
88
- visit(scope);
89
- const identity = hash([capsule.selection ?? '', capsule.digest, region, projection, ...(options.lifetime === undefined ? [] : [JSON.stringify(options.lifetime)])].join('\n')), by = speaker + ':' + identity.split(':')[1].slice(0, 12), journal = 'reading-closures/' + identity.split(':')[1];
90
- const prior = shardLines(store, speaker, journal), results = new Map(), out = [];
91
- const carried = (digest) => join(store, 'cas', 'carried', digest.split(':')[1] ?? '');
92
- const saved = (text) => { const digest = hash(text), path = carried(digest); mkdirSync(dirname(path), { recursive: true }); if (!existsSync(path) || hash(readFileSync(path, 'utf8')) !== digest)
93
- replaceWhole(path, text); return digest; };
94
- const load = (digest) => { if (!digest.startsWith(algorithm + ':') || !/^[a-f0-9]+$/.test(digest.split(':')[1] ?? ''))
95
- return; const path = carried(digest); if (!existsSync(path))
96
- return; const text = readFileSync(path, 'utf8'); return hash(text) === digest ? text : undefined; };
97
- let read = 0, opened = 0, executed = 0;
98
- for (const plan of ordered) {
99
- actCosts.measure(() => {
100
- // Retained evidence does not authorize a current answer.
101
- options.assertCurrent?.();
102
- const legacyClosure = [plan.line, canonical({ scope: 'implementation', role: 'writes', form: 'alphabet', measure: 'digest', value: identity, by: 'host', at: 'policy:input-identity' }), ...plan.inputs.map(input => canonical({ scope: input, role: 'writes', form: 'alphabet', measure: 'digest', value: hash(handed.get(input)), by: 'host', at: 'policy:input-identity' })), ...plan.needs.map(need => canonical({ scope: need, role: 'writes', form: 'alphabet', measure: 'digest', value: results.get(need).digest, by: 'host', at: 'policy:input-identity' }))].sort(byBytes).join('\n') + '\n';
103
- const leafContext = commit(options.context, region, readingPlace);
104
- const context = leafContext && { ...leafContext, policy: hash(JSON.stringify([leafContext.policy, options.allowsEmpty === true, options.lifetime ?? null, options.readerReference ?? null, capsule.selection ?? null, capsule.lines])), inputs: [...[...leafContext.inputs, ...access].map(([name, digest]) => [JSON.stringify(['context', name]), digest]), [JSON.stringify(['plan']), hash(plan.line)], ...plan.inputs.map(input => [JSON.stringify(['file', input]), hash(handed.get(input))]), ...plan.needs.map(need => [JSON.stringify(['receipt', need]), results.get(need).digest])] };
105
- const closure = context ? new TextDecoder().decode(readingIdentityBytes(context)) : legacyClosure;
106
- const input = hash(closure), scope = 'receipts/readings/' + hash(plan.scope).split(':')[1] + '/' + input.split(':')[1], matching = prior.filter(line => fieldOf(line, 'scope') === scope && fieldOf(line, 'measure') === 'bytes' && fieldOf(line, 'value') === input).at(-1);
107
- const count = matching && prior.filter(line => fieldOf(line, 'scope') === scope && fieldOf(line, 'measure') === 'count' && fieldOf(line, 'by') === by).at(-1);
108
- const heldOutput = count && load(fieldOf(count, 'at').replace(/^place:/, ''));
109
- const heldLines = heldOutput?.split('\n').filter(Boolean);
110
- const output = heldLines !== undefined && fieldOf(count, 'value') === `${heldLines.length}..${heldLines.length}` && heldLines.every(line => { const f = fields(line); return f.by === by && f.at === 'place:' + input; }) ? heldOutput : undefined;
111
- let lines, payload;
112
- if (output !== undefined && load(input) === closure) {
113
- if (output === '' && !options.allowsEmpty)
114
- throw Error('REFUSE·reading empty response is not admitted ' + plan.scope);
115
- lines = output.split('\n').filter(Boolean);
116
- for (const line of lines)
117
- fields(line);
118
- payload = fieldOf(count, 'at').replace(/^place:/, '');
119
- }
120
- else {
121
- if (readOnly())
122
- throw Error('REFUSE·preview reading closure is unpaid ' + plan.scope);
123
- const started = process.hrtime.bigint();
124
- const dependencies = plan.needs.flatMap(need => results.get(need).lines), answer = ask(input, [{ ...(readingPlace ? { place: readingPlace } : {}), protocol: PROTOCOL, verb: 'read', rootScope: plan.scope, name: plan.scope, region, at: plan.resolution, reads: ['**'], lines: [...inputLines(plan.inputs.map(place => ({ place, text: handed.get(place) }))), ...dependencies], files: [] }], context)[0];
125
- if (answer?.kind !== 'fact' || !Array.isArray(answer.claims))
126
- throw Error('REFUSE·reading ' + plan.scope + ' · ' + (answer?.why ?? 'no claims'));
127
- lines = answer.claims.map((unknown) => { if (typeof unknown?.scope !== 'string' || typeof unknown?.measure !== 'string' || typeof unknown?.role !== 'string' || !unknown.bound || !['interval', 'enumerated'].includes(unknown.bound.kind))
128
- throw Error('REFUSE·reading malformed claim ' + plan.scope); const span = unknown.bound; const text = canonical({ scope: unknown.scope, measure: unknown.measure, role: unknown.role, form: span.kind === 'interval' ? 'interval' : 'alphabet', value: span.kind === 'interval' ? `${span.lo}..${span.hi}` : Array.isArray(span.values) ? span.values.join('|') : '', by, at: 'place:' + input }); fields(text); return text; });
129
- if (!lines.length && !options.allowsEmpty)
130
- throw Error('REFUSE·reading empty response is not admitted ' + plan.scope);
131
- executed++;
132
- verify();
133
- options.assertCurrent?.();
134
- payload = saved(lines.length ? [...lines].sort(byBytes).join('\n') + '\n' : '');
135
- if (saved(closure) !== input)
136
- throw Error('REFUSE·receipt input closure mismatch');
137
- const seconds = (Number(process.hrtime.bigint() - started) / 1e9).toFixed(6);
138
- landShard(store, speaker, journal, [canonical({ scope, role: 'writes', form: 'interval', measure: 'count', value: `${lines.length}..${lines.length}`, by, at: 'place:' + payload }), canonical({ scope, role: 'writes', form: 'alphabet', measure: 'bytes', value: input, by, at: 'place:' + input }), canonical({ scope, role: 'writes', form: 'interval', measure: 's', value: seconds + '..' + seconds, by, at: 'place:' + input })]);
139
- if (plan.resolution === 1)
140
- opened++;
141
- }
142
- const receipt = context ? readingReceiptIdentity(input, payload, bytes => hash(new TextDecoder().decode(bytes))) : payload;
143
- if (context && plan.resolution !== 1)
144
- out.push(canonical({ scope: receiptScope(scope), role: 'writes', form: 'alphabet', measure: 'digest', value: receipt, by, at: 'place:' + input }));
145
- results.set(plan.scope, { digest: receipt, lines });
146
- out.push(canonical({ scope: plan.scope, role: 'writes', form: 'alphabet', measure: 'observed', value: input, by, at: 'place:' + input }),
147
- // A logical reading name is not a physical input coordinate. Preserve the
148
- // host-verified handoff beside the result so portable file seals retain
149
- // every input, including explicitly read foreign files.
150
- // Input witnesses do not locate the result at each input. Result attribution
151
- // remains the logical reading's place; two inputs are not two new origins.
152
- ...plan.inputs.map(coordinate => canonical({ scope: coordinate, role: 'writes', form: 'alphabet', measure: 'observed', value: hash(handed.get(coordinate)), by, at: 'witness:' + input })), ...lines);
153
- if (plan.resolution === 1) {
154
- read++;
155
- const output = load(payload);
156
- if (output === undefined)
157
- throw Error('REFUSE·receipt missing verified carrier ' + payload);
158
- const costs = shardLines(store, speaker, journal).filter(line => fieldOf(line, 'scope') === scope && fieldOf(line, 'measure') === 's' && fieldOf(line, 'at') === 'place:' + input);
159
- out.push(...portableReadingReceipt(scope, by, closure, output, hash, !!context, costs));
160
- }
161
- });
162
- }
163
- verify();
164
- emit(`RECEIPTS ${read} read · ${opened} opened · reading closures`);
165
- return { lines: out, read, opened, executed };
166
- }
167
- /** Verify the native reading carriers before a file seal may reuse them. These are semantic receipts, not file-region seals. */
168
- export function verifiedReadingReceipts(store, lines, digest, environment, requireContext = false) {
169
- const units = lines.filter(line => fieldOf(line, 'scope').startsWith('receipts/readings/') && fieldOf(line, 'measure') === 'bytes' && fieldOf(line, 'role') === 'writes');
170
- const load = (id, row) => {
171
- const hex = id.split(':')[1];
172
- if (!hex || !/^[a-f0-9]+$/.test(hex))
173
- return;
174
- const supplied = fields(row).about;
175
- // A supplied carrier must authenticate even if an old local copy still exists.
176
- if (supplied !== undefined)
177
- return digest(supplied) === id ? supplied : undefined;
178
- const path = join(store, 'cas', 'carried', hex);
179
- if (!existsSync(path))
180
- return;
181
- const bytes = readFileSync(path, 'utf8');
182
- return digest(bytes) === id ? bytes : undefined;
183
- };
184
- for (const unit of units) {
185
- const input = fieldOf(unit, 'value'), scope = fieldOf(unit, 'scope'), by = fieldOf(unit, 'by'), counts = lines.filter(line => fieldOf(line, 'scope') === scope && fieldOf(line, 'measure') === 'count' && fieldOf(line, 'by') === by && fieldOf(line, 'role') === 'writes');
186
- if (counts.length !== 1 || load(input, unit) === undefined)
187
- return;
188
- const count = counts[0], output = load(fieldOf(count, 'at').replace(/^place:/, ''), count);
189
- if (output === undefined)
190
- return;
191
- const inputBytes = load(input, unit);
192
- if (inputBytes.trimStart().startsWith('[')) {
193
- let context;
194
- try {
195
- context = JSON.parse(inputBytes);
196
- }
197
- catch {
198
- return;
199
- }
200
- if (!Array.isArray(context) || context.length !== 6 || context[0] !== 'reading-context@1')
201
- return;
202
- const canonicalContext = { instrument: context[1], implementation: context[2], policy: context[3], inputs: context[4], environment: context[5] };
203
- try {
204
- if (new TextDecoder().decode(readingIdentityBytes(canonicalContext)) !== inputBytes)
205
- return;
206
- }
207
- catch {
208
- return;
209
- }
210
- if (environment) {
211
- const expected = typeof environment === 'function' ? environment(canonicalContext) : environment;
212
- if (expected === undefined || JSON.stringify([...expected].sort((a, b) => byBytes(a[0], b[0]))) !== JSON.stringify(context[5]))
213
- return;
214
- }
215
- const identity = lines.filter(line => fieldOf(line, 'scope') === receiptScope(scope) && fieldOf(line, 'measure') === 'digest' && fieldOf(line, 'by') === by && fieldOf(line, 'role') === 'writes' && fieldOf(line, 'at') === 'place:' + input);
216
- const expected = readingReceiptIdentity(input, fieldOf(count, 'at').replace(/^place:/, ''), bytes => digest(new TextDecoder().decode(bytes)));
217
- if (identity.length !== 1 || fieldOf(identity[0], 'value') !== expected)
218
- return;
219
- }
220
- else if (requireContext || !inputBytes.endsWith('\n') || inputBytes.split('\n').filter(Boolean).some(line => parse(line).kind !== 'fact'))
221
- return;
222
- const rows = output.split('\n').filter(Boolean);
223
- if (fieldOf(count, 'value') !== `${rows.length}..${rows.length}` || rows.some(line => fieldOf(line, 'by') !== by || fieldOf(line, 'at') !== 'place:' + input))
224
- return;
225
- }
226
- return units.length;
227
- }
1
+ var Z=Object.defineProperty;var B=(s,c)=>Z(s,"name",{value:c,configurable:!0});import{actCosts as k}from"./act-cost.js";import{readFileSync as ee,existsSync as re}from"node:fs";import{join as te}from"node:path";import{library11_canonical as u,library11_parse as se,library11_PROTOCOL as ae,library11_byBytes as X}from"../vendor/runtime.js";import{landShard as oe,shardLines as ie}from"../land/ledger.js";import{fieldOf as e}from"../fold/claims.js";import{readOnly as ne}from"./read-only.js";import{library2_readingIdentityBytes as le,library2_readingReceiptIdentity as q}from"../vendor/runtime.js";import{readingPreparation as ce,inputLines as pe,readingFields as Y}from"./reading-preparation.js";import{inputLines as $e}from"./reading-preparation.js";const z=B(s=>[s,"identity"].join("/"),"receiptScope");function de(s,c,m,y,b,v=!0,$=[]){const t=b(m),i=b(y),f=y.split(`
2
+ `).filter(Boolean);return[...v?[u({scope:z(s),role:"writes",form:"alphabet",measure:"digest",value:q(t,i,p=>b(new TextDecoder().decode(p))),by:c,at:"place:"+t})]:[],u({scope:s,role:"writes",form:"alphabet",measure:"observed",value:i,by:c,at:"place:"+i}),u({scope:s,role:"writes",form:"alphabet",measure:"bytes",value:t,by:c,at:"place:"+t,about:m}),u({scope:s,role:"writes",form:"interval",measure:"count",value:`${f.length}..${f.length}`,by:c,at:"place:"+i,about:y}),...$]}B(de,"portableReadingReceipt");function xe(s){const{root:c,store:m,reader:y,speaker:b,digest:v,capsule:$,region:t,projection:i,files:f}=s,p=s.emit??(()=>{}),{ordered:S,identity:w,by:d,journal:E,prior:j,prepare:r,retained:A,verify:C,ask:L,load:l,saved:U,handed:_,readingPlace:G}=ce(s),P=new Map,I=[];let D=0,N=0,H=0;for(const a of S)k.measure(()=>{s.assertCurrent?.();const{context:T,closure:J,input:n,scope:R}=r(a,P),W=A({context:T,closure:J,input:n,scope:R});let g,O;if(W)g=W.lines,O=W.payload;else{if(ne())throw Error("REFUSE\xB7preview reading closure is unpaid "+a.scope);const h=process.hrtime.bigint(),M=a.needs.flatMap(o=>P.get(o).lines),x=L(n,[{...G?{place:G}:{},protocol:ae,verb:"read",rootScope:a.scope,name:a.scope,region:t,at:a.resolution,reads:["**"],lines:[...pe(a.inputs.map(o=>({place:o,text:_.get(o)}))),...M],files:[]}],T)[0];if(x?.kind!=="fact"||!Array.isArray(x.claims))throw Error("REFUSE\xB7reading "+a.scope+" \xB7 "+(x?.why??"no claims"));if(g=x.claims.map(o=>{if(typeof o?.scope!="string"||typeof o?.measure!="string"||typeof o?.role!="string"||!o.bound||!["interval","enumerated"].includes(o.bound.kind))throw Error("REFUSE\xB7reading malformed claim "+a.scope);const F=o.bound,V=u({scope:o.scope,measure:o.measure,role:o.role,form:F.kind==="interval"?"interval":"alphabet",value:F.kind==="interval"?`${F.lo}..${F.hi}`:Array.isArray(F.values)?F.values.join("|"):"",by:d,at:"place:"+n});return Y(V),V}),!g.length&&!s.allowsEmpty)throw Error("REFUSE\xB7reading empty response is not admitted "+a.scope);if(H++,C(),s.assertCurrent?.(),O=U(g.length?[...g].sort(X).join(`
3
+ `)+`
4
+ `:""),U(J)!==n)throw Error("REFUSE\xB7receipt input closure mismatch");const Q=(Number(process.hrtime.bigint()-h)/1e9).toFixed(6);oe(m,b,E,[u({scope:R,role:"writes",form:"interval",measure:"count",value:`${g.length}..${g.length}`,by:d,at:"place:"+O}),u({scope:R,role:"writes",form:"alphabet",measure:"bytes",value:n,by:d,at:"place:"+n}),u({scope:R,role:"writes",form:"interval",measure:"s",value:Q+".."+Q,by:d,at:"place:"+n})]),a.resolution===1&&N++}const K=T?q(n,O,h=>v(new TextDecoder().decode(h))):O;if(T&&a.resolution!==1&&I.push(u({scope:z(R),role:"writes",form:"alphabet",measure:"digest",value:K,by:d,at:"place:"+n})),P.set(a.scope,{digest:K,lines:g}),I.push(u({scope:a.scope,role:"writes",form:"alphabet",measure:"observed",value:n,by:d,at:"place:"+n}),...a.inputs.map(h=>u({scope:h,role:"writes",form:"alphabet",measure:"observed",value:v(_.get(h)),by:d,at:"witness:"+n})),...g),a.resolution===1){D++;const h=l(O);if(h===void 0)throw Error("REFUSE\xB7receipt missing verified carrier "+O);const M=ie(m,b,E).filter(x=>e(x,"scope")===R&&e(x,"measure")==="s"&&e(x,"at")==="place:"+n);I.push(...de(R,d,J,h,v,!!T,M))}});return C(),p(`RECEIPTS ${D} read \xB7 ${N} opened \xB7 reading closures`),{lines:I,read:D,opened:N,executed:H}}B(xe,"readingClosures");function Se(s,c,m,y,b=!1){const v=c.filter(t=>e(t,"scope").startsWith("receipts/readings/")&&e(t,"measure")==="bytes"&&e(t,"role")==="writes"),$=B((t,i)=>{const f=t.split(":")[1];if(!f||!/^[a-f0-9]+$/.test(f))return;const p=Y(i).about;if(p!==void 0)return m(p)===t?p:void 0;const S=te(s,"cas","carried",f);if(!re(S))return;const w=ee(S,"utf8");return m(w)===t?w:void 0},"load");for(const t of v){const i=e(t,"value"),f=e(t,"scope"),p=e(t,"by"),S=c.filter(r=>e(r,"scope")===f&&e(r,"measure")==="count"&&e(r,"by")===p&&e(r,"role")==="writes");if(S.length!==1||$(i,t)===void 0)return;const w=S[0],d=$(e(w,"at").replace(/^place:/,""),w);if(d===void 0)return;const E=$(i,t);if(E.trimStart().startsWith("[")){let r;try{r=JSON.parse(E)}catch{return}if(!Array.isArray(r)||r.length!==6||r[0]!=="reading-context@1")return;const A={instrument:r[1],implementation:r[2],policy:r[3],inputs:r[4],environment:r[5]};try{if(new TextDecoder().decode(le(A))!==E)return}catch{return}if(y){const l=typeof y=="function"?y(A):y;if(l===void 0||JSON.stringify([...l].sort((U,_)=>X(U[0],_[0])))!==JSON.stringify(r[5]))return}const C=c.filter(l=>e(l,"scope")===z(f)&&e(l,"measure")==="digest"&&e(l,"by")===p&&e(l,"role")==="writes"&&e(l,"at")==="place:"+i),L=q(i,e(w,"at").replace(/^place:/,""),l=>m(new TextDecoder().decode(l)));if(C.length!==1||e(C[0],"value")!==L)return}else if(b||!E.endsWith(`
5
+ `)||E.split(`
6
+ `).filter(Boolean).some(r=>se(r).kind!=="fact"))return;const j=d.split(`
7
+ `).filter(Boolean);if(e(w,"value")!==`${j.length}..${j.length}`||j.some(r=>e(r,"by")!==p||e(r,"at")!=="place:"+i))return}return v.length}B(Se,"verifiedReadingReceipts");export{$e as inputLines,de as portableReadingReceipt,xe as readingClosures,Se as verifiedReadingReceipts};
@@ -1,53 +1 @@
1
- import { AsyncLocalStorage } from 'node:async_hooks';
2
- import { createHash } from 'node:crypto';
3
- import { readFileSync, realpathSync } from 'node:fs';
4
- import { release } from 'node:os';
5
- import { readingIdentityBytes } from '@lapxo/topos/contract';
6
- const active = new AsyncLocalStorage();
7
- export const readingBoundary = active.getStore.bind(active);
8
- export function withReadingBoundary(identity, execution, run) {
9
- if (execution) {
10
- const algorithm = identity.split(':')[0];
11
- const hash = (text) => algorithm + ':' + createHash(algorithm).update(text).digest('hex');
12
- const expected = readingEnvironment(hash, execution.env, execution.cwd, execution.flags);
13
- const named = [...execution.context.environment].sort(([a], [b]) => Buffer.compare(Buffer.from(a), Buffer.from(b)));
14
- if (JSON.stringify([...expected].sort(([a], [b]) => Buffer.compare(Buffer.from(a), Buffer.from(b)))) !== JSON.stringify(named))
15
- throw Error('REFUSE·reading execution environment differs from its identity');
16
- }
17
- return active.run({ identity, execution }, run);
18
- }
19
- /** References commit the actual inherited boundary. Values are hashed, never
20
- * carried as environment secrets. No empty map is substituted for unknown input. */
21
- // The running runtime is resolved once for this act; mutable input bytes are not
22
- // stored in this slot. Later processes establish their own runtime reference.
23
- const runtimes = new Map();
24
- const runtimeOf = (algorithm) => { const held = runtimes.get(algorithm); if (held)
25
- return held; const digest = algorithm + ':' + createHash(algorithm).update(readFileSync(process.execPath)).digest('hex'); runtimes.set(algorithm, digest); return digest; };
26
- export function readingEnvironment(hash, env = process.env, cwd = process.cwd(), flags = process.execArgv) {
27
- const inherited = Object.entries(env).filter((entry) => entry[1] !== undefined);
28
- return [
29
- ['variables', hash(JSON.stringify(inherited.sort(([a], [b]) => Buffer.compare(Buffer.from(a), Buffer.from(b)))))],
30
- ['cwd', hash(realpathSync(cwd))], ['flags', hash(JSON.stringify(flags))],
31
- ['runtime', runtimeOf(hash('').split(':')[0])],
32
- ['platform', hash(JSON.stringify([process.platform, process.arch, process.versions, release()]))],
33
- ];
34
- }
35
- export function readingProfile(lines, field) {
36
- const values = (scope) => lines.filter(line => field(line, 'scope') === scope && field(line, 'role') === 'writes' && field(line, 'value') !== 'withdraw');
37
- const contexts = values('wire/reading-context'), receipts = values('wire/reading-receipt');
38
- if (!contexts.length && !receipts.length)
39
- return false;
40
- if (contexts.length !== 1 || receipts.length !== 1 || field(contexts[0], 'value') !== 'reading-context@1' || field(receipts[0], 'value') !== 'reading-receipt@1')
41
- throw Error('REFUSE·reading identity ambiguous or incomplete profiles');
42
- return true;
43
- }
44
- /** The caller supplies verified implementation and transitive references. This
45
- * constructor adds the process boundary that the host will actually hand over. */
46
- export function readingExecution(input, hash, boundary = { env: process.env, cwd: process.cwd(), flags: process.execArgv }) {
47
- const env = Object.fromEntries(Object.entries(boundary.env).filter((entry) => entry[1] !== undefined));
48
- const cwd = boundary.cwd, flags = Object.freeze([...boundary.flags]);
49
- Object.freeze(env);
50
- const context = { ...input, environment: readingEnvironment(hash, env, cwd, flags) };
51
- readingIdentityBytes(context);
52
- return { context, env, cwd, flags };
53
- }
1
+ var v=Object.defineProperty;var c=(t,e)=>v(t,"name",{value:e,configurable:!0});import{BoundRefusal as d}from"./refusals.js";import{sha256 as y}from"./hash.js";import{AsyncLocalStorage as g}from"node:async_hooks";import{createHash as l}from"node:crypto";import{readFileSync as x,realpathSync as S}from"node:fs";import{release as h}from"node:os";import{library2_readingIdentityBytes as B}from"../vendor/runtime.js";const a=new g,U=a.getStore.bind(a);function z(t,e,i){if(e){const r=t.split(":")[0],o=w(c(f=>r+":"+l(r).update(f).digest("hex"),"hash"),e.env,e.cwd,e.flags),s=[...e.context.environment].sort(([f],[p])=>Buffer.compare(Buffer.from(f),Buffer.from(p)));if(JSON.stringify([...o].sort(([f],[p])=>Buffer.compare(Buffer.from(f),Buffer.from(p))))!==JSON.stringify(s))throw Error("REFUSE\xB7reading execution environment differs from its identity")}return a.run({identity:t,execution:e},i)}c(z,"withReadingBoundary");const m=new Map,E=c(t=>{const e=m.get(t);if(e)return e;const i=t+":"+l(t).update(x(process.execPath)).digest("hex");return m.set(t,i),i},"runtimeOf");function w(t,e=process.env,i=process.cwd(),r=process.execArgv){const n=Object.entries(e).filter(o=>o[1]!==void 0);return[["variables",t(JSON.stringify(n.sort(([o],[s])=>Buffer.compare(Buffer.from(o),Buffer.from(s)))))],["cwd",t(S(i))],["flags",t(JSON.stringify(r))],["runtime",E(t("").split(":")[0])],["platform",t(JSON.stringify([process.platform,process.arch,process.versions,h()]))]]}c(w,"readingEnvironment");function A(t,e){const i=c(o=>t.filter(s=>e(s,"scope")===o&&e(s,"role")==="writes"&&e(s,"value")!=="withdraw"),"values"),r=i("wire/reading-context"),n=i("wire/reading-receipt");if(!r.length&&!n.length)return!1;if(r.length!==1||n.length!==1||e(r[0],"value")!=="reading-context@1"||e(n[0],"value")!=="reading-receipt@1")throw Error("REFUSE\xB7reading identity ambiguous or incomplete profiles");return!0}c(A,"readingProfile");function L(t,e,i={env:process.env,cwd:process.cwd(),flags:process.execArgv}){const r=Object.fromEntries(Object.entries(i.env).filter(f=>f[1]!==void 0)),n=i.cwd,o=Object.freeze([...i.flags]);Object.freeze(r);const s={...t,environment:w(e,r,n,o)};return B(s),{context:s,env:r,cwd:n,flags:o}}c(L,"readingExecution");const u=new g,M=c(()=>u.getStore()!==void 0,"preparingView");function P(t,e,i=!0){const r=u.getStore();if(!r)return e();const n=r.inputs.get(t);if(n)return n.value;const o=e(),s=JSON.stringify(o)??"null";if(r.inputs.size>=r.files||(r.used+=Buffer.byteLength(t)+Buffer.byteLength(s))>r.bytes)throw new d("reading-identity/budget","REFUSE\xB7reading-identity/budget view inputs");return r.inputs.set(t,{value:o,encoded:s,read:e,identity:i}),o}c(P,"viewInput");function V(t,e){const i={inputs:new Map,...t,used:0};return u.run(i,()=>{const r=e();for(const n of i.inputs.values())if((JSON.stringify(u.exit(n.read))??"null")!==n.encoded)throw new d("reading-identity/context","REFUSE\xB7reading-identity/context view inputs changed during preparation");return{value:r,inputs:[...i.inputs].filter(([,n])=>n.identity).map(([n,o])=>[n,y(o.encoded)]).sort(([n],[o])=>n<o?-1:n>o?1:0)}})}c(V,"captureViewInputs");export{V as captureViewInputs,M as preparingView,U as readingBoundary,w as readingEnvironment,L as readingExecution,A as readingProfile,P as viewInput,z as withReadingBoundary};
File without changes
@@ -0,0 +1,3 @@
1
+ var k=Object.defineProperty;var a=(t,e)=>k(t,"name",{value:e,configurable:!0});import{readFileSync as J}from"node:fs";import{sha256 as u}from"./hash.js";import{captureViewInputs as j,viewInput as y,readingEnvironment as b}from"./reading-context.js";import{withoutEffects as q}from"./read-only.js";import{committedInventoryFingerprint as R,committedLocalActs as F,withCommittedLocalActObservation as x}from"./ports/local-act.js";import{ingressBundles as A}from"./ports/ingress.js";import{instrumentCoordinates as B}from"../fold/digests.js";import{viewsOf as D}from"../fold/views.js";import{standingOf as K}from"../cli/place.js";import{evidenceLines as V}from"../render/view.js";import{resolve as O,join as H}from"node:path";import{library11_LOCK as M}from"../vendor/runtime.js";import{fieldOf as p,isWire as W}from"../fold/claims.js";import{storeOf as U}from"../land/ledger.js";import{underRootAuthority as _}from"../land/act.js";import{prepareObservedReadings as $}from"../fold/observed.js";import{authenticatedStanding as g}from"./admitted-place.js";import{withHostCall as I}from"./call-context.js";import{withContentStore as z}from"./content-store.js";import{BoundRefusal as n}from"./refusals.js";async function ge(t){try{if(!t||typeof t.place!="string"||!t.place||!t.instrument?.runtime)throw new n("host/context","REFUSE\xB7host/context");const e={...t.limits};for(const s of[e.bytes,e.files,e.readings,e.probes])if(!Number.isSafeInteger(s)||s<1)throw new n("host/budget","REFUSE\xB7host/budget");if(e.signal?.aborted)throw new n("host/cancelled","REFUSE\xB7host/cancelled");const i=O(t.place),r=U(i),o=structuredClone(t.instrument),d=t.reader;return await I({instrumentName:o.name,runtime:o.runtime,output:a(()=>{},"output")},()=>z(r,()=>_(r,"prepare reading identity",()=>{const s=w(g(i));for(const m of["bytes","files","readings","probes"])e[m]=Math.min(e[m],s[m]);return{kind:"fact",preparations:$(i,r,e,d)}}),()=>g(i)))}catch(e){return{kind:"refuse",code:e instanceof n?e.code:"reading-identity/failed",diagnostic:e instanceof Error?e.message:"REFUSE\xB7reading identity failed"}}}a(ge,"prepareNativeReadingIdentity");function w(t){const e=a(i=>{const r=t.filter(s=>p(s,"scope")==="reading-identity/"+i&&p(s,"role")==="writes"&&p(s,"value")!=="withdraw");if(r.length!==1)throw new n("reading-identity/budget","REFUSE\xB7reading identity requires one declared "+i+" limit");const o=/^0\.\.([1-9][0-9]*)$/.exec(p(r[0],"value")),d=Number(o?.[1]);if(!o||!Number.isSafeInteger(d))throw new n("reading-identity/budget","REFUSE\xB7invalid reading identity "+i+" limit");return d},"limit");return{bytes:e("bytes"),files:e("files"),readings:e("readings"),probes:e("probes")}}a(w,"declaredReadingIdentityLimits");function le(t){try{if(!t||!t.instrument?.runtime||typeof t.place!="string"||!t.place)throw new n("host/context","REFUSE\xB7host/context");if(t.view!=="lines"&&t.view!=="evidence")throw new n("reading-identity/selection","REFUSE\xB7reading-identity/selection supports lines and evidence");const e=t.view,i=O(t.place),r=U(i),o=t.instrument;return I({instrumentName:o.name,runtime:structuredClone(o.runtime),output:a(()=>{},"output")},()=>q(()=>{const d=R(F(r)),s=w(g(i)),l=new Date().toISOString().slice(0,10),m=b(u),f=j(s,()=>x(r,()=>{const C=w(y("authenticated-configuration:"+i,()=>g(i)));if(JSON.stringify(C)!==JSON.stringify(s))throw new n("reading-identity/context","REFUSE\xB7reading-identity/context identity budget changed");if(e==="evidence"&&y("foreign-ingress:"+r,()=>A(r)).length)throw new n("reading-identity/selection","REFUSE\xB7reading-identity/selection foreign view identity requires a transport snapshot");const v=K(i).standing;if(e==="evidence"){const c=D(v).get(e);if(!c||c.shape||c.regions.length!==1||c.regions[0]?.name!=="evidence")throw new n("reading-identity/selection","REFUSE\xB7reading-identity/selection requires the native evidence projection")}const E=e==="lines"?v.filter(W):V(i,r),S=[...B(r,o.runtime.entry,[],o.runtime.root,[],!0)].map(([c,L])=>[c,L]);if(!S.length)throw new n("reading-identity/failed","REFUSE\xB7reading-identity/failed is unavailable");return{text:E.length?E.join(`
2
+ `)+`
3
+ `:"",implementation:S,instrumentLock:u(y("instrument-lock:"+o.runtime.root,()=>J(H(o.runtime.root,M),"utf8")))}})),N=R(F(r));if(d!==N||l!==new Date().toISOString().slice(0,10)||JSON.stringify(m)!==JSON.stringify(b(u)))throw new n("reading-identity/context","REFUSE\xB7reading-identity/context committed inputs changed during preparation");const h=u(JSON.stringify(["native-view-inputs@1",i,e,d,f.inputs,f.value.implementation,f.value.instrumentLock,m,l]));if(t.expectedIdentity!==void 0&&t.expectedIdentity!==h)throw new n("reading-identity/context","REFUSE\xB7reading-identity/context view identity differs from the expected snapshot");return{kind:"fact",view:e,identity:h,text:f.value.text}}))}catch(e){return{kind:"refuse",code:e instanceof n?e.code:"reading-identity/failed",diagnostic:e instanceof Error?e.message:"REFUSE\xB7view identity failed"}}}a(le,"prepareNativeViewIdentity");export{w as declaredReadingIdentityLimits,ge as prepareNativeReadingIdentity,le as prepareNativeViewIdentity};
@@ -0,0 +1,6 @@
1
+ var ae=Object.defineProperty;var d=(t,r)=>ae(t,"name",{value:r,configurable:!0});import{mkdirSync as ce,readFileSync as T,existsSync as $}from"node:fs";import{join as W,dirname as de}from"node:path";import{library11_canonical as j,library11_parse as le,library11_PROTOCOL as ue,library11_byBytes as fe}from"../vendor/runtime.js";import{replaceWhole as pe,shardLines as he}from"../land/ledger.js";import{fieldOf as g}from"../fold/claims.js";import{library2_readingIdentityBytes as O,library2_readingReceiptIdentity as ge,library2_responseIdentity as ye,library2_snapshotAccess as me,library2_placeInputs as Ee,library2_withPlaceInputs as we}from"../vendor/runtime.js";import{withReadingBoundary as be}from"./reading-context.js";import{BoundRefusal as y}from"./refusals.js";class ee extends Error{static{d(this,"ReadingNeeds")}constructor(r){super("Reading inputs missing"),this.coordinates=r}}const te=d(t=>t.reduce((r,m)=>r+Buffer.byteLength(m.text,"utf8"),0),"filesBytes"),q=d(t=>{const r=le(t);if(r.kind!=="fact")throw Error("REFUSE\xB7input projection contains a non-wire line");return r.value.fields},"readingFields"),xe=d(t=>t.map(r=>j({scope:r.place,form:"alphabet",measure:"text",role:"writes",value:"lock",shape:r.place,about:r.text,by:"host",at:"policy:handed-input"})),"inputLines");function Se(t){const r=t.preparationLimits;if(r){for(const e of[r.bytes,r.files,r.readings,r.probes])if(!Number.isSafeInteger(e)||e<1)throw new y("host/budget","REFUSE\xB7host/budget");if(te(t.files)>r.bytes||t.files.length>r.files||r.probes<1)throw new y("host/budget","REFUSE\xB7host/budget")}const{root:m,store:b,speaker:S,digest:s,capsule:f,region:E,projection:h,files:w}=t;t.assertCurrent?.(),t.context&&O(t.context);let z=[];if(t.current){if(!t.context)throw Error("REFUSE\xB7current reading requires a declared identity");const{snapshot:e,kept:n,current:i,permission:o}=t.current;if(i.implementation!==t.context.implementation)throw Error("REFUSE\xB7current reading implementation differs from its verified context");const a=ye(e,i,s),u=me(e,n,i,o,s);if(!u.inspect||!u.reuse)throw Error("REFUSE\xB7current reading is not admitted for reuse");z=[["response",a],["permission",s(JSON.stringify([o.inspect,o.reuse,o.freshness]))]]}if(t.execution&&(!t.context||JSON.stringify(O(t.execution.context))!==JSON.stringify(O(t.context))))throw Error("REFUSE\xB7reading execution differs from declared context");const A=d(e=>{if(!f.selectedWorld)return;const{standing:n,offer:i}=f.selectedWorld;if(n.parts.some(a=>a.scope===`${i}/place-inputs/${e}`&&a.measure==="reads")){if(!t.context||!t.execution||!t.livePlace)throw Error("REFUSE\xB7place inputs require authenticated shadow and reading context "+e);return Ee(n,i,e,t.livePlace(),a=>s(new TextDecoder().decode(a)))}},"projectionFor"),k=A(h),D=A(E),M=d((e,n,i)=>i&&e?we(e,JSON.stringify(["place-inputs",f.selectedWorld.offer,n]),i):e,"commit"),G=d((e,n,i=t.context)=>be(e,t.execution&&i?{...t.execution,context:i}:t.execution,()=>f.ask(n,t.readerReference)),"ask"),N=M(t.context,h,k),re=N?s(new TextDecoder().decode(O(N))):"",ne=s("").split(":")[0],R=new Map(w.map(e=>[e.place,e.text]));if(R.size!==w.length)throw Error("REFUSE\xB7input projection has duplicate handed coordinates");const I=d(()=>{if(r?.signal?.aborted)throw new y("host/cancelled","REFUSE\xB7host/cancelled");for(const e of w){if(!$(W(m,e.place)))throw new ee([e.place]);if(!T(W(m,e.place)).equals(Buffer.from(e.text)))throw new y("reading-identity/integrity","REFUSE\xB7input changed "+e.place)}},"verify");if(I(),r?.signal?.aborted)throw new y("host/cancelled","REFUSE\xB7host/cancelled");const F=G(re,[{...k?{place:k}:{},protocol:ue,verb:"render",rootScope:"",region:h,at:1,reads:["**"],lines:xe(w),files:[]}],N)[0];if(F?.kind!=="fact"||!Array.isArray(F.lines))throw Error("REFUSE\xB7input projection "+(F?.why??"no lines"));if(r&&F.lines.length>r.readings)throw new y("host/budget","REFUSE\xB7host/budget");const v=new Map;for(const e of F.lines){const n=q(e),i=n.scope??"",o=/^receipt:(\d+)$/.exec(n.at??"");if(!i||v.has(i)||n.form!=="alphabet"||n.measure!=="reads"||n.role!=="reads"||!o)throw Error("REFUSE\xB7input projection ambiguous reading "+i);const a=(n.value??"").split("|").filter(Boolean),u=(n.needs??"").split("|").filter(Boolean);if(!a.length&&!u.length||new Set(a).size!==a.length||a.some(x=>!R.has(x))||new Set(u).size!==u.length)throw Error("REFUSE\xB7input projection has unhanded or duplicate dependencies "+i);const p=Number(o[1]);if(!Number.isSafeInteger(p))throw Error("REFUSE\xB7input projection invalid resolution "+i);v.set(i,{scope:i,inputs:a,needs:u,resolution:p,line:j({scope:i,form:n.form,measure:n.measure,role:n.role,value:a.join("|"),needs:u.join("|"),at:n.at})})}if(!v.size)throw Error("REFUSE\xB7input projection returned no readings");const H=[],J=new Set,K=new Set,Q=d(e=>{if(K.has(e))return;if(J.has(e))throw Error("REFUSE\xB7input projection dependency cycle "+e);const n=v.get(e);if(!n)throw Error("REFUSE\xB7input projection missing reading "+e);J.add(e);for(const i of n.needs)Q(i);J.delete(e),K.add(e),H.push(n)},"visit");for(const e of v.keys())Q(e);const B=s([f.selection??"",f.digest,E,h,...t.lifetime===void 0?[]:[JSON.stringify(t.lifetime)]].join(`
2
+ `)),_=S+":"+B.split(":")[1].slice(0,12),V="reading-closures/"+B.split(":")[1],P=he(b,S,V),X=d(e=>W(b,"cas","carried",e.split(":")[1]??""),"carried"),ie=d(e=>{const n=s(e),i=X(n);return ce(de(i),{recursive:!0}),(!$(i)||s(T(i,"utf8"))!==n)&&pe(i,e),n},"saved"),C=d((e,n=!1)=>{if(!e.startsWith(ne+":")||!/^[a-f0-9]+$/.test(e.split(":")[1]??""))return;const i=X(e);if(!$(i))return;const o=T(i,"utf8");if(s(o)!==e){if(n)throw new y("reading-identity/integrity","REFUSE\xB7reading carrier bytes differ");return}return o},"load"),se=d((e,n)=>{const i=[e.line,j({scope:"implementation",role:"writes",form:"alphabet",measure:"digest",value:B,by:"host",at:"policy:input-identity"}),...e.inputs.map(c=>j({scope:c,role:"writes",form:"alphabet",measure:"digest",value:s(R.get(c)),by:"host",at:"policy:input-identity"})),...e.needs.map(c=>j({scope:c,role:"writes",form:"alphabet",measure:"digest",value:n.get(c).digest,by:"host",at:"policy:input-identity"}))].sort(fe).join(`
3
+ `)+`
4
+ `,o=M(t.context,E,D),a=o&&{...o,policy:s(JSON.stringify([o.policy,t.allowsEmpty===!0,t.lifetime??null,t.readerReference??null,f.selection??null,f.lines])),inputs:[...[...o.inputs,...z].map(([c,U])=>[JSON.stringify(["context",c]),U]),[JSON.stringify(["plan"]),s(e.line)],...e.inputs.map(c=>[JSON.stringify(["file",c]),s(R.get(c))]),...e.needs.map(c=>[JSON.stringify(["receipt",c]),n.get(c).digest])]},u=a?new TextDecoder().decode(O(a)):i,p=s(u),x="receipts/readings/"+s(e.scope).split(":")[1]+"/"+p.split(":")[1];return{context:a,closure:u,input:p,scope:x}},"prepare"),oe=d((e,n=!1)=>{const{scope:i,input:o,closure:a}=e,p=P.filter(l=>g(l,"scope")===i&&g(l,"measure")==="bytes"&&g(l,"value")===o).at(-1)&&P.filter(l=>g(l,"scope")===i&&g(l,"measure")==="count"&&g(l,"by")===_).at(-1),x=p&&C(g(p,"at").replace(/^place:/,""),n),c=x?.split(`
5
+ `).filter(Boolean),U=c!==void 0&&g(p,"value")===`${c.length}..${c.length}`&&c.every(l=>{const Z=q(l);return Z.by===_&&Z.at==="place:"+o})?x:void 0;if(U===void 0||C(o,n)!==a)return;if(U===""&&!t.allowsEmpty)throw Error("REFUSE\xB7reading empty response is not admitted");const Y=U.split(`
6
+ `).filter(Boolean);for(const l of Y)q(l);const L=g(p,"at").replace(/^place:/,"");return{lines:Y,payload:L,digest:e.context?ge(o,L,l=>s(new TextDecoder().decode(l))):L}},"retained");return I(),{ordered:H,identity:B,by:_,journal:V,prior:P,prepare:se,retained:oe,verify:I,ask:G,load:C,saved:ie,handed:R,readingPlace:D,verifiedBytes:te(w)}}d(Se,"readingPreparation");function Ie(t){try{if(!t.context||!t.execution)throw new y("reading-identity/context","REFUSE\xB7reading preparation requires its actual execution context");const r=Se(t),m=new Map,b=[];let S=0;for(const s of r.ordered){t.assertCurrent?.(),r.verify();const f=s.needs.filter(w=>!m.has(w));if(f.length){b.push({scope:s.scope,kind:"needs",needs:f});continue}const E=r.prepare(s,m),h=r.retained(E,!0);h&&(m.set(s.scope,h),S++),b.push({scope:s.scope,kind:"ready",identity:E.input,context:E.context,...h?{receipt:h.digest}:{}})}return r.verify(),t.assertCurrent?.(),{kind:"fact",readings:b,probes:1,verifiedBytes:r.verifiedBytes,retained:S}}catch(r){return r instanceof ee?{kind:"needs",needs:r.coordinates}:{kind:"refuse",code:r instanceof y?r.code:"reading-identity/failed",diagnostic:r instanceof Error?r.message:"REFUSE\xB7reading preparation failed"}}}d(Ie,"prepareReadingIdentities");export{xe as inputLines,Ie as prepareReadingIdentities,q as readingFields,Se as readingPreparation};
@@ -1,40 +1 @@
1
- import { authorityOf, validateObjectContext } from '@lapxo/topos/wire';
2
- type ObjectContext = Parameters<typeof validateObjectContext>[1];
3
- type Signer = Parameters<typeof authorityOf>[1][number];
4
- export interface ReferenceTrust {
5
- readonly snapshot: string;
6
- readonly epoch: number;
7
- readonly proofScope: string;
8
- readonly policy: string;
9
- readonly formImplementation: string;
10
- readonly signers: readonly Signer[];
11
- readonly algorithms: readonly string[];
12
- readonly contracts?: {
13
- readonly refusals: string;
14
- readonly standing: string;
15
- };
16
- readonly objects: ObjectContext;
17
- readonly maxBytes: number;
18
- readonly maxRecords: number;
19
- readonly digestBytes: (bytes: Uint8Array) => string | Promise<string>;
20
- readonly verifyBytes: (bytes: string, key: string, signature: string, algorithms: readonly string[]) => boolean | Promise<boolean>;
21
- readonly fetchBytes: (source: string, blob: string) => Promise<Uint8Array>;
22
- }
23
- /** Prospective authenticated-standing@1 host composition; no effects and no authority from transport. */
24
- export declare function inspectAuthenticatedReference(fragment: string, trust: ReferenceTrust): Promise<{
25
- contracts?: {
26
- refusals: string;
27
- standing: string;
28
- } | undefined;
29
- reference: import("./reference-profile.ts").StandingReference;
30
- records: readonly import("@lapxo/topos/wire").ObjectRecord[];
31
- semanticIdentity: string;
32
- authorityContextIdentity: string;
33
- semanticStanding: string;
34
- originalRecords: readonly string[];
35
- }>;
36
- export { encodeReference, decodeReference } from './reference-profile.ts';
37
- export { BoundRefusal, readRefusalCatalog, describeRefusal } from './refusals.ts';
38
- export type { RefusalEntry } from './refusals.ts';
39
- export { readContent, retainContent, invokeSigningPort } from '../engine/ports.ts';
40
- export type { PortLimits, ContentReadPort, PersistencePort, DigestPort, SigningPort, SigningLot, SignatureRecord } from '../engine/ports.ts';
1
+ export {public4_BoundRefusal as BoundRefusal,public4_ContentReadPort as ContentReadPort,public4_DigestPort as DigestPort,public4_PersistencePort as PersistencePort,public4_PortLimits as PortLimits,public4_ReferenceTrust as ReferenceTrust,public4_RefusalEntry as RefusalEntry,public4_SignatureRecord as SignatureRecord,public4_SigningLot as SigningLot,public4_SigningPort as SigningPort,public4_decodeReference as decodeReference,public4_describeRefusal as describeRefusal,public4_encodeReference as encodeReference,public4_inspectAuthenticatedReference as inspectAuthenticatedReference,public4_invokeSigningPort as invokeSigningPort,public4_readContent as readContent,public4_readRefusalCatalog as readRefusalCatalog,public4_retainContent as retainContent} from "../public-types.js";