@lapxo/bound 0.2.4 → 0.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CITATION.cff +1 -1
- package/TARGET.bound +44 -39
- package/dist/cli/accept.js +72 -590
- 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 -282
- package/dist/cli/release-result.js +3 -80
- package/dist/cli/retained-judgment.js +1 -25
- package/dist/cli/standing-result.js +4 -19
- package/dist/cli/takes.js +10 -112
- package/dist/cli/verb.d.ts +1 -2
- package/dist/cli/verb.js +83 -684
- 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 -117
- 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 -132
- package/dist/fold/closed.js +24 -235
- 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 -35
- package/dist/host/archive.js +1 -152
- package/dist/host/call-context.js +1 -14
- package/dist/host/capsule-process.js +2 -62
- package/dist/host/capsule.js +9 -171
- package/dist/host/cell-receipts.js +12 -128
- package/dist/host/commit-result.js +1 -5
- package/dist/host/content-needed.js +1 -8
- package/dist/host/content-store.js +1 -31
- package/dist/host/contextual-place.js +2 -72
- package/dist/host/digest.js +2 -15
- package/dist/host/hash.js +1 -9
- package/dist/host/host-controls.js +1 -19
- package/dist/host/in-process-act.js +3 -84
- package/dist/host/in-process-context.js +3 -91
- package/dist/host/in-process-root.js +6 -84
- package/dist/host/in-process.js +4 -55
- package/dist/host/index.d.ts +1 -15
- package/dist/host/index.js +1 -7
- 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 -25
- package/dist/host/objects.js +1 -38
- package/dist/host/order.js +1 -2
- package/dist/host/place-act-transaction.js +4 -78
- 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 -183
- package/dist/host/ports/place-act.js +1 -134
- 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 -307
- package/dist/host/selected-capsules.js +1 -50
- package/dist/host/selected-topos.js +1 -80
- package/dist/host/signature-era.js +1 -12
- package/dist/host/signing.js +2 -48
- package/dist/host/source-content.js +2 -111
- package/dist/host/standing-carrier.js +1 -18
- package/dist/host/standing-projection.js +1 -50
- 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 -336
- 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 -41
- package/dist/observe/runner.js +4 -101
- 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-publication.inventory.json +2 -1
- package/docs/contracts/optional-wasm-adapter.publication.json +1 -1
- 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/reference.md +1 -0
- package/package.json +23 -34
- package/receipts.bound +11627 -10323
- package/samples/reading-identity/no.json +20 -0
- package/samples/reading-identity/yes.json +46 -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/.github/workflows/release.yml +0 -67
- package/.github/workflows/test.yml +0 -35
- package/dist/engine/object.d.ts +0 -17
- package/dist/engine/ports.d.ts +0 -37
- package/dist/fold/claims.d.ts +0 -29
- package/dist/host/call-context.d.ts +0 -20
- package/dist/host/commit-result.d.ts +0 -6
- package/dist/host/in-process-act.d.ts +0 -82
- package/dist/host/in-process-context.d.ts +0 -46
- package/dist/host/in-process-root.d.ts +0 -117
- package/dist/host/in-process.d.ts +0 -41
- package/dist/host/native/module-closure.d.ts +0 -35
- package/dist/host/native-receiver.d.ts +0 -19
- package/dist/host/place-act-transaction.d.ts +0 -24
- package/dist/host/place-clock-selection.d.ts +0 -55
- package/dist/host/ports/local-act.d.ts +0 -44
- package/dist/host/ports/place-act.d.ts +0 -49
- package/dist/host/ports/publication.d.ts +0 -10
- 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
- package/dist/host/root-clock-source.d.ts +0 -86
|
@@ -1,216 +1 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { sha256 as hash } from "../hash.js";
|
|
3
|
-
/** Instrument-only native route. The caller holds the existing Root lease
|
|
4
|
-
* across selection, cache authorization and this complete bounded child act.
|
|
5
|
-
*/
|
|
6
|
-
import { dirname } from 'node:path';
|
|
7
|
-
import { realpathSync } from 'node:fs';
|
|
8
|
-
import { nativeBinaryOrigin } from "./native-binary.js";
|
|
9
|
-
import { selectedHostControl } from "./control-selection.js";
|
|
10
|
-
import { authorityAtEpoch } from '@lapxo/topos/wire';
|
|
11
|
-
import { parsedLine as parse } from "../../fold/claims.js";
|
|
12
|
-
import { authorityFor } from "../../fold/signers.js";
|
|
13
|
-
import { authenticatedRootStanding } from "../admitted-place.js";
|
|
14
|
-
import { nativeExecutorInputs } from "./materialize.js";
|
|
15
|
-
export { materializeNativeRoute } from "./materialize.js";
|
|
16
|
-
import { assertNativeRuntime } from "./runtime.js";
|
|
17
|
-
import { nativeReferenceInputs } from "./references.js";
|
|
18
|
-
import { rootAuthorityProtection } from "../../land/act.js";
|
|
19
|
-
import { currentNativeRoot, inheritedNativeRoot } from "./root.js";
|
|
20
|
-
import { authenticateSignedPort, authenticateNativeProfile, canonicalJson } from "./reading.js";
|
|
21
|
-
import { boundedProcess } from "../process-lifetime.js";
|
|
22
|
-
import { validResponse, CapsuleProcessError } from "../capsule-process.js";
|
|
23
|
-
import { processOf } from "../../observe/runner.js";
|
|
24
|
-
const fail = (why) => { throw Error('REFUSE·native route ' + why); };
|
|
25
|
-
const routes = new WeakMap();
|
|
26
|
-
/** Shared origins are one exact input; individual signed selectors remain separate. */
|
|
27
|
-
export function nativeBinaryOriginInputs(binaries) {
|
|
28
|
-
const seen = new Map(), inputs = [];
|
|
29
|
-
for (const binary of binaries) {
|
|
30
|
-
if (!binary.origin)
|
|
31
|
-
continue;
|
|
32
|
-
const coordinate = 'native/binary-origin/' + binary.origin.coordinate, digest = hash(binary.origin.line), prior = seen.get(coordinate);
|
|
33
|
-
if (prior !== undefined) {
|
|
34
|
-
if (prior !== digest)
|
|
35
|
-
fail('conflicting binary origin input ' + coordinate);
|
|
36
|
-
continue;
|
|
37
|
-
}
|
|
38
|
-
seen.set(coordinate, digest);
|
|
39
|
-
inputs.push([coordinate, digest]);
|
|
40
|
-
}
|
|
41
|
-
return Object.freeze(inputs);
|
|
42
|
-
}
|
|
43
|
-
/** Inputs are semantic logical references. Fixed instrument/host graph and
|
|
44
|
-
* runtime-supervisor chain must also be supplied by the calling identity builder.
|
|
45
|
-
* Locations and lock-token/PID are operational custody, never these inputs.
|
|
46
|
-
*/
|
|
47
|
-
export function prepareNativeRoute(store, coordinate, readerMapping) {
|
|
48
|
-
const proof = rootAuthorityProtection(store), current = currentNativeRoot(store, process.pid, proof);
|
|
49
|
-
return prepareAtCurrentRoot(store, coordinate, readerMapping, current);
|
|
50
|
-
}
|
|
51
|
-
/** Private same-call reuse only: callers cannot supply a standing as authority. */
|
|
52
|
-
function prepareAtCurrentRoot(store, coordinate, readerMapping, current) {
|
|
53
|
-
const { root, context } = current, selected = authenticateNativeProfile(root, coordinate), profile = selected.profile;
|
|
54
|
-
// The Root cursor authorizes today's act under the held lease. It is not a
|
|
55
|
-
// semantic input to every program: unrelated Root acts do not reopen it.
|
|
56
|
-
// Exact selected grants and the authenticated reader mapping remain inputs.
|
|
57
|
-
const binaries = authenticatedNativeBinaries(root, profile), control = selectedHostControl(root, profile), identity = hash(canonicalJson([coordinate, selected.line, profile, binaries, readerMapping ?? null, ...(control ? [control] : [])])), inputs = [['native/selection', identity], ...(readerMapping ? [['native/reader-mapping', hash(readerMapping)]] : []), ...profile.selection.members.map(m => ['native/' + m.coordinate, m.digest]), ...binaries.map(b => ['native/binary/' + b.coordinate, hash(b.line)])];
|
|
58
|
-
inputs.push(...nativeBinaryOriginInputs(binaries));
|
|
59
|
-
if (control)
|
|
60
|
-
inputs.push(['native/control-profile', hash(control.line)], ['native/control-worker', control.profile.worker.digest], ['native/control-runtime', control.profile.runtime.digest]);
|
|
61
|
-
const route = { identity, profile, binaries, ...(control ? { control } : {}), inputs: inputs };
|
|
62
|
-
routes.set(route, { store, coordinate, context, profile });
|
|
63
|
-
inputs.push(...nativeExecutorInputs(route));
|
|
64
|
-
if (control && inputs.find(([name]) => name === control.profile.worker.coordinate)?.[1] !== control.profile.worker.digest)
|
|
65
|
-
fail('control worker differs from sealed executor');
|
|
66
|
-
Object.freeze(inputs);
|
|
67
|
-
return Object.freeze(route);
|
|
68
|
-
}
|
|
69
|
-
/** Recheck authority before both a current retained answer and fresh execution.
|
|
70
|
-
* Historical public --check uses the existing receipt-inspection path, not this
|
|
71
|
-
* command authorization route.
|
|
72
|
-
*/
|
|
73
|
-
export function assertNativeRouteCurrent(route) {
|
|
74
|
-
const held = routes.get(route);
|
|
75
|
-
if (!held)
|
|
76
|
-
return fail('unknown prepared route');
|
|
77
|
-
const proof = rootAuthorityProtection(held.store), root = inheritedNativeRoot({ store: held.store, parent: process.pid, expected: held.context }, proof);
|
|
78
|
-
const profile = authenticateSignedPort(root, held.coordinate).profile;
|
|
79
|
-
if (canonicalJson(profile) !== canonicalJson(held.profile) || canonicalJson(authenticatedNativeBinaries(root, held.profile)) !== canonicalJson(route.binaries) || canonicalJson(selectedHostControl(root, held.profile) ?? null) !== canonicalJson(route.control ?? null))
|
|
80
|
-
fail('current port changed');
|
|
81
|
-
}
|
|
82
|
-
export function invokeNativeRoute(route, input) {
|
|
83
|
-
const held = routes.get(route);
|
|
84
|
-
if (!held)
|
|
85
|
-
return fail('unknown prepared route');
|
|
86
|
-
assertNativeRouteCurrent(route);
|
|
87
|
-
assertNativeRuntime(input.execution.env, input.execution.flags);
|
|
88
|
-
if (input.execution.context.implementation !== held.profile.selection.archive)
|
|
89
|
-
fail('reading implementation differs');
|
|
90
|
-
nativeReferenceInputs(input.execution.context.inputs, route.inputs);
|
|
91
|
-
if (input.limits.timeoutMs > held.profile.port.timeoutMs || input.limits.responseBytes > held.profile.port.responseBytes)
|
|
92
|
-
fail('reader limits exceed current command grant');
|
|
93
|
-
const proof = rootAuthorityProtection(held.store), frame = { proof, archive: input.archive, locations: input.locations, requests: input.requests };
|
|
94
|
-
const args = [processOf('native'), held.store, held.coordinate, JSON.stringify(held.context), 'reserved', String(held.profile.selection.budget.bytes), 'act', String(process.pid), JSON.stringify(input.execution)];
|
|
95
|
-
const result = boundedProcess(process.execPath, args, JSON.stringify(frame), input.limits, input.execution.cwd, input.execution.env);
|
|
96
|
-
if (result.signal !== null || result.status !== 0)
|
|
97
|
-
throw new CapsuleProcessError('native child exited ' + String(result.status ?? result.signal), result);
|
|
98
|
-
let values;
|
|
99
|
-
try {
|
|
100
|
-
values = JSON.parse(result.stdout.trimEnd());
|
|
101
|
-
}
|
|
102
|
-
catch {
|
|
103
|
-
return fail('native child malformed batch');
|
|
104
|
-
}
|
|
105
|
-
if (!Array.isArray(values) || values.length !== input.requests.length || !values.every((value, index) => validResponse(value, input.requests[index])))
|
|
106
|
-
fail('native child invalid batch');
|
|
107
|
-
assertNativeRouteCurrent(route);
|
|
108
|
-
return values;
|
|
109
|
-
}
|
|
110
|
-
/** This predicate only schedules an outer lease. It grants no command. */
|
|
111
|
-
export function declaredNativeReaderPorts(lines) { return lines.some(line => { const got = parse(line); return got.kind === 'fact' && got.value.fields.scope.startsWith('reader/') && got.value.fields.scope.split('/').at(-1) === 'port' && got.value.fields.value !== 'withdraw'; }); }
|
|
112
|
-
export function prepareNativeReaderRoute(store, reader) {
|
|
113
|
-
const expectedScope = ['reader', reader.module, 'port'].join('/');
|
|
114
|
-
const declared = authenticatedRootStanding(dirname(store));
|
|
115
|
-
if (!declared.some(line => { const got = parse(line); return got.kind === 'fact' && got.value.fields.scope === expectedScope && got.value.fields.value !== 'withdraw'; }))
|
|
116
|
-
return undefined;
|
|
117
|
-
const proof = rootAuthorityProtection(store), currentRoot = currentNativeRoot(store, process.pid, proof), root = currentRoot.root;
|
|
118
|
-
const rows = root.live.filter(line => { const got = parse(line); return got.kind === 'fact' && got.value.fields.scope === expectedScope; });
|
|
119
|
-
if (!rows.length)
|
|
120
|
-
return undefined;
|
|
121
|
-
if (rows.length !== 1)
|
|
122
|
-
fail('ambiguous reader port ' + expectedScope);
|
|
123
|
-
const got = parse(rows[0]);
|
|
124
|
-
if (got.kind !== 'fact')
|
|
125
|
-
return fail('invalid reader port ' + expectedScope);
|
|
126
|
-
const f = got.value.fields;
|
|
127
|
-
if (f.role !== 'writes' || f.form !== 'alphabet' || f.measure !== 'id' || typeof f.value !== 'string' || !/^port\/[^\s]+$/.test(f.value))
|
|
128
|
-
fail('malformed reader port ' + expectedScope);
|
|
129
|
-
const auth = authorityFor(root.history, root.signer, root.eras), signed = auth.of(rows[0]);
|
|
130
|
-
if (signed.kind !== 'admitted' || signed.signer !== root.signer.id)
|
|
131
|
-
fail('reader port is not Root signed ' + expectedScope);
|
|
132
|
-
if (signed.kind !== 'admitted')
|
|
133
|
-
return fail('reader port signature not admitted');
|
|
134
|
-
const signer = auth.admitted.find(one => one.id === signed.signer);
|
|
135
|
-
if (!signer)
|
|
136
|
-
return fail('reader port signer absent');
|
|
137
|
-
const current = authorityAtEpoch(f, signer, root.epoch, expectedScope, 'authority');
|
|
138
|
-
if (current.kind !== 'admitted')
|
|
139
|
-
fail('reader port current eligibility ' + current.why);
|
|
140
|
-
return prepareAtCurrentRoot(store, f.value, rows[0], currentRoot);
|
|
141
|
-
}
|
|
142
|
-
export function nativeRouteStore(route) { const held = routes.get(route); if (!held)
|
|
143
|
-
return fail('unknown prepared route'); return held.store; }
|
|
144
|
-
/** Quiet-pass gate: authenticate grants/cursor only, no image/materialization or
|
|
145
|
-
* program execution. Historical --check remains its separate receipt path. */
|
|
146
|
-
export function assertNativeReaderGrantsCurrent(store) { currentNativeReaderSelections(store); }
|
|
147
|
-
/** Executable kinds come only from current authenticated Root declarations. A
|
|
148
|
-
* matching JSON hint identifies a candidate, but is never permission to execute. */
|
|
149
|
-
export function authenticatedNativeBinaries(root, profile) {
|
|
150
|
-
const out = [], names = new Set();
|
|
151
|
-
const keys = fieldNames;
|
|
152
|
-
for (const line of root.live) {
|
|
153
|
-
const row = parse(line);
|
|
154
|
-
if (row.kind !== 'fact' || !row.value.fields.scope.startsWith('port/'))
|
|
155
|
-
continue;
|
|
156
|
-
let hint;
|
|
157
|
-
try {
|
|
158
|
-
hint = JSON.parse(row.value.fields.about ?? '');
|
|
159
|
-
}
|
|
160
|
-
catch {
|
|
161
|
-
continue;
|
|
162
|
-
}
|
|
163
|
-
if (!['host-native-binary@1', 'host-native-binary-origin@1'].includes(hint?.profile) || hint.selector?.port !== profile.port.coordinate)
|
|
164
|
-
continue;
|
|
165
|
-
const coordinate = row.value.fields.scope, auth = authenticateSignedPort(root, coordinate), p = auth.profile;
|
|
166
|
-
if (keys(p) !== (p.profile === 'host-native-binary-origin@1' ? 'alias,condition,coordinate,entry,limits,origin,profile,selector' : 'alias,condition,coordinate,entry,limits,profile,selector') || p.coordinate !== coordinate || typeof p.alias !== 'string' || !p.alias.length || p.alias.includes('\0') || typeof p.condition !== 'string' || !p.condition.length || keys(p.selector ?? {}) !== 'binding,implementation,port' || p.selector.implementation !== profile.port.implementation || !profile.selection.bindings.some(b => b.id === p.selector.binding))
|
|
167
|
-
fail('binary declaration differs from selected parent ' + coordinate);
|
|
168
|
-
const entry = p.entry, member = profile.selection.members.find(m => m.coordinate === entry?.path);
|
|
169
|
-
if (keys(entry ?? {}) !== 'bytes,digest,path' || !member || entry.path === profile.selection.runtime || member.digest !== entry.digest || !Number.isSafeInteger(entry.bytes) || entry.bytes < 1 || keys(p.limits ?? {}) !== 'bytes' || !Number.isSafeInteger(p.limits.bytes) || p.limits.bytes < entry.bytes || p.limits.bytes > profile.selection.budget.bytes)
|
|
170
|
-
fail('binary outside selected image resources ' + coordinate);
|
|
171
|
-
if (names.has(coordinate))
|
|
172
|
-
fail('ambiguous binary declaration ' + coordinate);
|
|
173
|
-
names.add(coordinate);
|
|
174
|
-
if (entry.digest === profile.selection.members.find(m => m.coordinate === profile.selection.runtime)?.digest)
|
|
175
|
-
fail('binary aliases selected runtime');
|
|
176
|
-
const origin = nativeBinaryOrigin(root, p, auth.line);
|
|
177
|
-
if (origin?.path === realpathSync(process.execPath))
|
|
178
|
-
fail('binary origin aliases actual runtime');
|
|
179
|
-
out.push(Object.freeze({ line: auth.line, coordinate, profile: p, ...(origin ? { origin } : {}) }));
|
|
180
|
-
}
|
|
181
|
-
return Object.freeze(out);
|
|
182
|
-
}
|
|
183
|
-
/** Same semantic image identity for preparation, retained mount and quiet checks. */
|
|
184
|
-
export function nativeMountIdentity(profile, binaries, control) { return hash(canonicalJson(['logical-native-image/2', profile.selection, binaries, ...(control ? [control] : [])])); }
|
|
185
|
-
/** Current eligibility only: no executor graph, image load or materialization. */
|
|
186
|
-
export function currentNativeReaderSelections(store) {
|
|
187
|
-
const declared = authenticatedRootStanding(dirname(store));
|
|
188
|
-
if (!declaredNativeReaderPorts(declared))
|
|
189
|
-
return [];
|
|
190
|
-
const proof = rootAuthorityProtection(store), currentRoot = currentNativeRoot(store, process.pid, proof), root = currentRoot.root;
|
|
191
|
-
const mappings = root.live.flatMap(line => { const row = parse(line); return row.kind === 'fact' && row.value.fields.scope.startsWith('reader/') && row.value.fields.scope.split('/').at(-1) === 'port' ? [{ line, fields: row.value.fields }] : []; });
|
|
192
|
-
const seen = new Set(), auth = authorityFor(root.history, root.signer, root.eras), out = [];
|
|
193
|
-
for (const { line, fields: f } of mappings) {
|
|
194
|
-
if (seen.has(f.scope))
|
|
195
|
-
fail('ambiguous reader port ' + f.scope);
|
|
196
|
-
seen.add(f.scope);
|
|
197
|
-
if (f.role !== 'writes' || f.form !== 'alphabet' || f.measure !== 'id' || typeof f.value !== 'string' || !/^port\/[^\s]+$/.test(f.value))
|
|
198
|
-
fail('malformed reader port ' + f.scope);
|
|
199
|
-
const signed = auth.of(line);
|
|
200
|
-
if (signed.kind !== 'admitted' || signed.signer !== root.signer.id)
|
|
201
|
-
fail('reader port is not Root signed ' + f.scope);
|
|
202
|
-
if (signed.kind !== 'admitted')
|
|
203
|
-
return fail('reader mapping not admitted');
|
|
204
|
-
const signer = auth.admitted.find(one => one.id === signed.signer);
|
|
205
|
-
if (!signer)
|
|
206
|
-
return fail('reader mapping signer absent');
|
|
207
|
-
const current = authorityAtEpoch(f, signer, root.epoch, f.scope, 'authority');
|
|
208
|
-
if (current.kind !== 'admitted')
|
|
209
|
-
fail('reader port current eligibility ' + current.why);
|
|
210
|
-
const { profile } = authenticateNativeProfile(root, f.value);
|
|
211
|
-
const control = selectedHostControl(root, profile);
|
|
212
|
-
out.push({ profile, binaries: authenticatedNativeBinaries(root, profile), ...(control ? { control } : {}) });
|
|
213
|
-
}
|
|
214
|
-
return out;
|
|
215
|
-
}
|
|
216
|
-
export function currentNativeReaderProfiles(store) { return currentNativeReaderSelections(store).map(selection => selection.profile); }
|
|
1
|
+
var q=Object.defineProperty;var m=(t,e)=>q(t,"name",{value:e,configurable:!0});import{fieldNames as M}from"./reading.js";import{sha256 as b}from"../hash.js";import{dirname as O}from"node:path";import{realpathSync as W}from"node:fs";import{nativeBinaryOrigin as F}from"./native-binary.js";import{selectedHostControl as R}from"./control-selection.js";import{library11_authorityAtEpoch as P}from"../../vendor/runtime.js";import{parsedLine as x}from"../../fold/claims.js";import{authorityFor as E}from"../../fold/signers.js";import{authenticatedRootStanding as j}from"../admitted-place.js";import{nativeExecutorInputs as $}from"./materialize.js";import{materializeNativeRoute as Se}from"./materialize.js";import{assertNativeRuntime as G}from"./runtime.js";import{nativeReferenceInputs as H}from"./references.js";import{rootAuthorityProtection as w}from"../../land/act.js";import{currentNativeRoot as N,inheritedNativeRoot as L}from"./root.js";import{authenticateSignedPort as z,authenticateNativeProfile as A,canonicalJson as y}from"./reading.js";import{boundedProcess as U}from"../process-lifetime.js";import{validResponse as _,CapsuleProcessError as D}from"../capsule-process.js";import{processOf as K}from"../../observe/runner.js";const s=m(t=>{throw Error("REFUSE\xB7native route "+t)},"fail"),k=new WeakMap;function Q(t){const e=new Map,i=[];for(const f of t){if(!f.origin)continue;const o="native/binary-origin/"+f.origin.coordinate,g=b(f.origin.line),a=e.get(o);if(a!==void 0){a!==g&&s("conflicting binary origin input "+o);continue}e.set(o,g),i.push([o,g])}return Object.freeze(i)}m(Q,"nativeBinaryOriginInputs");function he(t,e,i){const f=w(t),o=N(t,process.pid,f);return I(t,e,i,o)}m(he,"prepareNativeRoute");function I(t,e,i,f){const{root:o,context:g}=f,a=A(o,e),c=a.profile,l=S(o,c),n=R(o,c),r=b(y([e,a.line,c,l,i??null,...n?[n]:[]])),d=[["native/selection",r],...i?[["native/reader-mapping",b(i)]]:[],...c.selection.members.map(p=>["native/"+p.coordinate,p.digest]),...l.map(p=>["native/binary/"+p.coordinate,b(p.line)])];d.push(...Q(l)),n&&d.push(["native/control-profile",b(n.line)],["native/control-worker",n.profile.worker.digest],["native/control-runtime",n.profile.runtime.digest]);const h={identity:r,profile:c,binaries:l,...n?{control:n}:{},inputs:d};return k.set(h,{store:t,coordinate:e,context:g,profile:c}),d.push(...$(h)),n&&d.find(([p])=>p===n.profile.worker.coordinate)?.[1]!==n.profile.worker.digest&&s("control worker differs from sealed executor"),Object.freeze(d),Object.freeze(h)}m(I,"prepareAtCurrentRoot");function J(t){const e=k.get(t);if(!e)return s("unknown prepared route");const i=w(e.store),f=L({store:e.store,parent:process.pid,expected:e.context},i),o=z(f,e.coordinate).profile;(y(o)!==y(e.profile)||y(S(f,e.profile))!==y(t.binaries)||y(R(f,e.profile)??null)!==y(t.control??null))&&s("current port changed")}m(J,"assertNativeRouteCurrent");function ve(t,e){const i=k.get(t);if(!i)return s("unknown prepared route");J(t),G(e.execution.env,e.execution.flags),e.execution.context.implementation!==i.profile.selection.archive&&s("reading implementation differs"),H(e.execution.context.inputs,t.inputs),(e.limits.timeoutMs>i.profile.port.timeoutMs||e.limits.responseBytes>i.profile.port.responseBytes)&&s("reader limits exceed current command grant");const f=w(i.store),o={proof:f,archive:e.archive,locations:e.locations,requests:e.requests},g=[K("native"),i.store,i.coordinate,JSON.stringify(i.context),"reserved",String(i.profile.selection.budget.bytes),"act",String(process.pid),JSON.stringify(e.execution)],a=U(process.execPath,g,JSON.stringify(o),e.limits,e.execution.cwd,e.execution.env);if(a.signal!==null||a.status!==0)throw new D("native child exited "+String(a.status??a.signal),a);let c;try{c=JSON.parse(a.stdout.trimEnd())}catch{return s("native child malformed batch")}return(!Array.isArray(c)||c.length!==e.requests.length||!c.every((l,n)=>_(l,e.requests[n])))&&s("native child invalid batch"),J(t),c}m(ve,"invokeNativeRoute");function T(t){return t.some(e=>{const i=x(e);return i.kind==="fact"&&i.value.fields.scope.startsWith("reader/")&&i.value.fields.scope.split("/").at(-1)==="port"&&i.value.fields.value!=="withdraw"})}m(T,"declaredNativeReaderPorts");function ye(t,e){const i=["reader",e.module,"port"].join("/");if(!j(O(t)).some(u=>{const v=x(u);return v.kind==="fact"&&v.value.fields.scope===i&&v.value.fields.value!=="withdraw"}))return;const o=w(t),g=N(t,process.pid,o),a=g.root,c=a.live.filter(u=>{const v=x(u);return v.kind==="fact"&&v.value.fields.scope===i});if(!c.length)return;c.length!==1&&s("ambiguous reader port "+i);const l=x(c[0]);if(l.kind!=="fact")return s("invalid reader port "+i);const n=l.value.fields;(n.role!=="writes"||n.form!=="alphabet"||n.measure!=="id"||typeof n.value!="string"||!/^port\/[^\s]+$/.test(n.value))&&s("malformed reader port "+i);const r=E(a.history,a.signer,a.eras),d=r.of(c[0]);if((d.kind!=="admitted"||d.signer!==a.signer.id)&&s("reader port is not Root signed "+i),d.kind!=="admitted")return s("reader port signature not admitted");const h=r.admitted.find(u=>u.id===d.signer);if(!h)return s("reader port signer absent");const p=P(n,h,a.epoch,i,"authority");return p.kind!=="admitted"&&s("reader port current eligibility "+p.why),I(t,n.value,c[0],g)}m(ye,"prepareNativeReaderRoute");function be(t){const e=k.get(t);return e?e.store:s("unknown prepared route")}m(be,"nativeRouteStore");function xe(t){B(t)}m(xe,"assertNativeReaderGrantsCurrent");function S(t,e){const i=[],f=new Set,o=M;for(const g of t.live){const a=x(g);if(a.kind!=="fact"||!a.value.fields.scope.startsWith("port/"))continue;let c;try{c=JSON.parse(a.value.fields.about??"")}catch{continue}if(!["host-native-binary@1","host-native-binary-origin@1"].includes(c?.profile)||c.selector?.port!==e.port.coordinate)continue;const l=a.value.fields.scope,n=z(t,l),r=n.profile;(o(r)!==(r.profile==="host-native-binary-origin@1"?"alias,condition,coordinate,entry,limits,origin,profile,selector":"alias,condition,coordinate,entry,limits,profile,selector")||r.coordinate!==l||typeof r.alias!="string"||!r.alias.length||r.alias.includes("\0")||typeof r.condition!="string"||!r.condition.length||o(r.selector??{})!=="binding,implementation,port"||r.selector.implementation!==e.port.implementation||!e.selection.bindings.some(u=>u.id===r.selector.binding))&&s("binary declaration differs from selected parent "+l);const d=r.entry,h=e.selection.members.find(u=>u.coordinate===d?.path);(o(d??{})!=="bytes,digest,path"||!h||d.path===e.selection.runtime||h.digest!==d.digest||!Number.isSafeInteger(d.bytes)||d.bytes<1||o(r.limits??{})!=="bytes"||!Number.isSafeInteger(r.limits.bytes)||r.limits.bytes<d.bytes||r.limits.bytes>e.selection.budget.bytes)&&s("binary outside selected image resources "+l),f.has(l)&&s("ambiguous binary declaration "+l),f.add(l),d.digest===e.selection.members.find(u=>u.coordinate===e.selection.runtime)?.digest&&s("binary aliases selected runtime");const p=F(t,r,n.line);p?.path===W(process.execPath)&&s("binary origin aliases actual runtime"),i.push(Object.freeze({line:n.line,coordinate:l,profile:r,...p?{origin:p}:{}}))}return Object.freeze(i)}m(S,"authenticatedNativeBinaries");function we(t,e,i){return b(y(["logical-native-image/2",t.selection,e,...i?[i]:[]]))}m(we,"nativeMountIdentity");function B(t){const e=j(O(t));if(!T(e))return[];const i=w(t),f=N(t,process.pid,i),o=f.root,g=o.live.flatMap(n=>{const r=x(n);return r.kind==="fact"&&r.value.fields.scope.startsWith("reader/")&&r.value.fields.scope.split("/").at(-1)==="port"?[{line:n,fields:r.value.fields}]:[]}),a=new Set,c=E(o.history,o.signer,o.eras),l=[];for(const{line:n,fields:r}of g){a.has(r.scope)&&s("ambiguous reader port "+r.scope),a.add(r.scope),(r.role!=="writes"||r.form!=="alphabet"||r.measure!=="id"||typeof r.value!="string"||!/^port\/[^\s]+$/.test(r.value))&&s("malformed reader port "+r.scope);const d=c.of(n);if((d.kind!=="admitted"||d.signer!==o.signer.id)&&s("reader port is not Root signed "+r.scope),d.kind!=="admitted")return s("reader mapping not admitted");const h=c.admitted.find(C=>C.id===d.signer);if(!h)return s("reader mapping signer absent");const p=P(r,h,o.epoch,r.scope,"authority");p.kind!=="admitted"&&s("reader port current eligibility "+p.why);const{profile:u}=A(o,r.value),v=R(o,u);l.push({profile:u,binaries:S(o,u),...v?{control:v}:{}})}return l}m(B,"currentNativeReaderSelections");function ke(t){return B(t).map(e=>e.profile)}m(ke,"currentNativeReaderProfiles");export{xe as assertNativeReaderGrantsCurrent,J as assertNativeRouteCurrent,S as authenticatedNativeBinaries,ke as currentNativeReaderProfiles,B as currentNativeReaderSelections,T as declaredNativeReaderPorts,ve as invokeNativeRoute,Se as materializeNativeRoute,Q as nativeBinaryOriginInputs,we as nativeMountIdentity,be as nativeRouteStore,ye as prepareNativeReaderRoute,he as prepareNativeRoute};
|
|
@@ -1,9 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* preloads. The fixed native entry currently has no ambient loader contract.
|
|
3
|
-
*/
|
|
4
|
-
export function assertNativeRuntime(environment, flags) {
|
|
5
|
-
if ((environment.NODE_OPTIONS ?? '').trim() !== '')
|
|
6
|
-
throw Error('REFUSE·native runtime NODE_OPTIONS has no fixed verified loader configuration');
|
|
7
|
-
if (flags.length)
|
|
8
|
-
throw Error('REFUSE·native runtime startup flags differ from the fixed dispatcher');
|
|
9
|
-
}
|
|
1
|
+
var e=Object.defineProperty;var t=(r,i)=>e(r,"name",{value:i,configurable:!0});function n(r,i){if((r.NODE_OPTIONS??"").trim()!=="")throw Error("REFUSE\xB7native runtime NODE_OPTIONS has no fixed verified loader configuration");if(i.length)throw Error("REFUSE\xB7native runtime startup flags differ from the fixed dispatcher")}t(n,"assertNativeRuntime");export{n as assertNativeRuntime};
|
|
@@ -1,8 +1 @@
|
|
|
1
|
-
|
|
2
|
-
// An opaque instrument selection travels with one observation. A request or a
|
|
3
|
-
// world's response cannot select its executor or replace another reader's port.
|
|
4
|
-
const active = new AsyncLocalStorage();
|
|
5
|
-
export const nativeReaderRoute = active.getStore.bind(active);
|
|
6
|
-
export function withNativeReaderRoute(route, run) {
|
|
7
|
-
return route === undefined ? run() : active.run(route, run);
|
|
8
|
-
}
|
|
1
|
+
var r=Object.defineProperty;var o=(e,t)=>r(e,"name",{value:t,configurable:!0});import{AsyncLocalStorage as i}from"node:async_hooks";const n=new i,d=n.getStore.bind(n);function u(e,t){return e===void 0?t():n.run(e,t)}o(u,"withNativeReaderRoute");export{d as nativeReaderRoute,u as withNativeReaderRoute};
|
|
@@ -1,25 +1 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { basename, dirname, extname, isAbsolute, join, relative } from 'node:path';
|
|
3
|
-
import { publicLock } from '@lapxo/topos/wire';
|
|
4
|
-
import { foldClaims, wireLinesOf } from "../fold/claims.js";
|
|
5
|
-
import { declaredRootClockSource } from "./root-clock-source.js";
|
|
6
|
-
import { withHostCall } from "./call-context.js";
|
|
7
|
-
import { BoundRefusal } from "./refusals.js";
|
|
8
|
-
/** Explicit installed/source ESM selection, never consumer argv or packet data.
|
|
9
|
-
* Identity and public configuration do not certify implementation correctness. */
|
|
10
|
-
export function nativeHostInstrument(root, entry) {
|
|
11
|
-
const at = realpathSync(root), file = realpathSync(entry), inside = relative(at, file), extension = extname(file);
|
|
12
|
-
if (!isAbsolute(root) || !isAbsolute(entry) || inside.startsWith('..') || isAbsolute(inside) || !['.ts', '.js'].includes(extension))
|
|
13
|
-
throw new BoundRefusal('host/context', 'REFUSE·host/context');
|
|
14
|
-
const published = publicLock(wireLinesOf(readFileSync(join(at, 'TARGET.bound'), 'utf8')));
|
|
15
|
-
if (!published)
|
|
16
|
-
throw new BoundRefusal('host/context', 'REFUSE·host requires a public instrument lock');
|
|
17
|
-
return { name: basename(at), runtime: { root: at, entry: file, directory: dirname(dirname(file)), extension: extension, lock: foldClaims(published).standing } };
|
|
18
|
-
}
|
|
19
|
-
/** Bind existing native authority construction to an explicit instrument for
|
|
20
|
-
* every later current/historical observation, not only the constructor call. */
|
|
21
|
-
export function nativePlaceActReceiver(root, instrument) {
|
|
22
|
-
const call = { instrumentName: instrument.name, runtime: structuredClone(instrument.runtime), output: () => { } };
|
|
23
|
-
const selected = withHostCall(call, () => declaredRootClockSource(root)), original = selected.trust;
|
|
24
|
-
return { selection: selected.selection, trust: { ...original, current: () => withHostCall(call, () => original.current()), historical: (encoded) => withHostCall(call, () => original.historical(encoded)) } };
|
|
25
|
-
}
|
|
1
|
+
var p=Object.defineProperty;var n=(r,e)=>p(r,"name",{value:e,configurable:!0});import{readFileSync as d,realpathSync as a}from"node:fs";import{basename as h,dirname as m,extname as b,isAbsolute as c,join as x,relative as w}from"node:path";import{library11_publicLock as R}from"../vendor/runtime.js";import{foldClaims as k,wireLinesOf as E}from"../fold/claims.js";import{declaredRootClockSource as S}from"./root-clock-source.js";import{withHostCall as l}from"./call-context.js";import{BoundRefusal as f}from"./refusals.js";function H(r,e){const t=a(r),o=a(e),i=w(t,o),s=b(o);if(!c(r)||!c(e)||i.startsWith("..")||c(i)||![".ts",".js"].includes(s))throw new f("host/context","REFUSE\xB7host/context");const u=R(E(d(x(t,"TARGET.bound"),"utf8")));if(!u)throw new f("host/context","REFUSE\xB7host requires a public instrument lock");return{name:h(t),runtime:{root:t,entry:o,directory:m(m(o)),extension:s,lock:k(u).standing}}}n(H,"nativeHostInstrument");function T(r,e){const t={instrumentName:e.name,runtime:structuredClone(e.runtime),output:n(()=>{},"output")},o=l(t,()=>S(r)),i=o.trust;return{selection:o.selection,trust:{...i,current:n(()=>l(t,()=>i.current()),"current"),historical:n(s=>l(t,()=>i.historical(s)),"historical")}}}n(T,"nativePlaceActReceiver");export{H as nativeHostInstrument,T as nativePlaceActReceiver};
|
package/dist/host/objects.js
CHANGED
|
@@ -1,38 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { objectProvider } from '@lapxo/topos/object-provider';
|
|
3
|
-
import { authorityFor, rootSigner } from "../fold/signers.js";
|
|
4
|
-
import { signaturesOf } from "../fold/digests.js";
|
|
5
|
-
import { storeOf } from "../land/ledger.js";
|
|
6
|
-
import { toposAt, contextModuleAt } from "./selected-topos.js";
|
|
7
|
-
import { foldClaims } from "../fold/claims.js";
|
|
8
|
-
import { usesWasmObject } from "../wasm/object.js";
|
|
9
|
-
/** Bound supplies host authority and I/O; topos owns grammar, selection and context validation. */
|
|
10
|
-
export async function admittedObjects(root, lines, emit = () => { }, requireContextClosure = false) {
|
|
11
|
-
const history = objectHistory(lines);
|
|
12
|
-
if (history.kind !== 'fact')
|
|
13
|
-
throw Error(`REFUSE·wire ${history.why}`);
|
|
14
|
-
const authority = authorityFor(lines, rootSigner(root), signaturesOf(storeOf(root)).admitted);
|
|
15
|
-
const admittedConfiguration = history.value.configuration.filter(fields => authority.of(canonical(fields)).kind === 'admitted').map(fields => canonical(fields));
|
|
16
|
-
const configuration = foldClaims(admittedConfiguration).standing.flatMap(line => { const got = parse(line); return got.kind === 'fact' ? [got.value.fields] : []; });
|
|
17
|
-
const verifyClosure = requireContextClosure || usesWasmObject(configuration), declaredModules = new Map();
|
|
18
|
-
const context = await objectProvider(history.value.objects, history.value.configuration, { admit: fields => authority.of(canonical(fields)).kind === 'admitted', emit, topos: digest => {
|
|
19
|
-
const selected = toposAt(digest, storeOf(root));
|
|
20
|
-
if (verifyClosure)
|
|
21
|
-
for (const offer of selected.parts.filter(fields => fields.kind === 'check' && fields.value)) {
|
|
22
|
-
const dependencies = [...new Set((offer.restsOn ?? '').split('|').filter(Boolean))].sort(), prior = declaredModules.get(offer.value);
|
|
23
|
-
if (prior && JSON.stringify(prior) !== JSON.stringify(dependencies))
|
|
24
|
-
throw Error('REFUSE·context module has conflicting declared closures');
|
|
25
|
-
declaredModules.set(offer.value, dependencies);
|
|
26
|
-
}
|
|
27
|
-
return selected;
|
|
28
|
-
}, module: digest => {
|
|
29
|
-
const dependencies = declaredModules.get(digest);
|
|
30
|
-
if (verifyClosure && dependencies === undefined)
|
|
31
|
-
throw Error('REFUSE·context module has no declared closure');
|
|
32
|
-
return contextModuleAt(digest, storeOf(root), verifyClosure ? dependencies : undefined);
|
|
33
|
-
} });
|
|
34
|
-
const checked = validateObjectContext(history.value.objects, context);
|
|
35
|
-
if (checked.kind !== 'fact')
|
|
36
|
-
throw Error(`REFUSE·context ${checked.why}`);
|
|
37
|
-
return { records: checked.value, context, configuration };
|
|
38
|
-
}
|
|
1
|
+
var b=Object.defineProperty;var e=(r,i)=>b(r,"name",{value:i,configurable:!0});import{library11_canonical as n,library11_parse as p,library11_objectHistory as y,library11_validateObjectContext as v}from"../vendor/runtime.js";import{objectProvider as g}from"../vendor/object-provider.js";import{authorityFor as h,rootSigner as j}from"../fold/signers.js";import{signaturesOf as x}from"../fold/digests.js";import{storeOf as d}from"../land/ledger.js";import{contextProviderServices as k}from"./selected-topos.js";import{foldClaims as w}from"../fold/claims.js";async function U(r,i,m=()=>{},C=!1){const o=y(i);if(o.kind!=="fact")throw Error(`REFUSE\xB7wire ${o.why}`);const c=h(i,j(r),x(d(r)).admitted),l=o.value.configuration.filter(t=>c.of(n(t)).kind==="admitted").map(t=>n(t)),u=w(l).standing.flatMap(t=>{const f=p(t);return f.kind==="fact"?[f.value.fields]:[]}),s=await g(o.value.objects,o.value.configuration,{admit:e(t=>c.of(n(t)).kind==="admitted","admit"),emit:m,...k(d(r))}),a=v(o.value.objects,s);if(a.kind!=="fact")throw Error(`REFUSE\xB7context ${a.why}`);return{records:a.value,context:s,configuration:u}}e(U,"admittedObjects");export{U as admittedObjects};
|
package/dist/host/order.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export const compareStrings = (a, b) => a < b ? -1 : a > b ? 1 : 0;
|
|
1
|
+
var c=Object.defineProperty;var t=(o,r)=>c(o,"name",{value:r,configurable:!0});const n=t((o,r)=>o<r?-1:o>r?1:0,"compareStrings");export{n as compareStrings};
|
|
@@ -1,78 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import { assertHostNotCancelled as cancelled, receiverClock, placeRegionOf } from "./host-controls.js";
|
|
6
|
-
export { ActCommitUnknown as PlaceActCommitUnknown } from "./commit-result.js";
|
|
7
|
-
/** The visibility point may have happened. Only an authenticated result query
|
|
8
|
-
* or replay can resolve this; the error never asserts rollback. */
|
|
9
|
-
const fail = (why) => { throw new BoundRefusal('host/act', 'REFUSE·place act ' + why); };
|
|
10
|
-
const rootBytes = (r) => JSON.stringify([r.namespace, r.snapshot, r.epoch, r.prefix, r.head, r.policies]);
|
|
11
|
-
/** Shared transaction, including historical replay, current authorization and
|
|
12
|
-
* atomic publication. Signing may await; current Root and receiver heads are
|
|
13
|
-
* checked again afterwards while the same exclusion remains held. */
|
|
14
|
-
export async function transactPlaceAct(encoded, source, trust, limits, persistence, signal) {
|
|
15
|
-
requireEffects('place act commitment');
|
|
16
|
-
cancelled(signal);
|
|
17
|
-
if (!limits || !Number.isSafeInteger(limits.acts) || limits.acts < 1 || !Number.isSafeInteger(limits.bytes) || limits.bytes < 1)
|
|
18
|
-
fail('missing storage budget');
|
|
19
|
-
const decoded = readPlaceActContext(encoded, trust.contract.budget), id = trust.contract.digest(encoded);
|
|
20
|
-
const regions = decoded.places.map(p => placeRegionOf(p.place));
|
|
21
|
-
return persistence.exclusive(regions, async () => {
|
|
22
|
-
cancelled(signal);
|
|
23
|
-
const prior = persistence.result(id, trust, limits);
|
|
24
|
-
if (prior) {
|
|
25
|
-
if (prior.context !== encoded)
|
|
26
|
-
fail('replay bytes differ');
|
|
27
|
-
// A signing callback is never invoked for a historically authenticated replay.
|
|
28
|
-
if (typeof source !== 'function')
|
|
29
|
-
placeActReceiptsOf(encoded, source, trust.historical(encoded));
|
|
30
|
-
return { ...prior, identity: id, kind: 'once' };
|
|
31
|
-
}
|
|
32
|
-
const verified = verifyPlaceActContext(encoded, trust.contract);
|
|
33
|
-
const originals = decoded.places.map(p => p.records);
|
|
34
|
-
const capacity = (size) => {
|
|
35
|
-
const inventory = persistence.inventory(limits);
|
|
36
|
-
if (inventory.bytes + size > limits.bytes)
|
|
37
|
-
fail('publication byte budget');
|
|
38
|
-
if (inventory.names.length >= limits.acts)
|
|
39
|
-
fail('publication act budget');
|
|
40
|
-
};
|
|
41
|
-
const sizeOf = (files) => Object.values(files).reduce((n, v) => n + new TextEncoder().encode(v).length, 0);
|
|
42
|
-
capacity(sizeOf({ 'context.json': encoded, 'originals.json': JSON.stringify(originals) + '\n' }));
|
|
43
|
-
const assertCurrent = () => {
|
|
44
|
-
const current = trust.current();
|
|
45
|
-
if (rootBytes(current.root) !== rootBytes(verified.dependencies))
|
|
46
|
-
fail('authority changed before publication');
|
|
47
|
-
if (new Set(current.heads.map(h => h.place)).size !== current.heads.length)
|
|
48
|
-
fail('ambiguous receiver heads');
|
|
49
|
-
const stored = persistence.heads(trust, limits);
|
|
50
|
-
for (const p of decoded.places) {
|
|
51
|
-
const actual = stored.find(h => h.place === p.place), selected = current.heads.find(h => h.place === p.place);
|
|
52
|
-
if (!actual || !selected || actual.identity !== selected.identity || actual.epoch !== selected.epoch)
|
|
53
|
-
fail('receiver snapshot is not committed head ' + p.place);
|
|
54
|
-
if (selected.identity !== p.previous)
|
|
55
|
-
fail('receiver head moved ' + p.place);
|
|
56
|
-
const next = receiverClock(selected.epoch, fail) + 1;
|
|
57
|
-
if (!Number.isSafeInteger(next) || receiverClock(p.epoch, fail) !== next)
|
|
58
|
-
fail('receiver epoch not next ' + p.place);
|
|
59
|
-
}
|
|
60
|
-
};
|
|
61
|
-
assertCurrent();
|
|
62
|
-
cancelled(signal);
|
|
63
|
-
const receipts = structuredClone(typeof source === 'function' ? await source() : source);
|
|
64
|
-
cancelled(signal);
|
|
65
|
-
placeActReceiptsOf(encoded, receipts, trust.contract);
|
|
66
|
-
const files = { 'context.json': encoded, 'receipts.json': JSON.stringify(receipts) + '\n', 'originals.json': JSON.stringify(originals) + '\n' };
|
|
67
|
-
capacity(sizeOf(files));
|
|
68
|
-
assertCurrent();
|
|
69
|
-
cancelled(signal);
|
|
70
|
-
try {
|
|
71
|
-
persistence.publish(id, files);
|
|
72
|
-
}
|
|
73
|
-
catch (error) {
|
|
74
|
-
throw new ActCommitUnknown(id, error);
|
|
75
|
-
}
|
|
76
|
-
return { context: encoded, receipts, originals, identity: id, kind: 'landed' };
|
|
77
|
-
});
|
|
78
|
-
}
|
|
1
|
+
var R=Object.defineProperty;var r=(e,i)=>R(e,"name",{value:i,configurable:!0});import{library3_readPlaceActContext as E,library3_verifyPlaceActContext as J,library3_placeActReceiptsOf as S}from"../vendor/runtime.js";import{requireEffects as U}from"./read-only.js";import{BoundRefusal as I}from"./refusals.js";import{ActCommitUnknown as _}from"./commit-result.js";import{assertHostNotCancelled as h,receiverClock as N,placeRegionOf as z}from"./host-controls.js";import{ActCommitUnknown as M}from"./commit-result.js";const n=r(e=>{throw new I("host/act","REFUSE\xB7place act "+e)},"fail"),j=r(e=>JSON.stringify([e.namespace,e.snapshot,e.epoch,e.prefix,e.head,e.policies]),"rootBytes");async function G(e,i,a,o,p,f){U("place act commitment"),h(f),(!o||!Number.isSafeInteger(o.acts)||o.acts<1||!Number.isSafeInteger(o.bytes)||o.bytes<1)&&n("missing storage budget");const m=E(e,a.contract.budget),l=a.contract.digest(e),k=m.places.map(y=>z(y.place));return p.exclusive(k,async()=>{h(f);const y=p.result(l,a,o);if(y)return y.context!==e&&n("replay bytes differ"),typeof i!="function"&&S(e,i,a.historical(e)),{...y,identity:l,kind:"once"};const P=J(e,a.contract),b=m.places.map(t=>t.records),v=r(t=>{const s=p.inventory(o);s.bytes+t>o.bytes&&n("publication byte budget"),s.names.length>=o.acts&&n("publication act budget")},"capacity"),C=r(t=>Object.values(t).reduce((s,c)=>s+new TextEncoder().encode(c).length,0),"sizeOf");v(C({"context.json":e,"originals.json":JSON.stringify(b)+`
|
|
2
|
+
`}));const w=r(()=>{const t=a.current();j(t.root)!==j(P.dependencies)&&n("authority changed before publication"),new Set(t.heads.map(c=>c.place)).size!==t.heads.length&&n("ambiguous receiver heads");const s=p.heads(a,o);for(const c of m.places){const g=s.find(x=>x.place===c.place),d=t.heads.find(x=>x.place===c.place);(!g||!d||g.identity!==d.identity||g.epoch!==d.epoch)&&n("receiver snapshot is not committed head "+c.place),d.identity!==c.previous&&n("receiver head moved "+c.place);const O=N(d.epoch,n)+1;(!Number.isSafeInteger(O)||N(c.epoch,n)!==O)&&n("receiver epoch not next "+c.place)}},"assertCurrent");w(),h(f);const u=structuredClone(typeof i=="function"?await i():i);h(f),S(e,u,a.contract);const A={"context.json":e,"receipts.json":JSON.stringify(u)+`
|
|
3
|
+
`,"originals.json":JSON.stringify(b)+`
|
|
4
|
+
`};v(C(A)),w(),h(f);try{p.publish(l,A)}catch(t){throw new _(l,t)}return{context:e,receipts:u,originals:b,identity:l,kind:"landed"}})}r(G,"transactPlaceAct");export{M as PlaceActCommitUnknown,G as transactPlaceAct};
|
|
@@ -1,124 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
import { foldClaims, isConfig, fieldOf, parsedLine as parse } from "../fold/claims.js";
|
|
7
|
-
import { signatureEraOf as eraOf } from "./signature-era.js";
|
|
8
|
-
import { authorityFor } from "../fold/signers.js";
|
|
9
|
-
import { verifyBytes } from "./adapters/keys/ed25519.js";
|
|
10
|
-
import { verifiesOwnerLine } from "../land/sign.js";
|
|
11
|
-
import { placeActHeads } from "./ports/place-act.js";
|
|
12
|
-
const fail = (why) => { throw Error('REFUSE·clock selection ' + why); };
|
|
13
|
-
const digest = (s) => 'sha256:' + createHash('sha256').update(s).digest('hex');
|
|
14
|
-
const text = (s) => typeof s === 'string' && s.length > 0;
|
|
15
|
-
const clock = (s) => { if (typeof s !== 'string' || !/^(0|[1-9][0-9]*)$/.test(s) || !Number.isSafeInteger(Number(s)))
|
|
16
|
-
fail('unknown clock'); return Number(s); };
|
|
17
|
-
// Exact-byte parsing returns frozen values. Retain only this pure syntax verdict;
|
|
18
|
-
// history, signatures, authority windows, clocks and protected rereads stay fresh.
|
|
19
|
-
const canonicalValues = new WeakSet();
|
|
20
|
-
const f = (line) => { const got = parse(line); if (got.kind !== 'fact')
|
|
21
|
-
return fail('noncanonical history'); if (!canonicalValues.has(got.value)) {
|
|
22
|
-
if (canonical(got.value.fields, got.value.version) !== line)
|
|
23
|
-
fail('noncanonical history');
|
|
24
|
-
canonicalValues.add(got.value);
|
|
25
|
-
} return got.value.fields; };
|
|
26
|
-
/** Root chooses selector and anchors/resources from its authenticated standing.
|
|
27
|
-
* Selection must be ROOT signed; a world's signature grants no host capability. */
|
|
28
|
-
export function hostClockSelection(input) {
|
|
29
|
-
const b = input.resources;
|
|
30
|
-
if (!b || Object.keys(b).sort().join(',') !== 'bytes,lines,places' || Object.values(b).some(n => !Number.isSafeInteger(n) || n < 1))
|
|
31
|
-
fail('missing input resources');
|
|
32
|
-
const inherited = input.inherited;
|
|
33
|
-
if (!inherited?.clock || Object.keys(inherited.clock).sort().join(',') !== 'bytes,placements,policies,proofs,records,signers' || !inherited.storage || Object.keys(inherited.storage).sort().join(',') !== 'acts,bytes' || [...Object.values(inherited.clock), ...Object.values(inherited.storage)].some(n => !Number.isSafeInteger(n) || n < 1))
|
|
34
|
-
fail('missing inherited resource authority');
|
|
35
|
-
if (input.history.length + input.legacyOriginals.length > b.lines)
|
|
36
|
-
fail('input line budget');
|
|
37
|
-
let bytes = 0;
|
|
38
|
-
for (const line of [...input.history, ...input.legacyOriginals]) {
|
|
39
|
-
if (typeof line !== 'string' || line.length > b.bytes || (bytes += Buffer.byteLength(line)) > b.bytes)
|
|
40
|
-
fail('input byte budget');
|
|
41
|
-
}
|
|
42
|
-
const snapshots = new Map();
|
|
43
|
-
for (const original of input.history) {
|
|
44
|
-
const epoch = clock(f(original).epoch ?? fail('history clock absent'));
|
|
45
|
-
let authority = snapshots.get(epoch);
|
|
46
|
-
if (!authority) {
|
|
47
|
-
const before = input.history.filter(l => !isConfig(l) || clock(f(l).epoch ?? fail('history clock absent')) <= epoch);
|
|
48
|
-
authority = authorityFor(before, input.anchor, eraOf(foldClaims(before.filter(l => fieldOf(l, 'scope').startsWith('wire/'))).standing).admitted);
|
|
49
|
-
snapshots.set(epoch, authority);
|
|
50
|
-
}
|
|
51
|
-
if (authority.of(original).kind !== 'admitted')
|
|
52
|
-
fail('history not authenticated at admission');
|
|
53
|
-
}
|
|
54
|
-
const live = foldClaims(input.history.filter(isConfig)).standing.filter(l => fieldOf(l, 'value') !== 'withdraw');
|
|
55
|
-
const ids = live.filter(l => { const p = f(l); return p.scope === input.profileSelector && p.measure === 'id'; });
|
|
56
|
-
if (ids.length !== 1 || f(ids[0]).value !== PLACE_ACT_CONTEXT || f(ids[0]).role !== 'writes' || f(ids[0]).form !== 'alphabet' || f(ids[0]).by !== input.anchor.id)
|
|
57
|
-
fail('missing/ambiguous clock profile id');
|
|
58
|
-
const rows = live.filter(l => { const p = f(l); return p.scope === input.selector && p.measure === 'text'; });
|
|
59
|
-
if (rows.length !== 1)
|
|
60
|
-
fail('missing/ambiguous Root selector');
|
|
61
|
-
const line = rows[0], fields = f(line);
|
|
62
|
-
if (fields.by !== input.anchor.id || fields.role !== 'writes' || fields.form !== 'alphabet' || fields.value !== 'lock' || !verifiesOwnerLine(line, input.anchor.publicKey, input.algorithms))
|
|
63
|
-
fail('selector is not Root signed');
|
|
64
|
-
if (!fields.about || fields.about.length > b.bytes)
|
|
65
|
-
fail('missing selector body');
|
|
66
|
-
let selection;
|
|
67
|
-
try {
|
|
68
|
-
selection = JSON.parse(fields.about);
|
|
69
|
-
}
|
|
70
|
-
catch {
|
|
71
|
-
return fail('selector JSON');
|
|
72
|
-
}
|
|
73
|
-
if (!selection || Object.keys(selection).sort().join(',') !== 'budget,digestAlgorithm,initial,namespace,profile,receiptScope,receiptSigner,regionFamily,storageBudget' || selection.profile !== PLACE_ACT_CONTEXT || selection.digestAlgorithm !== 'sha256' || !text(selection.namespace) || !text(selection.regionFamily) || !text(selection.receiptSigner) || !text(selection.receiptScope) || !Array.isArray(selection.initial) || !selection.initial.length || selection.initial.length > b.places)
|
|
74
|
-
fail('unsupported selector shape');
|
|
75
|
-
if (JSON.stringify(selection) !== fields.about)
|
|
76
|
-
fail('noncanonical selector JSON');
|
|
77
|
-
if (!selection.budget || Object.keys(selection.budget).sort().join(',') !== 'bytes,placements,policies,proofs,records,signers' || Object.values(selection.budget).some(n => !Number.isSafeInteger(n) || n < 1) || !selection.storageBudget || Object.keys(selection.storageBudget).sort().join(',') !== 'acts,bytes' || Object.values(selection.storageBudget).some(n => !Number.isSafeInteger(n) || n < 1))
|
|
78
|
-
fail('missing selected resources');
|
|
79
|
-
for (const name of ['bytes', 'records', 'placements', 'policies', 'proofs', 'signers'])
|
|
80
|
-
if (selection.budget[name] > inherited.clock[name])
|
|
81
|
-
fail('clock resource exceeds inherited ' + name);
|
|
82
|
-
for (const name of ['acts', 'bytes'])
|
|
83
|
-
if (selection.storageBudget[name] > inherited.storage[name])
|
|
84
|
-
fail('storage resource exceeds inherited ' + name);
|
|
85
|
-
if (selection.budget.bytes > b.bytes || selection.storageBudget.bytes > b.bytes || selection.budget.records > b.lines || selection.budget.placements > b.places)
|
|
86
|
-
fail('selected resources exceed input authority');
|
|
87
|
-
const wire = wireAt(live.map(f), Number.MAX_SAFE_INTEGER);
|
|
88
|
-
if (!wire || !wire.digests.has(selection.digestAlgorithm))
|
|
89
|
-
fail('digest algorithm not declared');
|
|
90
|
-
const authority = authorityFor(input.history, input.anchor, input.algorithms);
|
|
91
|
-
if (!input.history.includes(input.authorityCheckpoint) || !isConfig(input.authorityCheckpoint))
|
|
92
|
-
fail('missing authenticated Root authority checkpoint');
|
|
93
|
-
const checkpointEpoch = clock(f(input.authorityCheckpoint).epoch ?? fail('Root authority clock absent'));
|
|
94
|
-
if (snapshots.get(checkpointEpoch)?.of(input.authorityCheckpoint).kind !== 'admitted')
|
|
95
|
-
fail('Root checkpoint not admitted at original epoch');
|
|
96
|
-
const epoch = clock(f(input.authorityCheckpoint).epoch ?? fail('Root authority clock absent'));
|
|
97
|
-
if (input.history.filter(isConfig).some(l => clock(f(l).epoch ?? fail('history clock absent')) > epoch))
|
|
98
|
-
fail('authority checkpoint precedes Root configuration');
|
|
99
|
-
const prefix = digest(input.history.join('\n') + '\n'), head = digest(live.join('\n') + '\n');
|
|
100
|
-
const policies = [...new Set(live.map(digest))].sort();
|
|
101
|
-
if (policies.length > selection.budget.policies)
|
|
102
|
-
fail('actual dependency budget');
|
|
103
|
-
const root = { namespace: selection.namespace, snapshot: digest(JSON.stringify([prefix, head, String(epoch)])), epoch: String(epoch), prefix, head, policies };
|
|
104
|
-
const initialHeads = selection.initial.map(i => { if (!i || !i.receiver || !i.origin || !text(i.receiver.identity) || !text(i.origin.prefix) || !text(i.place))
|
|
105
|
-
fail('unknown initial namespace'); const parts = i.place.split('/'); if (i.place !== '.' && (parts.length < 2 || parts.at(-1) !== 'TARGET.bound' || parts.some(s => s === '' || s === '.' || s === '..')))
|
|
106
|
-
fail('unknown initial namespace'); clock(i.receiver.epoch); clock(i.origin.epoch); return { place: i.place, identity: i.receiver.identity, epoch: i.receiver.epoch }; });
|
|
107
|
-
if (new Set(initialHeads.map(h => h.place)).size !== initialHeads.length)
|
|
108
|
-
fail('duplicate namespace');
|
|
109
|
-
const legacy = new Set(input.legacyOriginals.map(l => digest(signedBytes(f(l)))));
|
|
110
|
-
let heads = [];
|
|
111
|
-
const contract = { budget: selection.budget, root, signers: authority.admitted, places: initialHeads.map(h => h.place), regionFamily: selection.regionFamily, receiptSigner: selection.receiptSigner, receiptScope: selection.receiptScope, digest,
|
|
112
|
-
verifiesRootContext: c => JSON.stringify(c) === JSON.stringify(root),
|
|
113
|
-
verifiesNamespaceAdmission: p => { if (p === '.')
|
|
114
|
-
return true; const parts = p.split('/'); if (parts.length < 2 || parts.pop() !== 'TARGET.bound' || parts.some(s => s === '' || s === '.' || s === '..'))
|
|
115
|
-
return false; const n = parts.join('/'), rows = live.filter(l => f(l).scope === selection.regionFamily + '/' + n); if (rows.length !== 1)
|
|
116
|
-
return false; const v = f(rows[0]); return v.role === 'writes' && v.form === 'alphabet' && v.measure === 'coordinates' && v.value === n + '/**'; },
|
|
117
|
-
verifiesNewLocalPrefix: (p, prefix, epoch, originals) => { const h = heads.find(h => h.place === p), i = selection.initial.find(i => i.place === p); if (!h || !i || originals.some(l => legacy.has(digest(signedBytes(f(l))))))
|
|
118
|
-
return false; return h.identity === i.receiver.identity ? prefix === i.origin.prefix && epoch === i.origin.epoch : prefix === h.identity && clock(epoch) === clock(h.epoch) + 1; },
|
|
119
|
-
verifiesOriginal: (l, s) => verifiesOwnerLine(l, s.publicKey, input.algorithms),
|
|
120
|
-
verifiesProof: (text, signature, s) => verifyBytes(text, s.publicKey, signature, input.algorithms), };
|
|
121
|
-
heads = input.authenticatedReceiverHeads ?? placeActHeads(input.store, initialHeads, { contract, historical: input.historical }, selection.storageBudget);
|
|
122
|
-
const trust = { contract, initialHeads, current: () => { const fresh = hostClockSelection({ ...input, ...input.readCurrent(), authenticatedReceiverHeads: undefined }); return { root: fresh.trust.contract.root, heads: placeActHeads(input.store, fresh.trust.initialHeads, fresh.trust, fresh.selection.storageBudget) }; }, historical: input.historical };
|
|
123
|
-
return { selection, trust };
|
|
124
|
-
}
|
|
1
|
+
var U=Object.defineProperty;var l=(t,s)=>U(t,"name",{value:s,configurable:!0});import{createHash as V}from"node:crypto";import{library3_PLACE_ACT_CONTEXT as _}from"../vendor/runtime.js";import{library11_canonical as $,library11_signedBytes as F,library11_wireAt as q}from"../vendor/runtime.js";import{foldClaims as J,isConfig as S,fieldOf as H,parsedLine as D}from"../fold/claims.js";import{signatureEraOf as Q}from"./signature-era.js";import{authorityFor as I}from"../fold/signers.js";import{verifyBytes as Y}from"./adapters/keys/ed25519.js";import{verifiesOwnerLine as L}from"../land/sign.js";import{placeActHeads as P}from"./ports/place-act.js";const i=l(t=>{throw Error("REFUSE\xB7clock selection "+t)},"fail"),y=l(t=>"sha256:"+V("sha256").update(t).digest("hex"),"digest"),m=l(t=>typeof t=="string"&&t.length>0,"text"),h=l(t=>((typeof t!="string"||!/^(0|[1-9][0-9]*)$/.test(t)||!Number.isSafeInteger(Number(t)))&&i("unknown clock"),Number(t)),"clock"),G=new WeakSet,c=l(t=>{const s=D(t);return s.kind!=="fact"?i("noncanonical history"):(G.has(s.value)||($(s.value.fields,s.value.version)!==t&&i("noncanonical history"),G.add(s.value)),s.value.fields)},"f");function Z(t){const s=t.resources;(!s||Object.keys(s).sort().join(",")!=="bytes,lines,places"||Object.values(s).some(e=>!Number.isSafeInteger(e)||e<1))&&i("missing input resources");const f=t.inherited;(!f?.clock||Object.keys(f.clock).sort().join(",")!=="bytes,placements,policies,proofs,records,signers"||!f.storage||Object.keys(f.storage).sort().join(",")!=="acts,bytes"||[...Object.values(f.clock),...Object.values(f.storage)].some(e=>!Number.isSafeInteger(e)||e<1))&&i("missing inherited resource authority"),t.history.length+t.legacyOriginals.length>s.lines&&i("input line budget");let K=0;for(const e of[...t.history,...t.legacyOriginals])(typeof e!="string"||e.length>s.bytes||(K+=Buffer.byteLength(e))>s.bytes)&&i("input byte budget");const O=new Map;for(const e of t.history){const r=h(c(e).epoch??i("history clock absent"));let a=O.get(r);if(!a){const p=t.history.filter(n=>!S(n)||h(c(n).epoch??i("history clock absent"))<=r);a=I(p,t.anchor,Q(J(p.filter(n=>H(n,"scope").startsWith("wire/"))).standing).admitted),O.set(r,a)}a.of(e).kind!=="admitted"&&i("history not authenticated at admission")}const u=J(t.history.filter(S)).standing.filter(e=>H(e,"value")!=="withdraw"),b=u.filter(e=>{const r=c(e);return r.scope===t.profileSelector&&r.measure==="id"});(b.length!==1||c(b[0]).value!==_||c(b[0]).role!=="writes"||c(b[0]).form!=="alphabet"||c(b[0]).by!==t.anchor.id)&&i("missing/ambiguous clock profile id");const j=u.filter(e=>{const r=c(e);return r.scope===t.selector&&r.measure==="text"});j.length!==1&&i("missing/ambiguous Root selector");const N=j[0],d=c(N);(d.by!==t.anchor.id||d.role!=="writes"||d.form!=="alphabet"||d.value!=="lock"||!L(N,t.anchor.publicKey,t.algorithms))&&i("selector is not Root signed"),(!d.about||d.about.length>s.bytes)&&i("missing selector body");let o;try{o=JSON.parse(d.about)}catch{return i("selector JSON")}(!o||Object.keys(o).sort().join(",")!=="budget,digestAlgorithm,initial,namespace,profile,receiptScope,receiptSigner,regionFamily,storageBudget"||o.profile!==_||o.digestAlgorithm!=="sha256"||!m(o.namespace)||!m(o.regionFamily)||!m(o.receiptSigner)||!m(o.receiptScope)||!Array.isArray(o.initial)||!o.initial.length||o.initial.length>s.places)&&i("unsupported selector shape"),JSON.stringify(o)!==d.about&&i("noncanonical selector JSON"),(!o.budget||Object.keys(o.budget).sort().join(",")!=="bytes,placements,policies,proofs,records,signers"||Object.values(o.budget).some(e=>!Number.isSafeInteger(e)||e<1)||!o.storageBudget||Object.keys(o.storageBudget).sort().join(",")!=="acts,bytes"||Object.values(o.storageBudget).some(e=>!Number.isSafeInteger(e)||e<1))&&i("missing selected resources");for(const e of["bytes","records","placements","policies","proofs","signers"])o.budget[e]>f.clock[e]&&i("clock resource exceeds inherited "+e);for(const e of["acts","bytes"])o.storageBudget[e]>f.storage[e]&&i("storage resource exceeds inherited "+e);(o.budget.bytes>s.bytes||o.storageBudget.bytes>s.bytes||o.budget.records>s.lines||o.budget.placements>s.places)&&i("selected resources exceed input authority");const A=q(u.map(c),Number.MAX_SAFE_INTEGER);(!A||!A.digests.has(o.digestAlgorithm))&&i("digest algorithm not declared");const X=I(t.history,t.anchor,t.algorithms);(!t.history.includes(t.authorityCheckpoint)||!S(t.authorityCheckpoint))&&i("missing authenticated Root authority checkpoint");const M=h(c(t.authorityCheckpoint).epoch??i("Root authority clock absent"));O.get(M)?.of(t.authorityCheckpoint).kind!=="admitted"&&i("Root checkpoint not admitted at original epoch");const w=h(c(t.authorityCheckpoint).epoch??i("Root authority clock absent"));t.history.filter(S).some(e=>h(c(e).epoch??i("history clock absent"))>w)&&i("authority checkpoint precedes Root configuration");const C=y(t.history.join(`
|
|
2
|
+
`)+`
|
|
3
|
+
`),E=y(u.join(`
|
|
4
|
+
`)+`
|
|
5
|
+
`),R=[...new Set(u.map(y))].sort();R.length>o.budget.policies&&i("actual dependency budget");const B={namespace:o.namespace,snapshot:y(JSON.stringify([C,E,String(w)])),epoch:String(w),prefix:C,head:E,policies:R},k=o.initial.map(e=>{(!e||!e.receiver||!e.origin||!m(e.receiver.identity)||!m(e.origin.prefix)||!m(e.place))&&i("unknown initial namespace");const r=e.place.split("/");return e.place!=="."&&(r.length<2||r.at(-1)!=="TARGET.bound"||r.some(a=>a===""||a==="."||a===".."))&&i("unknown initial namespace"),h(e.receiver.epoch),h(e.origin.epoch),{place:e.place,identity:e.receiver.identity,epoch:e.receiver.epoch}});new Set(k.map(e=>e.place)).size!==k.length&&i("duplicate namespace");const W=new Set(t.legacyOriginals.map(e=>y(F(c(e)))));let x=[];const T={budget:o.budget,root:B,signers:X.admitted,places:k.map(e=>e.place),regionFamily:o.regionFamily,receiptSigner:o.receiptSigner,receiptScope:o.receiptScope,digest:y,verifiesRootContext:l(e=>JSON.stringify(e)===JSON.stringify(B),"verifiesRootContext"),verifiesNamespaceAdmission:l(e=>{if(e===".")return!0;const r=e.split("/");if(r.length<2||r.pop()!=="TARGET.bound"||r.some(g=>g===""||g==="."||g===".."))return!1;const a=r.join("/"),p=u.filter(g=>c(g).scope===o.regionFamily+"/"+a);if(p.length!==1)return!1;const n=c(p[0]);return n.role==="writes"&&n.form==="alphabet"&&n.measure==="coordinates"&&n.value===a+"/**"},"verifiesNamespaceAdmission"),verifiesNewLocalPrefix:l((e,r,a,p)=>{const n=x.find(v=>v.place===e),g=o.initial.find(v=>v.place===e);return!n||!g||p.some(v=>W.has(y(F(c(v)))))?!1:n.identity===g.receiver.identity?r===g.origin.prefix&&a===g.origin.epoch:r===n.identity&&h(a)===h(n.epoch)+1},"verifiesNewLocalPrefix"),verifiesOriginal:l((e,r)=>L(e,r.publicKey,t.algorithms),"verifiesOriginal"),verifiesProof:l((e,r,a)=>Y(e,a.publicKey,r,t.algorithms),"verifiesProof")};x=t.authenticatedReceiverHeads??P(t.store,k,{contract:T,historical:t.historical},o.storageBudget);const z={contract:T,initialHeads:k,current:l(()=>{const e=Z({...t,...t.readCurrent(),authenticatedReceiverHeads:void 0});return{root:e.trust.contract.root,heads:P(t.store,e.trust.initialHeads,e.trust,e.selection.storageBudget)}},"current"),historical:t.historical};return{selection:o,trust:z}}l(Z,"hostClockSelection");export{Z as hostClockSelection};
|