@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.
- package/CITATION.cff +19 -0
- package/TARGET.bound +95 -39
- package/dist/cli/accept.js +72 -558
- package/dist/cli/act-result.js +3 -103
- package/dist/cli/args.js +3 -44
- package/dist/cli/custodian.js +2 -29
- package/dist/cli/host.js +4 -32
- package/dist/cli/names.js +1 -12
- package/dist/cli/native-descendant.js +1 -19
- package/dist/cli/native.js +3 -60
- package/dist/cli/observe.js +1 -13
- package/dist/cli/owner.js +3 -139
- package/dist/cli/pass.js +21 -321
- package/dist/cli/place.js +6 -281
- package/dist/cli/release-result.js +3 -80
- package/dist/cli/retained-judgment.js +1 -25
- package/dist/cli/standing-result.js +4 -21
- package/dist/cli/takes.js +10 -111
- package/dist/cli/verb.d.ts +1 -2
- package/dist/cli/verb.js +83 -683
- package/dist/engine/computation.js +2 -0
- package/dist/engine/conformance.js +4 -0
- package/dist/engine/encoding.js +1 -2
- package/dist/engine/index.d.ts +1 -13
- package/dist/engine/index.js +2 -11
- package/dist/engine/object.js +1 -38
- package/dist/engine/ports.js +2 -103
- package/dist/fold/admission-history.js +1 -17
- package/dist/fold/bootstrap-anchor.js +1 -28
- package/dist/fold/ceilings.js +1 -142
- package/dist/fold/claims.js +2 -131
- package/dist/fold/closed.js +24 -234
- package/dist/fold/configures.js +1 -25
- package/dist/fold/digests.js +10 -226
- package/dist/fold/evidence.js +1 -22
- package/dist/fold/fold-worker.js +1 -13
- package/dist/fold/kept.js +12 -173
- package/dist/fold/keys.js +3 -91
- package/dist/fold/laid.js +3 -90
- package/dist/fold/nos.js +1 -48
- package/dist/fold/object.js +1 -2
- package/dist/fold/observed.js +27 -534
- package/dist/fold/opened.js +1 -33
- package/dist/fold/own.js +3 -217
- package/dist/fold/paid.js +1 -92
- package/dist/fold/place-inputs.js +1 -70
- package/dist/fold/places.js +3 -100
- package/dist/fold/rank.js +1 -9
- package/dist/fold/reach.js +1 -83
- package/dist/fold/readers.js +6 -142
- package/dist/fold/receipts.js +1 -47
- package/dist/fold/region-declarations.js +1 -13
- package/dist/fold/region.js +8 -286
- package/dist/fold/release-policy.js +1 -101
- package/dist/fold/resolved.js +6 -145
- package/dist/fold/roles.js +2 -59
- package/dist/fold/second.js +4 -71
- package/dist/fold/shards.js +12 -100
- package/dist/fold/signed.js +3 -81
- package/dist/fold/signers.js +1 -54
- package/dist/fold/stranger.js +6 -24
- package/dist/fold/views.js +1 -66
- package/dist/fold/wire.js +1 -46
- package/dist/fold/zoom.js +3 -81
- package/dist/host/act-cost.js +1 -25
- package/dist/host/adapters/keys/ed25519.js +1 -30
- package/dist/host/adapters/modules/javascript.js +1 -50
- package/dist/host/adapters/transport/http.js +1 -28
- package/dist/host/admitted-place.js +1 -63
- package/dist/host/archive.js +1 -152
- package/dist/host/call-context.js +1 -0
- package/dist/host/capsule-process.js +2 -61
- package/dist/host/capsule.js +9 -168
- package/dist/host/cell-receipts.js +12 -128
- package/dist/host/commit-result.js +1 -0
- package/dist/host/content-needed.js +1 -8
- package/dist/host/content-store.js +1 -31
- package/dist/host/contextual-place.js +2 -77
- package/dist/host/digest.js +2 -15
- package/dist/host/hash.js +1 -9
- package/dist/host/host-controls.js +1 -0
- package/dist/host/in-process-act.js +3 -0
- package/dist/host/in-process-context.js +3 -0
- package/dist/host/in-process-root.js +6 -0
- package/dist/host/in-process.js +4 -0
- package/dist/host/index.d.ts +1 -0
- package/dist/host/index.js +1 -0
- package/dist/host/io.js +1 -11
- package/dist/host/lifetime.js +1 -79
- package/dist/host/located.js +6 -105
- package/dist/host/native/bounded-file.js +1 -32
- package/dist/host/native/command.js +1 -91
- package/dist/host/native/control-bridge-worker.js +2 -88
- package/dist/host/native/control-bridge.js +1 -110
- package/dist/host/native/control-selection.js +1 -32
- package/dist/host/native/custody.js +1 -91
- package/dist/host/native/deadline.js +1 -28
- package/dist/host/native/descendants.js +1 -528
- package/dist/host/native/generated-custodian.js +5 -267
- package/dist/host/native/generated.js +1 -379
- package/dist/host/native/image.js +1 -45
- package/dist/host/native/jobs.js +2 -148
- package/dist/host/native/loader.js +1 -269
- package/dist/host/native/materialize.js +1 -175
- package/dist/host/native/module-closure.js +1 -130
- package/dist/host/native/module-delivery.d.ts +1 -62
- package/dist/host/native/module-delivery.js +1 -151
- package/dist/host/native/module-syntax.js +1 -69
- package/dist/host/native/native-binary.js +1 -115
- package/dist/host/native/native-program.js +1 -72
- package/dist/host/native/node-jobs.js +3 -187
- package/dist/host/native/node-launch.js +1 -159
- package/dist/host/native/preload.js +1 -45
- package/dist/host/native/reading.js +1 -249
- package/dist/host/native/receipt-environment.js +1 -41
- package/dist/host/native/references.js +1 -30
- package/dist/host/native/root.js +1 -37
- package/dist/host/native/route.js +1 -216
- package/dist/host/native/runtime.js +1 -9
- package/dist/host/native-reader-context.js +1 -8
- package/dist/host/native-receiver.js +1 -0
- package/dist/host/objects.js +1 -38
- package/dist/host/order.js +1 -2
- package/dist/host/place-act-transaction.js +4 -0
- package/dist/host/place-clock-selection.js +5 -124
- package/dist/host/ports/ingress.js +2 -57
- package/dist/host/ports/local-act.js +5 -172
- package/dist/host/ports/place-act.js +1 -169
- package/dist/host/ports/publication.js +1 -56
- package/dist/host/ports/signing.js +1 -74
- package/dist/host/ports/store.js +1 -18
- package/dist/host/ports/transport.js +1 -48
- package/dist/host/process-lifetime.js +1 -17
- package/dist/host/provide.js +1 -183
- package/dist/host/read-only.js +1 -9
- package/dist/host/reading-closures.js +7 -227
- package/dist/host/reading-context.js +1 -53
- package/dist/host/reading-identity-types.js +0 -0
- package/dist/host/reading-identity.js +3 -0
- package/dist/host/reading-preparation.js +6 -0
- package/dist/host/reference-authenticated.d.ts +1 -40
- package/dist/host/reference-authenticated.js +3 -100
- package/dist/host/reference-contracts.js +1 -6
- package/dist/host/reference-export.js +6 -81
- package/dist/host/reference-native-api.d.ts +1 -3
- package/dist/host/reference-native-api.js +1 -3
- package/dist/host/reference-native.js +1 -74
- package/dist/host/reference-profile.js +1 -63
- package/dist/host/reference-standing.js +2 -18
- package/dist/host/reference.js +1 -24
- package/dist/host/refusals.js +2 -43
- package/dist/host/release.js +4 -256
- package/dist/host/root-clock-source.js +1 -305
- package/dist/host/selected-capsules.js +1 -50
- package/dist/host/selected-topos.js +1 -80
- package/dist/host/signature-era.js +1 -0
- package/dist/host/signing.js +2 -48
- package/dist/host/source-content.js +2 -110
- package/dist/host/standing-carrier.js +1 -0
- package/dist/host/standing-projection.js +1 -0
- package/dist/host/timing.js +1 -7
- package/dist/host/walk.js +20 -193
- package/dist/judge/late.js +1 -33
- package/dist/judge/take.js +2 -75
- package/dist/judge/widening.js +1 -25
- package/dist/land/act.js +8 -302
- package/dist/land/alias.js +1 -41
- package/dist/land/held.js +1 -23
- package/dist/land/inert.js +1 -33
- package/dist/land/leaving.js +1 -55
- package/dist/land/ledger.js +7 -188
- package/dist/land/owned.js +4 -66
- package/dist/land/sign.js +1 -53
- package/dist/land/standing-pin.js +1 -49
- package/dist/land/vouched.js +1 -112
- package/dist/land/withdraw.js +1 -24
- package/dist/observe/files.js +1 -88
- package/dist/observe/identity.js +1 -61
- package/dist/observe/match.js +1 -8
- package/dist/observe/regions.js +7 -306
- package/dist/observe/run.js +2 -40
- package/dist/observe/runner.js +4 -93
- package/dist/public-types.d.ts +1114 -0
- package/dist/render/capsule.js +1 -30
- package/dist/render/field.js +1 -40
- package/dist/render/names.js +1 -4
- package/dist/render/open.js +1 -61
- package/dist/render/page.js +1 -7
- package/dist/render/receipts.js +1 -47
- package/dist/render/shape.js +1 -74
- package/dist/render/target.js +4 -52
- package/dist/render/view.js +7 -197
- package/dist/vendor/50086958553b9376d600583f7dff354196bfeb41170fc6d1482ca7bea7c493e2.LICENSE +21 -0
- package/dist/vendor/b3e938d28f88a1851af303a40c749e12ebd5a686daac4f0b343b5cdd2e040419.LICENSE +21 -0
- package/dist/vendor/bundle.json +1 -0
- package/dist/vendor/library11.js +1 -0
- package/dist/vendor/object-provider.js +42 -0
- package/dist/vendor/runtime.js +38 -0
- package/dist/vendor/sources.json +1 -0
- package/dist/wasm/adapter.d.ts +1 -51
- package/dist/wasm/adapter.js +1 -180
- package/dist/wasm/node-worker.js +1 -13
- package/dist/wasm/object.js +1 -76
- package/dist/wasm/worker.js +1 -7
- package/docs/contracts/closure-delivery.md +1 -1
- package/docs/contracts/closure-delivery.publication.json +1 -1
- package/docs/contracts/conformance.json +142 -0
- package/docs/contracts/determinism.bound +9 -0
- package/docs/contracts/engine-object-projection.publication.json +1 -1
- package/docs/contracts/engine.md +21 -1
- package/docs/contracts/native-host.md +21 -0
- package/docs/contracts/native-host.publication.json +25 -0
- package/docs/contracts/native-publication.inventory.json +3 -1
- package/docs/contracts/optional-wasm-adapter.publication.json +1 -1
- package/docs/contracts/publication.inventory.json +29 -0
- package/docs/contracts/reading-identity.md +37 -0
- package/docs/contracts/reading-identity.publication.json +25 -0
- package/docs/contracts/refusals.bound +51 -0
- package/docs/contracts/refusals.md +18 -3
- package/docs/contracts/refusals.publication.json +2 -2
- package/docs/contracts/views.md +8 -0
- package/docs/guide.md +10 -0
- package/docs/reference.md +40 -0
- package/docs/why.md +109 -0
- package/package.json +37 -18
- package/receipts.bound +11675 -9725
- package/samples/native-host/no.json +10 -0
- package/samples/native-host/yes.json +20 -0
- package/samples/reading-identity/no.json +20 -0
- package/samples/reading-identity/yes.json +46 -0
- package/vectors/native/native-host.vector.json +62 -0
- package/vectors/native/reading-identity.vector.json +101 -0
- package/vectors/native/refusals.vector.json +104 -0
- package/vendor/syntax/LICENSE.md +7 -0
- package/vendor/syntax/parser.js +1 -0
- package/dist/engine/object.d.ts +0 -17
- package/dist/engine/ports.d.ts +0 -32
- package/dist/host/native/module-closure.d.ts +0 -35
- package/dist/host/reference-export.d.ts +0 -33
- package/dist/host/reference-native.d.ts +0 -30
- package/dist/host/reference-profile.d.ts +0 -23
- package/dist/host/refusals.d.ts +0 -14
|
@@ -1,77 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import { declaredRootClockSource, hasRootClockSource } from "./root-clock-source.js";
|
|
4
|
-
import { commitPlaceAct, placeActResult, committedPlaceActResults } from "./ports/place-act.js";
|
|
5
|
-
import { placesIn } from "../fold/places.js";
|
|
6
|
-
import { appliedHistoryIn } from "../fold/signed.js";
|
|
7
|
-
import { storeOf } from "../land/ledger.js";
|
|
8
|
-
import { publicStandingLines } from "./admitted-place.js";
|
|
9
|
-
import { foldClaims, fieldOf } from "../fold/claims.js";
|
|
10
|
-
const fail = (s) => { throw Error('REFUSE·contextual place ' + s); };
|
|
11
|
-
function read(path, limit) {
|
|
12
|
-
const fd = openSync(path, 'r');
|
|
13
|
-
try {
|
|
14
|
-
const stat = fstatSync(fd);
|
|
15
|
-
if (!stat.isFile() || stat.size > limit)
|
|
16
|
-
fail('batch byte budget');
|
|
17
|
-
const data = Buffer.alloc(stat.size);
|
|
18
|
-
let n = 0;
|
|
19
|
-
while (n < data.length) {
|
|
20
|
-
const got = readSync(fd, data, n, data.length - n, null);
|
|
21
|
-
if (!got)
|
|
22
|
-
fail('batch changed during read');
|
|
23
|
-
n += got;
|
|
24
|
-
}
|
|
25
|
-
if (readSync(fd, Buffer.alloc(1), 0, 1, null))
|
|
26
|
-
fail('batch changed during read');
|
|
27
|
-
return new TextDecoder('utf8', { fatal: true }).decode(data);
|
|
28
|
-
}
|
|
29
|
-
finally {
|
|
30
|
-
closeSync(fd);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
export function hasContextualPlace(root) { return hasRootClockSource(root); }
|
|
34
|
-
/** Exact selected SDK frame plus complete pre-signed receiver statements. No
|
|
35
|
-
* executable/verifier/epoch selection can be supplied by this envelope. */
|
|
36
|
-
export async function landContextualPlace(root, file) {
|
|
37
|
-
const selected = declaredRootClockSource(root), raw = read(file, selected.selection.budget.bytes);
|
|
38
|
-
let packet;
|
|
39
|
-
try {
|
|
40
|
-
packet = JSON.parse(raw);
|
|
41
|
-
}
|
|
42
|
-
catch {
|
|
43
|
-
return fail('invalid batch JSON');
|
|
44
|
-
}
|
|
45
|
-
if (!packet || Object.keys(packet).sort().join(',') !== 'context,profile,receipts' || packet.profile !== PLACE_ACT_CONTEXT || typeof packet.context !== 'string' || !Array.isArray(packet.receipts) || JSON.stringify(packet) + '\n' !== raw)
|
|
46
|
-
fail('unsupported/noncanonical batch envelope');
|
|
47
|
-
return commitPlaceAct(storeOf(root), packet.context, packet.receipts, selected.trust, selected.selection.storageBudget);
|
|
48
|
-
}
|
|
49
|
-
export function contextualAct(root, identity) {
|
|
50
|
-
const selected = declaredRootClockSource(root), bundle = placeActResult(storeOf(root), identity, selected.trust, selected.selection.storageBudget);
|
|
51
|
-
if (!bundle)
|
|
52
|
-
return undefined;
|
|
53
|
-
const all = new Map(committedPlaceActResults(storeOf(root), selected.trust, selected.selection.storageBudget).map(a => [a.identity, a])), kept = new Set(), contexts = [];
|
|
54
|
-
const visit = (id) => { if (kept.has(id))
|
|
55
|
-
return; const a = all.get(id); if (!a)
|
|
56
|
-
return; kept.add(id); const decoded = readPlaceActContext(a.bundle.context, selected.selection.budget); for (const p of decoded.places)
|
|
57
|
-
visit(p.previous); contexts.push({ identity: a.identity, context: a.bundle.context, receipts: a.bundle.receipts, authority: selected.authority(a.bundle.context) }); };
|
|
58
|
-
visit(identity);
|
|
59
|
-
return { profile: PLACE_ACT_CONTEXT, identity, context: bundle.context, receipts: bundle.receipts, contexts };
|
|
60
|
-
}
|
|
61
|
-
/** Carriers retain exact originals and authenticated context/receipts. Each
|
|
62
|
-
* namespace folds independently; labels assert no statistical independence. */
|
|
63
|
-
export function contextualStanding(root) {
|
|
64
|
-
const selected = declaredRootClockSource(root), acts = committedPlaceActResults(storeOf(root), selected.trust, selected.selection.storageBudget);
|
|
65
|
-
const groups = new Map();
|
|
66
|
-
for (const act of acts) {
|
|
67
|
-
const decoded = readPlaceActContext(act.bundle.context, selected.selection.budget);
|
|
68
|
-
for (const p of decoded.places) {
|
|
69
|
-
const key = JSON.stringify([decoded.root.namespace, p.place]), group = groups.get(key) ?? { namespace: decoded.root.namespace, place: p.place, lines: [], contexts: [] };
|
|
70
|
-
group.lines.push(...p.records);
|
|
71
|
-
group.contexts.push({ identity: act.identity, context: act.bundle.context, receipts: act.bundle.receipts });
|
|
72
|
-
groups.set(key, group);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
const legacyPlaces = placesIn(root).map(place => { const history = appliedHistoryIn(root, place), folded = foldClaims(history); return { namespace: 'legacy-global', place: [place, 'TARGET.bound'].join('/'), standing: folded.standing.filter(line => fieldOf(line, 'value') !== 'withdraw'), history }; });
|
|
76
|
-
return { profile: PLACE_ACT_CONTEXT, root: publicStandingLines(root), legacyPlaces, contexts: acts.map(a => ({ identity: a.identity, context: a.bundle.context, receipts: a.bundle.receipts, authority: selected.authority(a.bundle.context) })), places: [...groups.values()].map(group => { const folded = foldClaims(group.lines); return { namespace: group.namespace, place: group.place, standing: folded.standing.filter(line => fieldOf(line, 'value') !== 'withdraw'), retracted: folded.retracted, superseded: folded.superseded, forks: folded.forks, contexts: group.contexts }; }) };
|
|
77
|
-
}
|
|
1
|
+
var S=Object.defineProperty;var r=(t,c)=>S(t,"name",{value:c,configurable:!0});import{openSync as A,fstatSync as C,readSync as x,closeSync as E}from"node:fs";import{library3_readPlaceActContext as y,library3_PLACE_ACT_CONTEXT as m}from"../vendor/runtime.js";import{declaredRootClockSource as d,hasRootClockSource as P}from"./root-clock-source.js";import{commitPlaceAct as T,placeActResult as _,committedPlaceActResults as g}from"./ports/place-act.js";import{placesIn as N}from"../fold/places.js";import{appliedHistoryIn as O}from"../fold/signed.js";import{storeOf as p}from"../land/ledger.js";import{publicStandingLines as R}from"./admitted-place.js";import{projectContextualStanding as w}from"./standing-carrier.js";import{admissionHistoryAt as B}from"../fold/admission-history.js";const u=r(t=>{throw Error("REFUSE\xB7contextual place "+t)},"fail");function k(t,c){const n=A(t,"r");try{const e=C(n);(!e.isFile()||e.size>c)&&u("batch byte budget");const o=Buffer.alloc(e.size);let i=0;for(;i<o.length;){const l=x(n,o,i,o.length-i,null);l||u("batch changed during read"),i+=l}return x(n,Buffer.alloc(1),0,1,null)&&u("batch changed during read"),new TextDecoder("utf8",{fatal:!0}).decode(o)}finally{E(n)}}r(k,"read");function U(t){return P(t)}r(U,"hasContextualPlace");async function q(t,c){const n=d(t),e=k(c,n.selection.budget.bytes);let o;try{o=JSON.parse(e)}catch{return u("invalid batch JSON")}return(!o||Object.keys(o).sort().join(",")!=="context,profile,receipts"||o.profile!==m||typeof o.context!="string"||!Array.isArray(o.receipts)||JSON.stringify(o)+`
|
|
2
|
+
`!==e)&&u("unsupported/noncanonical batch envelope"),T(p(t),o.context,o.receipts,n.trust,n.selection.storageBudget)}r(q,"landContextualPlace");function K(t,c){const n=d(t),e=_(p(t),c,n.trust,n.selection.storageBudget);if(!e)return;const o=new Map(g(p(t),n.trust,n.selection.storageBudget).map(s=>[s.identity,s])),i=new Set,l=[],f=r(s=>{if(i.has(s))return;const a=o.get(s);if(!a)return;i.add(s);const b=y(a.bundle.context,n.selection.budget);for(const h of b.places)f(h.previous);l.push({identity:a.identity,context:a.bundle.context,receipts:a.bundle.receipts,authority:n.authority(a.bundle.context)})},"visit");return f(c),{profile:m,identity:c,context:e.context,receipts:e.receipts,contexts:l}}r(K,"contextualAct");function j(t){const c=d(t),n=g(p(t),c.trust,c.selection.storageBudget);return{rootHistory:B(t,Number.MAX_SAFE_INTEGER),legacyPlaces:N(t).map(e=>({place:[e,"TARGET.bound"].join("/"),history:O(t,e)})),contexts:n.map(e=>({identity:e.identity,context:e.bundle.context,receipts:e.bundle.receipts,authority:c.authority(e.bundle.context)}))}}r(j,"contextualStandingSnapshot");function Q(t){const c=j(t),n=d(t);return w(R(t),c.legacyPlaces,c.contexts,c.contexts.map(e=>({identity:e.identity,context:y(e.context,n.selection.budget)})))}r(Q,"contextualStanding");export{K as contextualAct,Q as contextualStanding,j as contextualStandingSnapshot,U as hasContextualPlace,q as landContextualPlace};
|
package/dist/host/digest.js
CHANGED
|
@@ -1,15 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import { selfName } from "../fold/claims.js";
|
|
4
|
-
/** Sorted by UTF-8 bytes; the algorithm is a field (`sha256:…`), never bare hex. */
|
|
5
|
-
export function fullDigest(input, algorithm) {
|
|
6
|
-
if (!algorithm)
|
|
7
|
-
throw new Error(`${selfName()}: REFUSE·runtime a digest was asked for before the lock said which algorithm`);
|
|
8
|
-
const text = typeof input === 'string' ? input : [...input].sort(byBytes).join('\n');
|
|
9
|
-
return `${algorithm}:${createHash(algorithm).update(text).digest('hex')}`;
|
|
10
|
-
}
|
|
11
|
-
export function bytesDigest(bytes, algorithm) {
|
|
12
|
-
if (!algorithm)
|
|
13
|
-
throw new Error(`${selfName()}: REFUSE·runtime a digest was asked for before the lock said which algorithm`);
|
|
14
|
-
return `${algorithm}:${createHash(algorithm).update(bytes).digest('hex')}`;
|
|
15
|
-
}
|
|
1
|
+
var f=Object.defineProperty;var t=(r,e)=>f(r,"name",{value:e,configurable:!0});import{createHash as o}from"node:crypto";import{library11_byBytes as a}from"../vendor/runtime.js";import{selfName as s}from"../fold/claims.js";function w(r,e){if(!e)throw new Error(`${s()}: REFUSE\xB7runtime a digest was asked for before the lock said which algorithm`);const i=typeof r=="string"?r:[...r].sort(a).join(`
|
|
2
|
+
`);return`${e}:${o(e).update(i).digest("hex")}`}t(w,"fullDigest");function m(r,e){if(!e)throw new Error(`${s()}: REFUSE\xB7runtime a digest was asked for before the lock said which algorithm`);return`${e}:${o(e).update(r).digest("hex")}`}t(m,"bytesDigest");export{m as bytesDigest,w as fullDigest};
|
package/dist/host/hash.js
CHANGED
|
@@ -1,9 +1 @@
|
|
|
1
|
-
|
|
2
|
-
/** SHA-256 byte hashing for host formats that explicitly name this algorithm. */
|
|
3
|
-
export const sha = (bytes) => createHash('sha256').update(bytes).digest('hex');
|
|
4
|
-
/** Typed digest spelling shared by fixed host boundaries; hashes identical bytes. */
|
|
5
|
-
export const sha256 = (bytes) => 'sha256:' + sha(bytes);
|
|
6
|
-
/** Length-delimited UTF-8 fields for existing host history identities. */
|
|
7
|
-
export function hashText(hash, value) { hash.update(String(Buffer.byteLength(value, 'utf8')) + ':'); hash.update(value, 'utf8'); }
|
|
8
|
-
/** Exact typed SHA-256 spelling used by fixed host declarations. */
|
|
9
|
-
export const isSha256 = (value) => typeof value === 'string' && /^sha256:[0-9a-f]{64}$/.test(value);
|
|
1
|
+
var o=Object.defineProperty;var e=(t,s)=>o(t,"name",{value:s,configurable:!0});import{createHash as a}from"node:crypto";const r=e(t=>a("sha256").update(t).digest("hex"),"sha"),f=e(t=>"sha256:"+r(t),"sha256");function n(t,s){t.update(String(Buffer.byteLength(s,"utf8"))+":"),t.update(s,"utf8")}e(n,"hashText");const i=e(t=>typeof t=="string"&&/^sha256:[0-9a-f]{64}$/.test(t),"isSha256");export{n as hashText,i as isSha256,r as sha,f as sha256};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var s=Object.defineProperty;var o=(e,t)=>s(e,"name",{value:t,configurable:!0});import{library11_LOCK as r}from"../vendor/runtime.js";import{BoundRefusal as n}from"./refusals.js";function i(e){throw new n("host/"+e,"REFUSE\xB7host/"+e)}o(i,"refuseHost");function u(e){e?.aborted&&i("cancelled")}o(u,"assertHostNotCancelled");function m(e,t){return(!/^(0|[1-9][0-9]*)$/.test(e)||!Number.isSafeInteger(Number(e)))&&t("unknown receiver clock"),Number(e)}o(m,"receiverClock");const p=o(e=>typeof e=="string"&&e.endsWith("/"+r)&&!e.startsWith("/")&&!e.split("/").some(t=>!t||t==="."||t===".."),"isPlaceLockCoordinate"),a=o(e=>e==="."?"":e.slice(0,-(r.length+1)),"placeRegionOf");export{u as assertHostNotCancelled,p as isPlaceLockCoordinate,a as placeRegionOf,m as receiverClock,i as refuseHost};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
var _=Object.defineProperty;var o=(i,t)=>_(i,"name",{value:t,configurable:!0});import{library11_authorityAtEpoch as M}from"../vendor/runtime.js";import{library3_placeReceiptBytes as q,library3_readPlaceActContext as F}from"../vendor/runtime.js";import{library2_readingIdentity as E,library2_readingReceiptIdentity as P}from"../vendor/runtime.js";import{readContent as H,invokeFrameSigningPort as J}from"../engine/ports.js";import{transactPlaceAct as O,PlaceActCommitUnknown as U}from"./place-act-transaction.js";import{withActHost as I}from"../land/act.js";import{sha256 as a,isSha256 as z}from"./hash.js";import{BoundRefusal as v}from"./refusals.js";import{refuseHost as r}from"./host-controls.js";import{withHostInstrument as w}from"./call-context.js";import{requireEffects as Z}from"./read-only.js";async function et(i,t){return w(t.instrumentName,()=>I({name:t.instrumentName,report:o(()=>{},"report"),signal:i.signal},async()=>{try{Z("contextual host admission");const{place:e,source:c,identity:s,rootSnapshot:m,algorithm:g,signal:h}=i,N=structuredClone(i.reading),d={...i.contentLimits},y={...i.signingLimits},f={...i.storageLimits};(typeof t.instrumentName!="string"||!t.instrumentName||!/[a-zA-Z0-9]/.test(t.instrumentName)||!/^[a-zA-Z0-9._-]+$/.test(t.instrumentName)||typeof e!="string"||!e||typeof c!="string"||!c||typeof g!="string"||!g)&&r("context"),(f.acts>t.limits.storage.acts||f.bytes>t.limits.storage.bytes||y.timeoutMs>t.limits.signing.timeoutMs||y.maxBytes>t.limits.signing.maxBytes||d.timeoutMs>t.limits.content.timeoutMs||d.maxBytes>t.limits.content.maxBytes)&&r("budget");const S=E({...N,inputs:[...N.inputs,["host/place",a(e)],["host/snapshot",m],["host/act",s],["host/operation",a(JSON.stringify([g,d,y,f]))]]},a),n=t.trust();n.contract.root.snapshot!==m&&r("stale"),d.maxBytes>n.contract.budget.bytes&&r("budget");const L=await H(c,s,{read:t.read,digestBytes:a},d,h);let p;try{p=new TextDecoder("utf-8",{fatal:!0}).decode(L)}catch{return r("snapshot-format")}const b=F(p,n.contract.budget);n.contract.digest(p)!==s&&r("integrity");const A=await O(p,o(async()=>{const u=n.contract.receiptSigner,B=n.contract.signers.find(l=>l.id===u);(!B||M({scope:n.contract.receiptScope,by:u},B,Number(n.contract.root.epoch),n.contract.receiptScope,"authority").kind!=="admitted")&&r("receiver-authority");const R=await J({keyId:u,algorithm:g,bytes:b.places.map(l=>q(s,l,b.root,u,n.contract.receiptScope,n.contract.budget))},t.sign,y,h);return b.places.map((l,C)=>({place:l.place,by:u,signature:R[C].signature}))},"acquire"),n,f,t.persistence,h),k=a(JSON.stringify(A)+`
|
|
2
|
+
`);return{kind:"fact",value:{place:e,act:A,reading:S,result:k,commitment:P(S,k,a)}}}catch(e){return e instanceof U?{kind:"uncertain",identity:e.identity,code:e.code,diagnostic:e.message}:{kind:"refuse",code:e instanceof v?e.code:"host/failed",diagnostic:e instanceof Error?e.message:"REFUSE\xB7host/failed"}}}))}o(et,"landPlaceActInProcess");function it(i,t){return w(t.instrumentName,()=>I({name:t.instrumentName,report:o(()=>{},"report"),signal:i.signal},()=>{try{i.signal?.aborted&&r("cancelled"),(!i.place||!z(i.identity))&&r("context");const e={...i.storageLimits};(e.acts>t.limits.storage.acts||e.bytes>t.limits.storage.bytes)&&r("budget");const c=E({...structuredClone(i.reading),inputs:[...i.reading.inputs,["host/place",a(i.place)],["host/act",i.identity],["host/operation",a("historical-recovery")]]},a),s=t.persistence.result(i.identity,t.trust(),e);s||r("act-unavailable");const m=a(JSON.stringify(s)+`
|
|
3
|
+
`);return{kind:"fact",value:{place:i.place,identity:i.identity,act:s,historical:!0,reading:c,result:m,commitment:P(c,m,a)}}}catch(e){return{kind:"refuse",code:e instanceof v?e.code:"host/failed",diagnostic:e instanceof Error?e.message:"REFUSE\xB7host/failed"}}}))}o(it,"recoverPlaceActInProcess");export{et as landPlaceActInProcess,it as recoverPlaceActInProcess};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
var O=Object.defineProperty;var h=(r,a)=>O(r,"name",{value:a,configurable:!0});import{library11_parse as x}from"../vendor/runtime.js";import{library2_readingIdentity as A,library2_readingReceiptIdentity as C}from"../vendor/runtime.js";import{readContent as N}from"../engine/ports.js";import{sha256 as y}from"./hash.js";import{BoundRefusal as P}from"./refusals.js";import{refuseHost as e,isPlaceLockCoordinate as v,placeRegionOf as H}from"./host-controls.js";import{publicStandingProjection as w,assertStandingView as k}from"./standing-projection.js";import{rootClockSelectionOf as J,inspectPortablePlaceContexts as I}from"./root-clock-source.js";import{projectContextualStanding as R}from"./standing-carrier.js";import{authorityFor as j}from"../fold/signers.js";import{ownRecordAdmitted as E}from"../fold/signed.js";import{wordsOf as _}from"../fold/wire.js";import{fieldOf as S,isConfig as B}from"../fold/claims.js";import{signatureEraOf as F}from"./signature-era.js";function L(r,a,o){(!r||Object.keys(r).sort().join(",")!=="contexts,legacyPlaces,rootHistory"||!Array.isArray(r.rootHistory)||!Array.isArray(r.legacyPlaces)||!Array.isArray(r.contexts))&&e("snapshot-format");let i=r.rootHistory.length;i>o&&e("budget");const m=h(t=>typeof t=="string"&&x(t).kind==="fact","validLine");(!r.rootHistory.length||r.rootHistory.some(t=>!m(t)))&&e("snapshot-format");const s=w(r.rootHistory,a),f=_(s,"families");f.length&&!f.includes("view")&&e("vocabulary-unavailable"),k(s);const l=J(s,a),n=F(s).admitted;(r.legacyPlaces.length>l.resources.places||r.contexts.length>l.resources.acts)&&e("budget");const g=j(r.rootHistory,a,n).admitted;g.some(t=>!t.coverage.includes("*"))&&!f.includes("region")&&e("vocabulary-unavailable");const p=new Set;for(const t of r.legacyPlaces){(!t||!v(t.place)||p.has(t.place)||!Array.isArray(t.history))&&e("snapshot-format"),p.add(t.place),i+=t.history.length,i>o&&e("budget");const d=H(t.place);t.history.some(c=>!m(c)||!E(c,d,"region",g,n))&&e("legacy-authority")}for(const t of r.contexts){(!t||!t.authority||!Array.isArray(t.authority.history))&&e("snapshot-format"),i+=t.authority.history.length,i>o&&e("budget");const d=S(t.authority.checkpoint,"epoch"),c=r.rootHistory.filter(b=>!B(b)||Number(S(b,"epoch"))<=Number(d));JSON.stringify(c)!==JSON.stringify(t.authority.history)&&e("historical-snapshot")}const u=I(JSON.stringify(r.contexts),a,l);return R(s,r.legacyPlaces,r.contexts,u)}h(L,"authenticatedCarrier");async function tt(r,a){try{const{place:o,source:i,snapshot:m,signal:s}=r,f=structuredClone(r.anchor),l=structuredClone(r.reading),n={...r.limits};(!o||typeof o!="string"||!i||typeof i!="string"||!Number.isSafeInteger(n.records)||n.records<1)&&e("context");const g=A({...l,inputs:[...l.inputs,["host/place",y(o)],["host/anchor",y(JSON.stringify(f))],["host/snapshot",m]]},y),p=await N(i,m,{read:a.read,digestBytes:y},n,s);let u,t;try{u=new TextDecoder("utf-8",{fatal:!0}).decode(p),t=JSON.parse(u)}catch{return e("snapshot-format")}JSON.stringify(t)+`
|
|
2
|
+
`!==u&&e("snapshot-format"),s?.aborted&&e("cancelled");const d=L(t,f,n.records),c=y(JSON.stringify(d)+`
|
|
3
|
+
`);return{kind:"fact",value:{place:o,standing:d,reading:g,result:c,commitment:C(g,c,y)}}}catch(o){return{kind:"refuse",code:o instanceof P?o.code:"host/failed",diagnostic:o instanceof Error?o.message:"REFUSE\xB7host/failed"}}}h(tt,"readContextualStandingInProcess");export{tt as readContextualStandingInProcess};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
var H=Object.defineProperty;var d=(n,e)=>H(n,"name",{value:e,configurable:!0});import{library11_canonical as T,library11_parse as F}from"../vendor/runtime.js";import{library2_readingIdentity as J,library2_readingReceiptIdentity as L}from"../vendor/runtime.js";import{readContent as M}from"../engine/ports.js";import{acceptRootRecords as O}from"../cli/accept.js";import{verifiedLegacyActResult as I}from"../cli/act-result.js";import{admissionHistoryAt as U,admissionAnchor as j}from"../fold/admission-history.js";import{isConfig as P}from"../fold/claims.js";import{sha256 as s,isSha256 as R}from"./hash.js";import{BoundRefusal as A}from"./refusals.js";import{refuseHost as r}from"./host-controls.js";import{ActCommitUnknown as q}from"./commit-result.js";import{requireEffects as z}from"./read-only.js";import{withHostCall as S}from"./call-context.js";import{withActHost as D}from"../land/act.js";const w=d(n=>s(U(n,Number.MAX_SAFE_INTEGER).join(`
|
|
2
|
+
`)+`
|
|
3
|
+
`),"rootLotSnapshot");async function se(n,e){const i=[];let f=0,o;const m=structuredClone(e.runtime),a={...n.limits};return S({instrumentName:e.instrumentName,runtime:m,output:d((t,l)=>{f+=new TextEncoder().encode(l).length,f>e.limits.diagnostics&&r("budget"),i.push({stream:t,text:l})},"output")},()=>D({name:e.instrumentName,report:d(t=>{f+=new TextEncoder().encode(t).length,f>e.limits.diagnostics&&r("budget"),i.push({stream:"error",text:t})},"report"),signal:n.signal},async()=>{try{z("Root lot admission"),(!n.place||!e.root||!e.instrumentName||!m.root||!m.entry||!m.directory||![".ts",".js"].includes(m.extension)||!Array.isArray(m.lock)||!m.lock.length)&&r("context"),(a.records>e.limits.records||a.maxBytes>e.limits.maxBytes||a.timeoutMs>e.limits.timeoutMs||!Number.isSafeInteger(a.records)||a.records<1||!Number.isSafeInteger(e.limits.diagnostics)||e.limits.diagnostics<1)&&r("budget");const{place:t,snapshot:l,source:C,digest:p,signal:y}=n,b=structuredClone(n.reading);(!R(l)||w(e.root)!==l)&&r("stale");const _=j(e.root),k=J({...b,inputs:[...b.inputs,["host/place",s(t)],["host/snapshot",l],["host/anchor",s(JSON.stringify(_))],["host/draft",p],["host/principal",s(e.signer.keyId)],["host/operation",s(JSON.stringify(["root-lot",a]))]]},s),x=await M(C,p,{read:e.read,digestBytes:s},a,y);let h;try{h=new TextDecoder("utf-8",{fatal:!0}).decode(x)}catch{return r("snapshot-format")}const g=h.endsWith(`
|
|
4
|
+
`)?h.slice(0,-1).split(`
|
|
5
|
+
`):[];(!g.length||g.length>a.records)&&r("budget");for(const u of g){const c=F(u);(c.kind!=="fact"||T(c.value.fields,c.value.version)!==u||!P(u)||c.value.fields.by!=="target"||c.value.fields.epoch!==void 0||c.value.fields.sig!==void 0)&&r("root-lot-format")}w(e.root)!==l&&r("stale");const v=await O(e.root,{records:g,keyId:e.signer.keyId,signer:{name:e.signer.name,sign:e.signer.sign,signal:y},signal:y,storage:e.storage,prepared:e.prepared,committed:d((u,c,B)=>{o={identity:u,bundle:c,status:B}},"committed")});if(v!==0&&!o)return{kind:"refuse",code:"host/act",diagnostics:i};const E={place:t,status:o?.status??"already-held",...o?{identity:o.identity,act:I(e.root,o.identity).result}:{},conformance:v===0?"complete":"refused",reading:k},N=s(JSON.stringify(E)+`
|
|
6
|
+
`);return{kind:"fact",value:{...E,result:N,commitment:L(k,N,s)},diagnostics:i}}catch(t){return t instanceof q?{kind:"uncertain",identity:t.identity,code:t.code,diagnostic:t.message,diagnostics:i}:o?{kind:"fact",value:{place:n.place,status:o.status,identity:o.identity,conformance:"incomplete"},diagnostic:t instanceof Error?t.message:"post-commit failure",diagnostics:i}:{kind:"refuse",code:t instanceof A?t.code:"host/failed",diagnostic:t instanceof Error?t.message:"REFUSE\xB7host/failed",diagnostics:i}}}))}d(se,"landRootLotInProcess");function ae(n,e){return S({instrumentName:e.instrumentName,runtime:structuredClone(e.runtime),output:d(()=>{},"output")},()=>{try{R(n)||r("context");const i=I(e.root,n);return{kind:"fact",value:{historical:!0,act:i.result,bundle:i.bundle}}}catch(i){return{kind:"refuse",code:i instanceof A?i.code:"host/failed",diagnostic:i instanceof Error?i.message:"REFUSE\xB7host/failed"}}})}d(ae,"recoverRootActInProcess");export{se as landRootLotInProcess,ae as recoverRootActInProcess,w as rootLotSnapshot};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
var I=Object.defineProperty;var m=(e,d)=>I(e,"name",{value:d,configurable:!0});import{library11_parse as R}from"../vendor/runtime.js";import{library2_readingIdentity as y,library2_readingReceiptIdentity as k}from"../vendor/runtime.js";import{readContent as C}from"../engine/ports.js";import{sha256 as a,isSha256 as v}from"./hash.js";import{BoundRefusal as w}from"./refusals.js";import{refuseHost as r}from"./host-controls.js";import{assertStandingView as E,publicStandingProjection as _}from"./standing-projection.js";async function H(e,d){try{(!e||typeof e.place!="string"||!e.place||typeof e.source!="string"||!e.source||!v(e.snapshot))&&r("context"),e.signal?.aborted&&r("cancelled");const{place:i,source:b,snapshot:g,signal:c}=e,s={...e.limits};(!Number.isSafeInteger(s.records)||s.records<1)&&r("budget");const t=structuredClone(e.anchor),l=structuredClone(e.reading);(!t||t.keyClass!=="authorize"||!t.id||!t.publicKey||!Array.isArray(t.coverage)||!t.coverage.length)&&r("context"),y(l,a);const p=y({...l,inputs:[...l.inputs,["host/place",a(i)],["host/anchor",a(JSON.stringify(t))],["host/snapshot",g]]},a),S=await C(b,g,{read:d.read,digestBytes:a},s,c);let u;try{u=new TextDecoder("utf-8",{fatal:!0}).decode(S)}catch{return r("snapshot-format")}const n=u.split(`
|
|
2
|
+
`).filter(f=>f.length>0);n.length>s.records&&r("budget"),(!n.length||n.some(f=>R(f).kind!=="fact"))&&r("snapshot-format"),c?.aborted&&r("cancelled");const o=_(n,t);E(o),c?.aborted&&r("cancelled");const h=a(o.join(`
|
|
3
|
+
`)+(o.length?`
|
|
4
|
+
`:""));return{kind:"fact",value:{place:i,rootStanding:o,reading:p,result:h,commitment:k(p,h,a)}}}catch(i){return{kind:"refuse",code:i instanceof w?i.code:"host/failed",diagnostic:i instanceof Error?i.message:"REFUSE\xB7host/failed"}}}m(H,"readRootStandingInProcess");export{H as readRootStandingInProcess};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {public2_HostInstrumentRuntime as HostInstrumentRuntime,public2_NativeHostInstrument as NativeHostInstrument,public2_NativeReadingIdentityContext as NativeReadingIdentityContext,public2_NativeReadingIdentityResult as NativeReadingIdentityResult,public2_NativeViewIdentityContext as NativeViewIdentityContext,public2_NativeViewIdentityResult as NativeViewIdentityResult,public2_PlaceActBudget as PlaceActBudget,public2_PlaceActHostContext as PlaceActHostContext,public2_PlaceActHostPorts as PlaceActHostPorts,public2_PlaceActPersistence as PlaceActPersistence,public2_PlaceActTrust as PlaceActTrust,public2_PreparedReading as PreparedReading,public2_PublicationStorage as PublicationStorage,public2_ReadingPreparationLimits as ReadingPreparationLimits,public2_ReadingPreparationResult as ReadingPreparationResult,public2_RootLotContext as RootLotContext,public2_RootLotPorts as RootLotPorts,public2_RootStandingHostContext as RootStandingHostContext,public2_RootStandingHostResult as RootStandingHostResult,public2_landPlaceActInProcess as landPlaceActInProcess,public2_landRootLotInProcess as landRootLotInProcess,public2_nativeHostInstrument as nativeHostInstrument,public2_nativePlaceActPersistence as nativePlaceActPersistence,public2_nativePlaceActReceiver as nativePlaceActReceiver,public2_prepareNativeReadingIdentity as prepareNativeReadingIdentity,public2_prepareNativeViewIdentity as prepareNativeViewIdentity,public2_readContextualStandingInProcess as readContextualStandingInProcess,public2_readRootStandingInProcess as readRootStandingInProcess,public2_recoverPlaceActInProcess as recoverPlaceActInProcess,public2_recoverRootActInProcess as recoverRootActInProcess,public2_rootLotSnapshot as rootLotSnapshot} from "../public-types.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{readRootStandingInProcess as o}from"./in-process.js";import{readContextualStandingInProcess as n}from"./in-process-context.js";import{landPlaceActInProcess as c,recoverPlaceActInProcess as s}from"./in-process-act.js";import{landRootLotInProcess as p,recoverRootActInProcess as P,rootLotSnapshot as d}from"./in-process-root.js";import{nativeHostInstrument as m,nativePlaceActReceiver as v}from"./native-receiver.js";import{nativePlaceActPersistence as f}from"./ports/place-act.js";import{prepareNativeReadingIdentity as A,prepareNativeViewIdentity as R}from"./reading-identity.js";export{c as landPlaceActInProcess,p as landRootLotInProcess,m as nativeHostInstrument,f as nativePlaceActPersistence,v as nativePlaceActReceiver,A as prepareNativeReadingIdentity,R as prepareNativeViewIdentity,n as readContextualStandingInProcess,o as readRootStandingInProcess,s as recoverPlaceActInProcess,P as recoverRootActInProcess,d as rootLotSnapshot};
|
package/dist/host/io.js
CHANGED
|
@@ -1,11 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export { spawn, spawnSync } from 'node:child_process';
|
|
3
|
-
export { createHash } from 'node:crypto';
|
|
4
|
-
export { appendFileSync, closeSync, existsSync, linkSync, lstatSync, mkdirSync, mkdtempSync, openSync, readFileSync, readSync, readdirSync, realpathSync, renameSync, rmSync, statSync, writeFileSync, } from 'node:fs';
|
|
5
|
-
export { tmpdir } from 'node:os';
|
|
6
|
-
export { basename, dirname, join, relative, resolve } from 'node:path';
|
|
7
|
-
export { fileURLToPath } from 'node:url';
|
|
8
|
-
export { parentPort, workerData } from 'node:worker_threads';
|
|
9
|
-
export { gzipSync } from 'node:zlib';
|
|
10
|
-
/** UTF-8 encoding is shared with host-free protocol ports. */
|
|
11
|
-
export { encodeUTF8 } from "../engine/encoding.js";
|
|
1
|
+
import{spawn as n,spawnSync as o}from"node:child_process";import{createHash as a}from"node:crypto";import{appendFileSync as p,closeSync as y,existsSync as S,linkSync as m,lstatSync as i,mkdirSync as d,mkdtempSync as f,openSync as l,readFileSync as s,readSync as x,readdirSync as k,realpathSync as w,renameSync as F,rmSync as h,statSync as v,writeFileSync as P}from"node:fs";import{tmpdir as U}from"node:os";import{basename as g,dirname as j,join as z,relative as D,resolve as H}from"node:path";import{fileURLToPath as R}from"node:url";import{parentPort as u,workerData as A}from"node:worker_threads";import{gzipSync as C}from"node:zlib";import{encodeUTF8 as G}from"../engine/encoding.js";export{p as appendFileSync,g as basename,y as closeSync,a as createHash,j as dirname,G as encodeUTF8,S as existsSync,R as fileURLToPath,C as gzipSync,z as join,m as linkSync,i as lstatSync,d as mkdirSync,f as mkdtempSync,l as openSync,u as parentPort,s as readFileSync,x as readSync,k as readdirSync,w as realpathSync,D as relative,F as renameSync,H as resolve,h as rmSync,n as spawn,o as spawnSync,v as statSync,U as tmpdir,A as workerData,P as writeFileSync};
|
package/dist/host/lifetime.js
CHANGED
|
@@ -1,79 +1 @@
|
|
|
1
|
-
import {
|
|
2
|
-
const deadline = BigInt(process.argv[2] ?? '0'), responseBytes = Number(process.argv[3]);
|
|
3
|
-
if (deadline <= 0n || !Number.isSafeInteger(responseBytes) || responseBytes <= 0)
|
|
4
|
-
throw Error('REFUSE·reader invalid process limits');
|
|
5
|
-
let child, finished = false, failure, size = 0;
|
|
6
|
-
const stdout = [], stderr = [];
|
|
7
|
-
const grouped = process.platform !== 'win32';
|
|
8
|
-
const cancel = () => { if (child?.pid === undefined)
|
|
9
|
-
return; try {
|
|
10
|
-
if (grouped)
|
|
11
|
-
process.kill(-child.pid, 'SIGKILL');
|
|
12
|
-
else
|
|
13
|
-
child.kill('SIGKILL');
|
|
14
|
-
}
|
|
15
|
-
catch { } };
|
|
16
|
-
const finish = (status, signal) => {
|
|
17
|
-
if (finished)
|
|
18
|
-
return;
|
|
19
|
-
finished = true;
|
|
20
|
-
clearTimeout(timer);
|
|
21
|
-
cancel();
|
|
22
|
-
child?.stdin?.destroy();
|
|
23
|
-
child?.stdout?.destroy();
|
|
24
|
-
child?.stderr?.destroy();
|
|
25
|
-
process.stdin.destroy();
|
|
26
|
-
const bytes = failure ? Buffer.alloc(0) : Buffer.concat(stdout);
|
|
27
|
-
const result = { stdout: bytes.toString('utf8'), stdoutBytes: bytes.toString('base64'), stderr: Buffer.concat(stderr).toString('utf8'), status, signal, ...(failure ? { failure } : {}) };
|
|
28
|
-
process.stdout.write(JSON.stringify(result));
|
|
29
|
-
};
|
|
30
|
-
const refuse = (why) => { if (failure && why === 'response exceeds declared byte bound' && !failure.includes(why))
|
|
31
|
-
failure += ' · ' + why;
|
|
32
|
-
else
|
|
33
|
-
failure ?? (failure = why); finish(null, 'SIGKILL'); };
|
|
34
|
-
// A closed input pipe can precede the queued stderr/close events of an early
|
|
35
|
-
// rejecting child. Cancel immediately, but drain only until the SAME deadline.
|
|
36
|
-
const inputFailed = (why) => { if (finished)
|
|
37
|
-
return; failure ?? (failure = why); stdout.length = 0; cancel(); child?.stdin?.destroy(); process.stdin.destroy(); if (process.hrtime.bigint() >= deadline)
|
|
38
|
-
finish(null, 'SIGKILL'); };
|
|
39
|
-
const remaining = Number(deadline - process.hrtime.bigint()) / 1e6;
|
|
40
|
-
const timer = setTimeout(() => refuse('declared timeout exhausted'), Math.max(0, remaining));
|
|
41
|
-
process.once('SIGTERM', () => refuse('interrupted'));
|
|
42
|
-
try {
|
|
43
|
-
if (remaining <= 0)
|
|
44
|
-
refuse('declared timeout exhausted');
|
|
45
|
-
const chunks = [];
|
|
46
|
-
for await (const chunk of process.stdin) {
|
|
47
|
-
if (finished)
|
|
48
|
-
break;
|
|
49
|
-
chunks.push(Buffer.from(chunk));
|
|
50
|
-
}
|
|
51
|
-
if (!finished) {
|
|
52
|
-
const request = JSON.parse(Buffer.concat(chunks).toString('utf8'));
|
|
53
|
-
if (request.limits.responseBytes !== responseBytes || !Number.isSafeInteger(request.limits.timeoutMs) || request.limits.timeoutMs <= 0)
|
|
54
|
-
throw Error('invalid process limits');
|
|
55
|
-
// Parsing is synchronous; recheck before spawning even if the timer has not
|
|
56
|
-
// had a turn to run. An expired handoff must never start the command.
|
|
57
|
-
if (process.hrtime.bigint() >= deadline) {
|
|
58
|
-
refuse('declared timeout exhausted');
|
|
59
|
-
}
|
|
60
|
-
else {
|
|
61
|
-
child = spawn(request.command, [...request.args], { cwd: request.cwd, env: request.env, detached: grouped, stdio: ['pipe', 'pipe', 'pipe'] });
|
|
62
|
-
const receive = (items, bytes) => { if (finished)
|
|
63
|
-
return; size += bytes.length; if (size > responseBytes)
|
|
64
|
-
refuse('response exceeds declared byte bound');
|
|
65
|
-
else if (!failure || items === stderr)
|
|
66
|
-
items.push(bytes); };
|
|
67
|
-
child.stdout.on('data', (b) => receive(stdout, b));
|
|
68
|
-
child.stderr.on('data', (b) => receive(stderr, b));
|
|
69
|
-
child.stdin.on('error', error => inputFailed('input failed: ' + error.message));
|
|
70
|
-
child.once('error', error => refuse(error.message));
|
|
71
|
-
child.once('close', finish);
|
|
72
|
-
child.stdin.end(request.input);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
catch {
|
|
77
|
-
if (!finished)
|
|
78
|
-
refuse('input unavailable or malformed');
|
|
79
|
-
}
|
|
1
|
+
var I=Object.defineProperty;var d=(s,e)=>I(s,"name",{value:e,configurable:!0});import{spawn as y}from"node:child_process";const u=BigInt(process.argv[2]??"0"),a=Number(process.argv[3]);if(u<=0n||!Number.isSafeInteger(a)||a<=0)throw Error("REFUSE\xB7reader invalid process limits");let t,o=!1,i,g=0;const f=[],l=[],h=process.platform!=="win32",b=d(()=>{if(t?.pid!==void 0)try{h?process.kill(-t.pid,"SIGKILL"):t.kill("SIGKILL")}catch{}},"cancel"),p=d((s,e)=>{if(o)return;o=!0,clearTimeout(v),b(),t?.stdin?.destroy(),t?.stdout?.destroy(),t?.stderr?.destroy(),process.stdin.destroy();const c=i?Buffer.alloc(0):Buffer.concat(f),r={stdout:c.toString("utf8"),stdoutBytes:c.toString("base64"),stderr:Buffer.concat(l).toString("utf8"),status:s,signal:e,...i?{failure:i}:{}};process.stdout.write(JSON.stringify(r))},"finish"),n=d(s=>{i&&s==="response exceeds declared byte bound"&&!i.includes(s)?i+=" \xB7 "+s:i??(i=s),p(null,"SIGKILL")},"refuse"),B=d(s=>{o||(i??(i=s),f.length=0,b(),t?.stdin?.destroy(),process.stdin.destroy(),process.hrtime.bigint()>=u&&p(null,"SIGKILL"))},"inputFailed"),S=Number(u-process.hrtime.bigint())/1e6,v=setTimeout(()=>n("declared timeout exhausted"),Math.max(0,S));process.once("SIGTERM",()=>n("interrupted"));try{S<=0&&n("declared timeout exhausted");const s=[];for await(const e of process.stdin){if(o)break;s.push(Buffer.from(e))}if(!o){const e=JSON.parse(Buffer.concat(s).toString("utf8"));if(e.limits.responseBytes!==a||!Number.isSafeInteger(e.limits.timeoutMs)||e.limits.timeoutMs<=0)throw Error("invalid process limits");if(process.hrtime.bigint()>=u)n("declared timeout exhausted");else{t=y(e.command,[...e.args],{cwd:e.cwd,env:e.env,detached:h,stdio:["pipe","pipe","pipe"]});const c=d((r,m)=>{o||(g+=m.length,g>a?n("response exceeds declared byte bound"):(!i||r===l)&&r.push(m))},"receive");t.stdout.on("data",r=>c(f,r)),t.stderr.on("data",r=>c(l,r)),t.stdin.on("error",r=>B("input failed: "+r.message)),t.once("error",r=>n(r.message)),t.once("close",p),t.stdin.end(e.input)}}}catch{o||n("input unavailable or malformed")}
|
package/dist/host/located.js
CHANGED
|
@@ -1,105 +1,6 @@
|
|
|
1
|
-
var
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
return path;
|
|
8
|
-
};
|
|
9
|
-
import { readFileSync } from 'node:fs';
|
|
10
|
-
import { join } from 'node:path';
|
|
11
|
-
import { pathToFileURL } from 'node:url';
|
|
12
|
-
import { pinExport, provide } from "./provide.js";
|
|
13
|
-
const wanted = (role) => role === 'reader' ? ['observe', 'run'] : [role];
|
|
14
|
-
const foreign = (role) => ['render', 'receipt', 'observe', 'run'].filter((name) => !wanted(role).includes(name));
|
|
15
|
-
const isFn = (module, name) => typeof module[name] === 'function';
|
|
16
|
-
const text = (error) => (error instanceof Error ? error.message : String(error)).replace(/\s+/g, ' ').trim();
|
|
17
|
-
/**
|
|
18
|
-
* Wire and capsule of the world, from `dep/topos` (or the lock's `uses/topos` pin). The host never spells where that
|
|
19
|
-
* package lies.
|
|
20
|
-
*/
|
|
21
|
-
const sdk = async () => {
|
|
22
|
-
provide();
|
|
23
|
-
const [wireAt, capsuleAt] = [pinExport('topos', './wire'), pinExport('topos', './capsule')];
|
|
24
|
-
if (!wireAt || !capsuleAt)
|
|
25
|
-
throw new Error('REFUSE·pin dep/topos names no wire or capsule');
|
|
26
|
-
const [wire, capsule] = await Promise.all([import(__rewriteRelativeImportExtension(pathToFileURL(wireAt).href)), import(__rewriteRelativeImportExtension(pathToFileURL(capsuleAt).href))]);
|
|
27
|
-
return {
|
|
28
|
-
CAPSULE: String(wire['CAPSULE'] ?? ''),
|
|
29
|
-
PROTOCOL: String(wire['PROTOCOL'] ?? ''),
|
|
30
|
-
parse: wire['parse'],
|
|
31
|
-
declarationOf: capsule['declarationOf'],
|
|
32
|
-
readers: capsule['readers'],
|
|
33
|
-
receiptShell: capsule['receiptShell'],
|
|
34
|
-
shell: capsule['shell'],
|
|
35
|
-
};
|
|
36
|
-
};
|
|
37
|
-
/**
|
|
38
|
-
* The host loads a world from its lock: the lock read once, each region imported from its one file by name and role into
|
|
39
|
-
* the shell of its kind. A region that fails is one line on stderr and is left out; the regions that loaded still form
|
|
40
|
-
* the shell. A world with no region of a kind has no shell of it. `load` is the host's child entry, the same load with
|
|
41
|
-
* its places read from the arguments the host spawned it with.
|
|
42
|
-
*/
|
|
43
|
-
/** A capsule that ships one render module: the host calls it per region and hands it the lines. The module does not read. */
|
|
44
|
-
const pagesOf = async (root, file) => {
|
|
45
|
-
const { CAPSULE, PROTOCOL, declarationOf, shell } = await sdk();
|
|
46
|
-
const lines = readFileSync(join(root, CAPSULE), 'utf8').split('\n').filter((line) => line.startsWith(PROTOCOL));
|
|
47
|
-
const { regions } = declarationOf(lines);
|
|
48
|
-
const module = await import(__rewriteRelativeImportExtension(pathToFileURL(join(root, file)).href));
|
|
49
|
-
const render = module['render'] ?? module['default']?.['render'];
|
|
50
|
-
if (typeof render !== 'function')
|
|
51
|
-
return {};
|
|
52
|
-
const held = Object.fromEntries(Object.entries(regions).map(([name, reads]) => [name, {
|
|
53
|
-
reads,
|
|
54
|
-
region: (asked) => render({ ...asked, region: name }),
|
|
55
|
-
}]));
|
|
56
|
-
return held && Object.keys(held).length ? { render: shell(held) } : {};
|
|
57
|
-
};
|
|
58
|
-
export const locate = async (root, dir, ext) => {
|
|
59
|
-
if (ext === 'render')
|
|
60
|
-
return pagesOf(root, dir);
|
|
61
|
-
const { CAPSULE, PROTOCOL, parse, declarationOf, readers, receiptShell, shell } = await sdk();
|
|
62
|
-
const lines = readFileSync(join(root, CAPSULE), 'utf8').split('\n').filter((line) => line.startsWith(PROTOCOL));
|
|
63
|
-
const field = (line, name) => ((got) => (got.kind === 'fact' ? got.value.fields[name] ?? '' : ''))(parse(line));
|
|
64
|
-
const { regions, writes } = declarationOf(lines);
|
|
65
|
-
const reader = new Set(lines.filter((line) => field(line, 'measure') === 'writes').map((line) => field(line, 'scope').slice('region/'.length)));
|
|
66
|
-
const kind = (name) => (reader.has(name) ? 'reader' : writes[name] ?? '');
|
|
67
|
-
const region = async (name, reads, role) => {
|
|
68
|
-
let module;
|
|
69
|
-
try {
|
|
70
|
-
module = await import(__rewriteRelativeImportExtension(pathToFileURL(join(root, dir, `${name}${ext}`)).href));
|
|
71
|
-
}
|
|
72
|
-
catch (error) {
|
|
73
|
-
process.stderr.write(`LOAD ${name} · module error · ${text(error)}\n`);
|
|
74
|
-
return undefined;
|
|
75
|
-
}
|
|
76
|
-
const has = wanted(role).filter((key) => isFn(module, key));
|
|
77
|
-
const exported = foreign(role).filter((key) => isFn(module, key));
|
|
78
|
-
if (!has.length && exported.length) {
|
|
79
|
-
process.stderr.write(`LOAD ${name} · role mismatch · ${role} exports ${exported.join('|')}\n`);
|
|
80
|
-
return undefined;
|
|
81
|
-
}
|
|
82
|
-
if (!has.length) {
|
|
83
|
-
process.stderr.write(`LOAD ${name} · missing export · ${wanted(role)[0]}\n`);
|
|
84
|
-
return undefined;
|
|
85
|
-
}
|
|
86
|
-
const picked = role === 'reader' ? { observe: module['observe'], run: module['run'] } : { region: module[role] };
|
|
87
|
-
return [name, { reads, ...picked }];
|
|
88
|
-
};
|
|
89
|
-
const loaded = async (role) => {
|
|
90
|
-
const held = [];
|
|
91
|
-
for (const [name, reads] of Object.entries(regions)) {
|
|
92
|
-
if (kind(name) !== role)
|
|
93
|
-
continue;
|
|
94
|
-
const row = await region(name, reads, role);
|
|
95
|
-
if (row)
|
|
96
|
-
held.push(row);
|
|
97
|
-
}
|
|
98
|
-
return held.length ? Object.fromEntries(held) : undefined;
|
|
99
|
-
};
|
|
100
|
-
const render = await loaded('render');
|
|
101
|
-
const receipt = await loaded('receipt');
|
|
102
|
-
const reading = await loaded('reader');
|
|
103
|
-
return { render: render && shell(render), receipt: receipt && receiptShell(receipt), ...(reading ? readers(reading) : {}) };
|
|
104
|
-
};
|
|
105
|
-
export const load = () => locate(process.argv[3] ?? '', process.argv[4] ?? '', process.argv[5] ?? '');
|
|
1
|
+
var I=Object.defineProperty;var n=(e,t)=>I(e,"name",{value:t,configurable:!0});var m=function(e,t){return typeof e=="string"&&/^\.\.?\//.test(e)?e.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i,function(i,o,d,p,f){return o?t?".jsx":".js":d&&(!p||!f)?i:d+p+"."+f.toLowerCase()+"js"}):e};import{readFileSync as P}from"node:fs";import{join as E}from"node:path";import{pathToFileURL as L}from"node:url";import{pinExport as R,provide as W}from"./provide.js";const j=n(e=>e==="reader"?["observe","run"]:[e],"wanted"),q=n(e=>["render","receipt","observe","run"].filter(t=>!j(e).includes(t)),"foreign"),U=n((e,t)=>typeof e[t]=="function","isFn"),z=n(e=>(e instanceof Error?e.message:String(e)).replace(/\s+/g," ").trim(),"text"),k=n(async()=>{W();const[e,t]=[R("topos","./wire"),R("topos","./capsule")];if(!e||!t)throw new Error("REFUSE\xB7pin dep/topos names no wire or capsule");const[i,o]=await Promise.all([import(m(L(e).href)),import(m(L(t).href))]);return{CAPSULE:String(i.CAPSULE??""),PROTOCOL:String(i.PROTOCOL??""),parse:i.parse,declarationOf:o.declarationOf,readers:o.readers,receiptShell:o.receiptShell,shell:o.shell}},"sdk"),B=n(async(e,t)=>{const{CAPSULE:i,PROTOCOL:o,declarationOf:d,shell:p}=await k(),f=P(E(e,i),"utf8").split(`
|
|
2
|
+
`).filter(a=>a.startsWith(o)),{regions:S}=d(f),g=await import(m(L(E(e,t)).href)),O=g.render??g.default?.render;if(typeof O!="function")return{};const u=Object.fromEntries(Object.entries(S).map(([a,v])=>[a,{reads:v,region:n(y=>O({...y,region:a}),"region")}]));return u&&Object.keys(u).length?{render:p(u)}:{}},"pagesOf"),G=n(async(e,t,i)=>{if(i==="render")return B(e,t);const{CAPSULE:o,PROTOCOL:d,parse:p,declarationOf:f,readers:S,receiptShell:g,shell:O}=await k(),u=P(E(e,o),"utf8").split(`
|
|
3
|
+
`).filter(r=>r.startsWith(d)),a=n((r,l)=>(s=>s.kind==="fact"?s.value.fields[l]??"":"")(p(r)),"field"),{regions:v,writes:y}=f(u),T=new Set(u.filter(r=>a(r,"measure")==="writes").map(r=>a(r,"scope").slice(7))),F=n(r=>T.has(r)?"reader":y[r]??"","kind"),_=n(async(r,l,s)=>{let c;try{c=await import(m(L(E(e,t,`${r}${i}`)).href))}catch(w){process.stderr.write(`LOAD ${r} \xB7 module error \xB7 ${z(w)}
|
|
4
|
+
`);return}const h=j(s).filter(w=>U(c,w)),C=q(s).filter(w=>U(c,w));if(!h.length&&C.length){process.stderr.write(`LOAD ${r} \xB7 role mismatch \xB7 ${s} exports ${C.join("|")}
|
|
5
|
+
`);return}if(!h.length){process.stderr.write(`LOAD ${r} \xB7 missing export \xB7 ${j(s)[0]}
|
|
6
|
+
`);return}const D=s==="reader"?{observe:c.observe,run:c.run}:{region:c[s]};return[r,{reads:l,...D}]},"region"),$=n(async r=>{const l=[];for(const[s,c]of Object.entries(v)){if(F(s)!==r)continue;const h=await _(s,c,r);h&&l.push(h)}return l.length?Object.fromEntries(l):void 0},"loaded"),b=await $("render"),x=await $("receipt"),A=await $("reader");return{render:b&&O(b),receipt:x&&g(x),...A?S(A):{}}},"locate"),Q=n(()=>G(process.argv[3]??"",process.argv[4]??"",process.argv[5]??""),"load");export{Q as load,G as locate};
|
|
@@ -1,32 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
/** The opened descriptor is bounded before allocation/read. Growth after fstat
|
|
3
|
-
* is detected with one sentinel byte; no oversized buffer reaches decode/hash.
|
|
4
|
-
*/
|
|
5
|
-
export function readBoundedFile(path, remaining, coordinate) {
|
|
6
|
-
if (!Number.isSafeInteger(remaining) || remaining < 0)
|
|
7
|
-
throw Error('REFUSE·native file missing byte budget ' + coordinate);
|
|
8
|
-
const fd = fs.openSync(path, 'r');
|
|
9
|
-
try {
|
|
10
|
-
const stat = fs.fstatSync(fd);
|
|
11
|
-
if (!stat.isFile() || !Number.isSafeInteger(stat.size) || stat.size > remaining)
|
|
12
|
-
throw Error('REFUSE·native file byte budget before read ' + coordinate);
|
|
13
|
-
const bytes = Buffer.alloc(stat.size);
|
|
14
|
-
let offset = 0;
|
|
15
|
-
while (offset < bytes.length) {
|
|
16
|
-
const count = fs.readSync(fd, bytes, offset, bytes.length - offset, null);
|
|
17
|
-
if (!count)
|
|
18
|
-
throw Error('REFUSE·native file changed during read ' + coordinate);
|
|
19
|
-
offset += count;
|
|
20
|
-
}
|
|
21
|
-
if (fs.readSync(fd, Buffer.alloc(1), 0, 1, null) !== 0)
|
|
22
|
-
throw Error('REFUSE·native file grew during read ' + coordinate);
|
|
23
|
-
return bytes;
|
|
24
|
-
}
|
|
25
|
-
finally {
|
|
26
|
-
fs.closeSync(fd);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
export function readBoundedBatch(paths, budget) {
|
|
30
|
-
let bytes = 0;
|
|
31
|
-
return paths.map(file => { const data = readBoundedFile(file.path, budget - bytes, file.coordinate); bytes += data.length; return data; });
|
|
32
|
-
}
|
|
1
|
+
var u=Object.defineProperty;var a=(o,e)=>u(o,"name",{value:e,configurable:!0});import f from"node:fs";function c(o,e,t){if(!Number.isSafeInteger(e)||e<0)throw Error("REFUSE\xB7native file missing byte budget "+t);const r=f.openSync(o,"r");try{const n=f.fstatSync(r);if(!n.isFile()||!Number.isSafeInteger(n.size)||n.size>e)throw Error("REFUSE\xB7native file byte budget before read "+t);const i=Buffer.alloc(n.size);let l=0;for(;l<i.length;){const s=f.readSync(r,i,l,i.length-l,null);if(!s)throw Error("REFUSE\xB7native file changed during read "+t);l+=s}if(f.readSync(r,Buffer.alloc(1),0,1,null)!==0)throw Error("REFUSE\xB7native file grew during read "+t);return i}finally{f.closeSync(r)}}a(c,"readBoundedFile");function h(o,e){let t=0;return o.map(r=>{const n=c(r.path,e-t,r.coordinate);return t+=n.length,n})}a(h,"readBoundedBatch");export{h as readBoundedBatch,c as readBoundedFile};
|
|
@@ -1,91 +1 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { channel } from 'node:diagnostics_channel';
|
|
3
|
-
import { isAbsolute } from 'node:path';
|
|
4
|
-
import { checkCommandPort, commandRequest, commandResponse } from '@lapxo/topos/contract';
|
|
5
|
-
import { requireEffects } from "../read-only.js";
|
|
6
|
-
import { assertNativeRuntime } from "./runtime.js";
|
|
7
|
-
import { scheduleDeadline } from "./deadline.js";
|
|
8
|
-
const rejectedCommand = channel('bound.command.refusal');
|
|
9
|
-
/** macOS prototype: bounded async invocation with POSIX child-group cancellation.
|
|
10
|
-
* No acquisition or persistence on prospective paths; no partial success frames.
|
|
11
|
-
* Host callbacks are trusted admission/verification operations, never signatures
|
|
12
|
-
* or authority assertions supplied by the command's own output. */
|
|
13
|
-
export async function executeLot(options) {
|
|
14
|
-
const start = process.hrtime.bigint();
|
|
15
|
-
const { host, signal, phase, accepts } = options;
|
|
16
|
-
// Admitted semantic configuration is snapshotted for the whole invocation;
|
|
17
|
-
// mutations of a caller's delivery object cannot alter checks mid-flight.
|
|
18
|
-
const port = Object.freeze({ ...options.port, closure: Object.freeze([...options.port.closure]), environment: Object.freeze([...options.port.environment]) });
|
|
19
|
-
const lot = Object.freeze({ ...options.lot, requests: Object.freeze([...options.lot.requests]) });
|
|
20
|
-
const environment = Object.freeze({ ...options.environment });
|
|
21
|
-
assertNativeRuntime(environment, []);
|
|
22
|
-
const refuse = (why) => { throw Error(`REFUSE·port ${port.coordinate} ${why}`); };
|
|
23
|
-
if (phase !== 'act')
|
|
24
|
-
refuse('invocation forbidden during ' + phase);
|
|
25
|
-
requireEffects('command ' + port.coordinate);
|
|
26
|
-
if (signal?.aborted)
|
|
27
|
-
refuse('interrupted before invocation');
|
|
28
|
-
checkCommandPort(port, host);
|
|
29
|
-
const deadline = start + BigInt(port.timeoutMs) * 1000000n;
|
|
30
|
-
const resolved = host.resolve(port), invocation = Object.freeze({ ...resolved, args: Object.freeze([...resolved.args]) });
|
|
31
|
-
if (!isAbsolute(invocation.command) || !isAbsolute(invocation.cwd))
|
|
32
|
-
refuse('host invocation needs absolute coordinates');
|
|
33
|
-
if (host.loaderClosure(port, invocation) !== 'verified')
|
|
34
|
-
refuse('runtime-loader closure unmeasured');
|
|
35
|
-
const names = Object.keys(environment).sort(), declared = [...new Set(port.environment)].sort();
|
|
36
|
-
if (names.length !== declared.length || names.some((name, index) => name !== declared[index]) || names.some(name => typeof environment[name] !== 'string' || environment[name].includes('\0')))
|
|
37
|
-
refuse('environment differs from declared handoff');
|
|
38
|
-
const frame = commandRequest(port, lot);
|
|
39
|
-
const envelope = invocation.hostEnvelope;
|
|
40
|
-
if (envelope && (!Number.isSafeInteger(invocation.envelopeBytes) || invocation.envelopeBytes < 1 || envelope.byteLength > invocation.envelopeBytes))
|
|
41
|
-
refuse('host envelope byte resources');
|
|
42
|
-
if (process.hrtime.bigint() >= deadline)
|
|
43
|
-
refuse('timeout before invocation');
|
|
44
|
-
if (signal?.aborted)
|
|
45
|
-
refuse('interrupted before invocation');
|
|
46
|
-
const result = await new Promise((resolve, reject) => {
|
|
47
|
-
const child = spawn(invocation.command, [...invocation.args], { cwd: invocation.cwd, env: { ...environment }, shell: false, detached: false, stdio: envelope ? ['pipe', 'pipe', 'pipe', 'pipe'] : ['pipe', 'pipe', 'pipe'] });
|
|
48
|
-
const stdout = [], stderr = [];
|
|
49
|
-
let bytes = 0, why, done = false;
|
|
50
|
-
const stop = (cause) => { if (why)
|
|
51
|
-
return; why = cause; try {
|
|
52
|
-
child.kill('SIGKILL');
|
|
53
|
-
}
|
|
54
|
-
catch { } child.stdin.destroy(); if (envelope)
|
|
55
|
-
child.stdio[3]?.destroy(); };
|
|
56
|
-
const cancelTimer = scheduleDeadline(deadline, () => stop('timeout'));
|
|
57
|
-
const abort = () => stop('interrupted');
|
|
58
|
-
signal?.addEventListener('abort', abort, { once: true });
|
|
59
|
-
if (signal?.aborted)
|
|
60
|
-
abort();
|
|
61
|
-
const collect = (target, chunk, channel) => { if (why)
|
|
62
|
-
return; bytes += chunk.length; if (bytes > port.responseBytes) {
|
|
63
|
-
stop('response-bytes exceeded');
|
|
64
|
-
return;
|
|
65
|
-
} if (channel === 'stderr' && port.stderr === 'reject') {
|
|
66
|
-
rejectedCommand.publish({ coordinate: port.coordinate, stderr: chunk.subarray(0, Math.min(port.responseBytes, 1024)).toString('utf8') });
|
|
67
|
-
stop('stderr forbidden');
|
|
68
|
-
return;
|
|
69
|
-
} target.push(chunk); };
|
|
70
|
-
child.stdout.on('data', (chunk) => collect(stdout, chunk, 'stdout'));
|
|
71
|
-
child.stderr.on('data', (chunk) => collect(stderr, chunk, 'stderr'));
|
|
72
|
-
child.stdin.on('error', () => stop('request handoff failed'));
|
|
73
|
-
const finish = (status, error) => { if (done)
|
|
74
|
-
return; done = true; cancelTimer(); signal?.removeEventListener('abort', abort); if (error || why) {
|
|
75
|
-
reject(Error(`REFUSE·port ${port.coordinate} ${why ?? error.message}`));
|
|
76
|
-
return;
|
|
77
|
-
} resolve({ status, interrupted: false, stdout: Buffer.concat(stdout).toString('utf8'), stderr: Buffer.concat(stderr).toString('utf8') }); };
|
|
78
|
-
child.once('error', error => finish(null, error));
|
|
79
|
-
child.once('close', status => finish(status));
|
|
80
|
-
if (envelope) {
|
|
81
|
-
const pipe = child.stdio[3];
|
|
82
|
-
const header = Buffer.alloc(8);
|
|
83
|
-
header.writeBigUInt64BE(BigInt(envelope.byteLength));
|
|
84
|
-
pipe.on('error', () => stop('host envelope handoff failed'));
|
|
85
|
-
pipe.end(Buffer.concat([header, Buffer.from(envelope)]));
|
|
86
|
-
}
|
|
87
|
-
child.stdin.end(frame);
|
|
88
|
-
});
|
|
89
|
-
const members = commandResponse(port, lot, result, accepts);
|
|
90
|
-
return { members, stderr: result.stderr, invocations: 1 };
|
|
91
|
-
}
|
|
1
|
+
var _=Object.defineProperty;var a=(n,p)=>_(n,"name",{value:p,configurable:!0});import{spawn as k}from"node:child_process";import{channel as F}from"node:diagnostics_channel";import{isAbsolute as C}from"node:path";import{library2_checkCommandPort as M,library2_commandRequest as N,library2_commandResponse as A}from"../../vendor/runtime.js";import{requireEffects as D}from"../read-only.js";import{assertNativeRuntime as G}from"./runtime.js";import{scheduleDeadline as K}from"./deadline.js";const T=F("bound.command.refusal");async function te(n){const p=process.hrtime.bigint(),{host:b,signal:m,phase:y,accepts:$}=n,t=Object.freeze({...n.port,closure:Object.freeze([...n.port.closure]),environment:Object.freeze([...n.port.environment])}),B=Object.freeze({...n.lot,requests:Object.freeze([...n.lot.requests])}),l=Object.freeze({...n.environment});G(l,[]);const i=a(c=>{throw Error(`REFUSE\xB7port ${t.coordinate} ${c}`)},"refuse");y!=="act"&&i("invocation forbidden during "+y),D("command "+t.coordinate),m?.aborted&&i("interrupted before invocation"),M(t,b);const j=p+BigInt(t.timeoutMs)*1000000n,E=b.resolve(t),r=Object.freeze({...E,args:Object.freeze([...E.args])});(!C(r.command)||!C(r.cwd))&&i("host invocation needs absolute coordinates"),b.loaderClosure(t,r)!=="verified"&&i("runtime-loader closure unmeasured");const h=Object.keys(l).sort(),w=[...new Set(t.environment)].sort();(h.length!==w.length||h.some((c,v)=>c!==w[v])||h.some(c=>typeof l[c]!="string"||l[c].includes("\0")))&&i("environment differs from declared handoff");const x=N(t,B),d=r.hostEnvelope;d&&(!Number.isSafeInteger(r.envelopeBytes)||r.envelopeBytes<1||d.byteLength>r.envelopeBytes)&&i("host envelope byte resources"),process.hrtime.bigint()>=j&&i("timeout before invocation"),m?.aborted&&i("interrupted before invocation");const O=await new Promise((c,v)=>{const o=k(r.command,[...r.args],{cwd:r.cwd,env:{...l},shell:!1,detached:!1,stdio:d?["pipe","pipe","pipe","pipe"]:["pipe","pipe","pipe"]}),z=[],S=[];let L=0,u,R=!1;const f=a(e=>{if(!u){u=e;try{o.kill("SIGKILL")}catch{}o.stdin.destroy(),d&&o.stdio[3]?.destroy()}},"stop"),P=K(j,()=>f("timeout")),g=a(()=>f("interrupted"),"abort");m?.addEventListener("abort",g,{once:!0}),m?.aborted&&g();const q=a((e,s,U)=>{if(!u){if(L+=s.length,L>t.responseBytes){f("response-bytes exceeded");return}if(U==="stderr"&&t.stderr==="reject"){T.publish({coordinate:t.coordinate,stderr:s.subarray(0,Math.min(t.responseBytes,1024)).toString("utf8")}),f("stderr forbidden");return}e.push(s)}},"collect");o.stdout.on("data",e=>q(z,e,"stdout")),o.stderr.on("data",e=>q(S,e,"stderr")),o.stdin.on("error",()=>f("request handoff failed"));const I=a((e,s)=>{if(!R){if(R=!0,P(),m?.removeEventListener("abort",g),s||u){v(Error(`REFUSE\xB7port ${t.coordinate} ${u??s.message}`));return}c({status:e,interrupted:!1,stdout:Buffer.concat(z).toString("utf8"),stderr:Buffer.concat(S).toString("utf8")})}},"finish");if(o.once("error",e=>I(null,e)),o.once("close",e=>I(e)),d){const e=o.stdio[3],s=Buffer.alloc(8);s.writeBigUInt64BE(BigInt(d.byteLength)),e.on("error",()=>f("host envelope handoff failed")),e.end(Buffer.concat([s,Buffer.from(d)]))}o.stdin.end(x)});return{members:A(t,B,O,$),stderr:O.stderr,invocations:1}}a(te,"executeLot");export{te as executeLot};
|