@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,101 +1 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { matches, parse } from '@lapxo/topos/wire';
|
|
3
|
-
const fields = (line) => {
|
|
4
|
-
const got = parse(line);
|
|
5
|
-
return got.kind === 'fact' ? got.value.fields : {};
|
|
6
|
-
};
|
|
7
|
-
const f = (line, name) => fields(line)[name] ?? '';
|
|
8
|
-
const words = (value) => [...new Set(value.split('|').filter(Boolean))];
|
|
9
|
-
const active = (line) => f(line, 'value') !== 'withdraw';
|
|
10
|
-
const declaration = (line) => active(line) && f(line, 'role') === 'writes' && f(line, 'form') === 'alphabet' && f(line, 'measure') === 'id';
|
|
11
|
-
/** Preserve actual fold faults; none gets a release category from its spelling. */
|
|
12
|
-
export function releaseFaults(fold) {
|
|
13
|
-
return [
|
|
14
|
-
...fold.forks.map((one) => ({ kind: 'fork', evidence: [one.key, ...one.lines] })),
|
|
15
|
-
...fold.refused.map((line) => ({ kind: 'refused', evidence: [line] })),
|
|
16
|
-
...fold.grey.map((line) => ({ kind: 'grey', evidence: [line] })),
|
|
17
|
-
...fold.orphans.map((line) => ({ kind: 'orphan', evidence: [line] })),
|
|
18
|
-
...(fold.second.verdict === 'forks' ? [{ kind: 'second-fork', evidence: [fold.second.verdict] }] : []),
|
|
19
|
-
];
|
|
20
|
-
}
|
|
21
|
-
/** Select declared obligations, never categories inferred from their names or paths. */
|
|
22
|
-
export function releasePolicy(input) {
|
|
23
|
-
const policy = [...new Set(input.standing.filter((line) => f(line, 'scope') === 'release/blocks' && declaration(line)))];
|
|
24
|
-
const debt = [...new Set([...input.demands, ...input.ceilings])];
|
|
25
|
-
const gateLines = input.standing.filter(line => active(line) && f(line, 'role') === 'demands' && f(line, 'form') === 'alphabet' && f(line, 'measure') === 'verdict');
|
|
26
|
-
const gates = gateLines.map(line => verdictDemand(fields(line), input.verdicts ?? []));
|
|
27
|
-
const base = { snapshot: input.snapshot, policy, debt, gates };
|
|
28
|
-
if (!policy.length)
|
|
29
|
-
return { ...base, status: 'absent', categories: [], unresolved: [] };
|
|
30
|
-
const values = new Set(policy.map((line) => [...words(f(line, 'value'))].sort().join('|')));
|
|
31
|
-
const unresolved = [];
|
|
32
|
-
for (const fault of input.faults ?? []) {
|
|
33
|
-
if (fault.obligation === undefined || !debt.includes(fault.obligation))
|
|
34
|
-
unresolved.push(`unclassified ${fault.kind}: ${fault.evidence.join(' | ')}`);
|
|
35
|
-
}
|
|
36
|
-
if (values.size !== 1)
|
|
37
|
-
unresolved.push('release/blocks has conflicting standing values');
|
|
38
|
-
const labels = words(f(policy[0], 'value'));
|
|
39
|
-
if (!labels.length)
|
|
40
|
-
unresolved.push('release/blocks selects no category');
|
|
41
|
-
const categories = labels.map((name) => {
|
|
42
|
-
const links = [...new Set(input.standing.filter((line) => f(line, 'scope') === `release/category/${name}` && declaration(line)))];
|
|
43
|
-
if (!links.length)
|
|
44
|
-
unresolved.push(`release/category/${name} has no admitted link`);
|
|
45
|
-
if (new Set(links.map((line) => [...words(f(line, 'value'))].sort().join('|'))).size > 1)
|
|
46
|
-
unresolved.push(`release/category/${name} has conflicting standing values`);
|
|
47
|
-
const selected = new Set();
|
|
48
|
-
for (const selector of words(f(links[0] ?? '', 'value'))) {
|
|
49
|
-
const met = debt.filter((line) => matches(selector, f(line, 'scope')));
|
|
50
|
-
if (!met.length)
|
|
51
|
-
unresolved.push(`release/category/${name} selector ${selector} names no obligation`);
|
|
52
|
-
met.forEach((line) => selected.add(line));
|
|
53
|
-
}
|
|
54
|
-
if (!selected.size)
|
|
55
|
-
unresolved.push(`release/category/${name} selects no obligation`);
|
|
56
|
-
const failures = [];
|
|
57
|
-
for (const line of selected) {
|
|
58
|
-
for (const fault of input.faults ?? [])
|
|
59
|
-
if (fault.obligation === line)
|
|
60
|
-
failures.push({ line, reason: fault.kind, evidence: [...fault.evidence] });
|
|
61
|
-
if (input.demands.includes(line)) {
|
|
62
|
-
const gate = gateLines.includes(line) ? verdictDemand(fields(line), input.verdicts ?? []) : undefined;
|
|
63
|
-
if (gate) {
|
|
64
|
-
if (gate.status !== 'met')
|
|
65
|
-
failures.push({ line, reason: gate.status, evidence: gate.evidence.map(e => `${e.coordinate}=${e.value}`) });
|
|
66
|
-
continue;
|
|
67
|
-
}
|
|
68
|
-
if (!input.paid.includes(line))
|
|
69
|
-
failures.push({ line, reason: 'missing', evidence: [] });
|
|
70
|
-
continue;
|
|
71
|
-
}
|
|
72
|
-
const scope = f(line, 'scope');
|
|
73
|
-
const over = input.readings.over.filter((one) => one.ceiling === scope);
|
|
74
|
-
if (over.length && input.ceilings.filter((one) => f(one, 'scope') === scope).length !== 1)
|
|
75
|
-
unresolved.push(`ceiling evidence for ${scope} does not identify one obligation`);
|
|
76
|
-
if (over.length)
|
|
77
|
-
failures.push({ line, reason: 'outside', evidence: over.map((one) => `${one.side} ${one.question} ${one.got}`) });
|
|
78
|
-
if (input.readings.unread.includes(line))
|
|
79
|
-
failures.push({ line, reason: 'unread', evidence: [] });
|
|
80
|
-
if (input.readings.vacuous.includes(line))
|
|
81
|
-
failures.push({ line, reason: 'vacuous', evidence: [] });
|
|
82
|
-
if (!input.readings.read.includes(line) && !input.readings.unread.includes(line) && !input.readings.vacuous.includes(line)) {
|
|
83
|
-
unresolved.push(`ceiling ${scope} has no result in this fold`);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
return { name, links, selected: [...selected], failures };
|
|
87
|
-
});
|
|
88
|
-
return { ...base, categories, unresolved: [...new Set(unresolved)], status: unresolved.length ? 'incomplete' : categories.some((one) => one.failures.length) ? 'blocked' : 'ready' };
|
|
89
|
-
}
|
|
90
|
-
/** Existing fold output can show the policy without a new view or a release action. */
|
|
91
|
-
export function releasePolicyLines(result) {
|
|
92
|
-
if (result === undefined)
|
|
93
|
-
return [];
|
|
94
|
-
const gates = (result.gates ?? []).map(g => `GATE ${g.scope} ${g.status} · requires=${g.required.join('|')} · ${g.evidence.map(e => `${e.coordinate}=${e.value}`).join(' | ') || g.reason || 'no evidence'}`);
|
|
95
|
-
return [
|
|
96
|
-
...gates,
|
|
97
|
-
`RELEASE policy ${result.status} · fold ${result.snapshot.fold} · instrument ${result.snapshot.instrument}`,
|
|
98
|
-
...result.unresolved.map((one) => `UNRESOLVED release · ${one}`),
|
|
99
|
-
...result.categories.flatMap((one) => one.failures.map((failure) => `BLOCK ${one.name} · ${f(failure.line, 'scope')} · ${failure.reason}${failure.evidence.length ? ` · ${failure.evidence.join(' | ')}` : ''}`)),
|
|
100
|
-
];
|
|
101
|
-
}
|
|
1
|
+
var L=Object.defineProperty;var d=(e,o)=>L(e,"name",{value:o,configurable:!0});import{library0_verdictDemand as y}from"../vendor/runtime.js";import{library11_matches as q,library11_parse as x}from"../vendor/runtime.js";const p=d(e=>{const o=x(e);return o.kind==="fact"?o.value.fields:{}},"fields"),i=d((e,o)=>p(e)[o]??"","f"),h=d(e=>[...new Set(e.split("|").filter(Boolean))],"words"),w=d(e=>i(e,"value")!=="withdraw","active"),S=d(e=>w(e)&&i(e,"role")==="writes"&&i(e,"form")==="alphabet"&&i(e,"measure")==="id","declaration");function A(e){return[...e.forks.map(o=>({kind:"fork",evidence:[o.key,...o.lines]})),...e.refused.map(o=>({kind:"refused",evidence:[o]})),...e.grey.map(o=>({kind:"grey",evidence:[o]})),...e.orphans.map(o=>({kind:"orphan",evidence:[o]})),...e.second.verdict==="forks"?[{kind:"second-fork",evidence:[e.second.verdict]}]:[]]}d(A,"releaseFaults");function B(e){const o=[...new Set(e.standing.filter(s=>i(s,"scope")==="release/blocks"&&S(s)))],t=[...new Set([...e.demands,...e.ceilings])],r=e.standing.filter(s=>w(s)&&i(s,"role")==="demands"&&i(s,"form")==="alphabet"&&i(s,"measure")==="verdict"),E=r.map(s=>y(p(s),e.verdicts??[])),m={snapshot:e.snapshot,policy:o,debt:t,gates:E};if(!o.length)return{...m,status:"absent",categories:[],unresolved:[]};const j=new Set(o.map(s=>[...h(i(s,"value"))].sort().join("|"))),c=[];for(const s of e.faults??[])(s.obligation===void 0||!t.includes(s.obligation))&&c.push(`unclassified ${s.kind}: ${s.evidence.join(" | ")}`);j.size!==1&&c.push("release/blocks has conflicting standing values");const $=h(i(o[0],"value"));$.length||c.push("release/blocks selects no category");const b=$.map(s=>{const g=[...new Set(e.standing.filter(n=>i(n,"scope")===`release/category/${s}`&&S(n)))];g.length||c.push(`release/category/${s} has no admitted link`),new Set(g.map(n=>[...h(i(n,"value"))].sort().join("|"))).size>1&&c.push(`release/category/${s} has conflicting standing values`);const v=new Set;for(const n of h(i(g[0]??"","value"))){const f=t.filter(u=>q(n,i(u,"scope")));f.length||c.push(`release/category/${s} selector ${n} names no obligation`),f.forEach(u=>v.add(u))}v.size||c.push(`release/category/${s} selects no obligation`);const l=[];for(const n of v){for(const a of e.faults??[])a.obligation===n&&l.push({line:n,reason:a.kind,evidence:[...a.evidence]});if(e.demands.includes(n)){const a=r.includes(n)?y(p(n),e.verdicts??[]):void 0;if(a){a.status!=="met"&&l.push({line:n,reason:a.status,evidence:a.evidence.map(k=>`${k.coordinate}=${k.value}`)});continue}e.paid.includes(n)||l.push({line:n,reason:"missing",evidence:[]});continue}const f=i(n,"scope"),u=e.readings.over.filter(a=>a.ceiling===f);u.length&&e.ceilings.filter(a=>i(a,"scope")===f).length!==1&&c.push(`ceiling evidence for ${f} does not identify one obligation`),u.length&&l.push({line:n,reason:"outside",evidence:u.map(a=>`${a.side} ${a.question} ${a.got}`)}),e.readings.unread.includes(n)&&l.push({line:n,reason:"unread",evidence:[]}),e.readings.vacuous.includes(n)&&l.push({line:n,reason:"vacuous",evidence:[]}),!e.readings.read.includes(n)&&!e.readings.unread.includes(n)&&!e.readings.vacuous.includes(n)&&c.push(`ceiling ${f} has no result in this fold`)}return{name:s,links:g,selected:[...v],failures:l}});return{...m,categories:b,unresolved:[...new Set(c)],status:c.length?"incomplete":b.some(s=>s.failures.length)?"blocked":"ready"}}d(B,"releasePolicy");function O(e){return e===void 0?[]:[...(e.gates??[]).map(t=>`GATE ${t.scope} ${t.status} \xB7 requires=${t.required.join("|")} \xB7 ${t.evidence.map(r=>`${r.coordinate}=${r.value}`).join(" | ")||t.reason||"no evidence"}`),`RELEASE policy ${e.status} \xB7 fold ${e.snapshot.fold} \xB7 instrument ${e.snapshot.instrument}`,...e.unresolved.map(t=>`UNRESOLVED release \xB7 ${t}`),...e.categories.flatMap(t=>t.failures.map(r=>`BLOCK ${t.name} \xB7 ${i(r.line,"scope")} \xB7 ${r.reason}${r.evidence.length?` \xB7 ${r.evidence.join(" | ")}`:""}`))]}d(O,"releasePolicyLines");export{A as releaseFaults,B as releasePolicy,O as releasePolicyLines};
|
package/dist/fold/resolved.js
CHANGED
|
@@ -1,145 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
import { writerFor } from "./signers.js";
|
|
8
|
-
import { viewsOf } from "./views.js";
|
|
9
|
-
import { zoomed } from "./zoom.js";
|
|
10
|
-
import { ledgerLines, storeAt } from "../land/ledger.js";
|
|
11
|
-
import { sourced } from "../land/vouched.js";
|
|
12
|
-
import { entriesIn, observeFile, observeText } from "../observe/files.js";
|
|
13
|
-
export const bytesOnly = (line) => {
|
|
14
|
-
const got = parse(line);
|
|
15
|
-
// Authenticated evidence is delivered verbatim. A shortened observation is
|
|
16
|
-
// a different signed message, even when it describes the same input.
|
|
17
|
-
if (got.kind === 'fact' && got.value.fields.sig)
|
|
18
|
-
return line;
|
|
19
|
-
return got.kind === 'fact' && fieldOf(line, 'measure') === 'observed' ? canonical({ ...got.value.fields, value: fieldOf(line, 'at').replace(/^.*:/, '').slice(0, 16) }) : line;
|
|
20
|
-
};
|
|
21
|
-
const held = new WeakMap();
|
|
22
|
-
/**
|
|
23
|
-
* Every receipt of a place, @8: the bytes of what it observed that a reading ran over, those readings, the verdicts its
|
|
24
|
-
* paid demands were taken with, and at the root the digest of each place's own receipts. The attest is none of them:
|
|
25
|
-
* it stands in the root lock and the release, naming the root these lines resolve to. The fold keeps the set in the
|
|
26
|
-
* root's store under the digest of its bytes, which every line that resolves it names, and what a place with no reader
|
|
27
|
-
* carries is read back from there, never from a file the place ships.
|
|
28
|
-
*/
|
|
29
|
-
export function receiptsOf(fold) {
|
|
30
|
-
const kept = held.get(fold);
|
|
31
|
-
if (kept !== undefined)
|
|
32
|
-
return kept;
|
|
33
|
-
if (!fold.observed.length && carriesOnly(fold.root, fold.store))
|
|
34
|
-
return held.set(fold, [...new Set(carriedIn(fold.store).flatMap((file) => (observeText(file) ?? '').split('\n').filter(isWire)))]).get(fold);
|
|
35
|
-
const under = fold.under ?? '';
|
|
36
|
-
const shape = [...viewsOf(fold.standing).values()].flatMap((view) => ('regions' in view && view.regions.some((one) => one.name === 'receipts') ? [view.shape] : []))[0] ?? '';
|
|
37
|
-
const closed = under || !shape ? [] : entriesIn(fold.root).filter((entry) => entry.dir && observeText(join(fold.root, entry.name, shape)) !== undefined).map((entry) => `${entry.name}/`).sort();
|
|
38
|
-
const own = (place) => place.startsWith(under) && !closed.some((one) => place.startsWith(one)) && (!shape || !place.endsWith(shape));
|
|
39
|
-
const mine = new Set(fold.observed.filter((line) => fieldOf(line, 'measure') === 'observed' && own(fieldOf(line, 'scope')))
|
|
40
|
-
.map((line) => `${fieldOf(line, 'by')} ${fieldOf(line, 'at')}`));
|
|
41
|
-
const ran = [...new Set(fold.observed.filter((line) => fieldOf(line, 'measure') !== 'observed'
|
|
42
|
-
&& mine.has(`${fieldOf(line, 'by')} ${fieldOf(line, 'at')}`)))];
|
|
43
|
-
const ranAt = new Set(ran.map((line) => `${fieldOf(line, 'by')} ${fieldOf(line, 'at')}`));
|
|
44
|
-
const cones = new Set(fold.observed.filter((line) => {
|
|
45
|
-
if (fieldOf(line, 'measure') !== 'observed')
|
|
46
|
-
return false;
|
|
47
|
-
const at = fieldOf(line, 'at'), by = fieldOf(line, 'by');
|
|
48
|
-
// A physical input witnesses an owned reading's base, without becoming
|
|
49
|
-
// another location of its result. Even a foreign input belongs in that
|
|
50
|
-
// reading's portable carrier; its own child place is not the reader.
|
|
51
|
-
if (at.startsWith('witness:'))
|
|
52
|
-
return ranAt.has(`${by} place:${at.slice('witness:'.length)}`);
|
|
53
|
-
return own(fieldOf(line, 'scope')) && ranAt.has(`${by} ${at}`);
|
|
54
|
-
}).map(bytesOnly));
|
|
55
|
-
const paid = ledgerLines(fold.store, 'judge').filter((line) => fold.paid.some((demand) => fieldOf(demand, 'scope') === fieldOf(line, 'scope')
|
|
56
|
-
&& !(closed.length > 0 && fieldOf(demand, 'needs').split('|').filter(Boolean).length > 0
|
|
57
|
-
&& fieldOf(demand, 'needs').split('|').filter(Boolean).every((need) => closed.some((one) => need.startsWith(one))))));
|
|
58
|
-
const named = closed.map((place) => {
|
|
59
|
-
const digest = bytesDigest(fold.store, observeFile(join(fold.root, place, shape)) ?? new Uint8Array());
|
|
60
|
-
return canonical({ scope: `${sourced(fold.standing)}/${place}${shape}`, role: 'writes', form: 'alphabet', measure: 'digest', value: digest, by: writerFor(fold.standing, 'fold') ?? '', at: `place:${digest}` });
|
|
61
|
-
});
|
|
62
|
-
const place = under.replace(/\/$/, '');
|
|
63
|
-
const lines = [...new Set([...named, ...[...cones].sort(), ...[...ran].sort(), ...paid, ...(fold.receiptHistory ?? [])])]
|
|
64
|
-
.map((line) => (place && !fieldOf(line, 'sig') ? zoomed(line, place) : line));
|
|
65
|
-
if (!lines.length) {
|
|
66
|
-
const shipped = (observeText(join(fold.root, under, RECEIPTS)) ?? '').split('\n').filter(isWire);
|
|
67
|
-
const carried = carriedFrom(fold.store, shipped);
|
|
68
|
-
if (carried !== undefined && carried.length)
|
|
69
|
-
return held.set(fold, carried).get(fold);
|
|
70
|
-
}
|
|
71
|
-
held.set(fold, lines);
|
|
72
|
-
keepCarried(fold.store, lines);
|
|
73
|
-
return lines;
|
|
74
|
-
}
|
|
75
|
-
export function keepCarried(store, lines, from) {
|
|
76
|
-
const text = lines.map((line) => `${line}\n`).join('');
|
|
77
|
-
const digest = createHash('sha256').update(text).digest('hex');
|
|
78
|
-
const at = storeAt(store, 'cas', 'carried', digest);
|
|
79
|
-
if (existsSync(at)) {
|
|
80
|
-
verifiedCarried(at, digest);
|
|
81
|
-
}
|
|
82
|
-
else {
|
|
83
|
-
if (readOnly())
|
|
84
|
-
return `sha256:${digest}`;
|
|
85
|
-
mkdirSync(dirname(at), { recursive: true });
|
|
86
|
-
const src = from === undefined ? '' : storeAt(from, 'cas', 'carried', digest);
|
|
87
|
-
if (src && existsSync(src)) {
|
|
88
|
-
verifiedCarried(src, digest);
|
|
89
|
-
try {
|
|
90
|
-
linkSync(src, at);
|
|
91
|
-
return `sha256:${digest}`;
|
|
92
|
-
}
|
|
93
|
-
catch {
|
|
94
|
-
// Cross-device stores still keep the authenticated bytes below.
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
writeFileSync(`${at}.${process.pid}`, text);
|
|
98
|
-
renameSync(`${at}.${process.pid}`, at);
|
|
99
|
-
}
|
|
100
|
-
return `sha256:${digest}`;
|
|
101
|
-
}
|
|
102
|
-
/**
|
|
103
|
-
* What a copy of a place reads back of its receipts: the lines it shipped when they are the whole set, or, when they
|
|
104
|
-
* name a root at the digest of its bytes, the set the store keeps there; a root the store does not keep is no set, and
|
|
105
|
-
* the caller refuses rather than read the lines that only name it.
|
|
106
|
-
*/
|
|
107
|
-
export function carriedFrom(store, shipped) {
|
|
108
|
-
// Signed receipts inside the observed set are evidence, not its framing.
|
|
109
|
-
const headerOf = (line) => fieldOf(line, 'scope') === 'receipts' && fieldOf(line, 'measure') === 'digest' && fieldOf(line, 'by') === 'bound' && !fieldOf(line, 'sig');
|
|
110
|
-
const named = shipped.find(headerOf);
|
|
111
|
-
if (named === undefined)
|
|
112
|
-
return shipped;
|
|
113
|
-
// Resolution 8 may precede its authenticated summary in the same public file.
|
|
114
|
-
// It is evidence only if its exact bytes meet the summary's carrier digest.
|
|
115
|
-
for (let i = 1; i < shipped.length; i += 1) {
|
|
116
|
-
const header = shipped[i];
|
|
117
|
-
if (!headerOf(header))
|
|
118
|
-
continue;
|
|
119
|
-
const digest = fieldOf(header, 'at').replace(/^place:sha256:/, '');
|
|
120
|
-
const body = shipped.slice(0, i);
|
|
121
|
-
if (/^[0-9a-f]{64}$/.test(digest) && createHash('sha256').update(body.map(line => `${line}\n`).join('')).digest('hex') === digest)
|
|
122
|
-
return body;
|
|
123
|
-
}
|
|
124
|
-
if (shipped.indexOf(named) > 0)
|
|
125
|
-
throw Error('REFUSE·receipt public carrier bytes mismatch; a cached carrier cannot replace supplied evidence');
|
|
126
|
-
const hex = fieldOf(named, 'at').replace(/^place:(?:sha256:)?/, '');
|
|
127
|
-
const text = /^[0-9a-f]{64}$/.test(hex) ? verifiedCarried(storeAt(store, 'cas', 'carried', hex), hex) : undefined;
|
|
128
|
-
return text === undefined ? undefined : text.split('\n').filter(isWire);
|
|
129
|
-
}
|
|
130
|
-
export const carriedIn = (store) => ((dir) => (existsSync(dir)
|
|
131
|
-
? readdirSync(dir).filter((name) => /^[0-9a-f]{64}$/.test(name)).sort().map((name) => {
|
|
132
|
-
const at = join(dir, name);
|
|
133
|
-
verifiedCarried(at, name);
|
|
134
|
-
return at;
|
|
135
|
-
}) : []))(storeAt(store, 'cas', 'carried'));
|
|
136
|
-
/** Authenticate the existing SHA-256 receipt carrier before interpreting any lines. */
|
|
137
|
-
function verifiedCarried(at, expected) {
|
|
138
|
-
const bytes = observeFile(at);
|
|
139
|
-
if (bytes === undefined)
|
|
140
|
-
return undefined;
|
|
141
|
-
const actual = createHash('sha256').update(bytes).digest('hex');
|
|
142
|
-
if (actual !== expected)
|
|
143
|
-
throw Error(`REFUSE·receipt carried bytes mismatch · expected sha256:${expected} · got sha256:${actual}`);
|
|
144
|
-
return new TextDecoder('utf-8', { fatal: true }).decode(bytes);
|
|
145
|
-
}
|
|
1
|
+
var A=Object.defineProperty;var u=(e,s)=>A(e,"name",{value:s,configurable:!0});import{readOnly as C}from"../host/read-only.js";import{createHash as w,dirname as I,existsSync as x,join as $,linkSync as M,mkdirSync as R,readdirSync as T,renameSync as U,writeFileSync as B}from"../host/io.js";import{library11_canonical as k,library11_parse as D}from"../vendor/runtime.js";import{RECEIPTS as H,fieldOf as r,isWire as S}from"./claims.js";import{bytesDigest as _}from"./digests.js";import{carriesOnly as z}from"./observed.js";import{writerFor as L}from"./signers.js";import{viewsOf as P}from"./views.js";import{zoomed as q}from"./zoom.js";import{ledgerLines as G,storeAt as b}from"../land/ledger.js";import{sourced as J}from"../land/vouched.js";import{entriesIn as K,observeFile as W,observeText as E}from"../observe/files.js";const N=u(e=>{const s=D(e);return s.kind==="fact"&&s.value.fields.sig?e:s.kind==="fact"&&r(e,"measure")==="observed"?k({...s.value.fields,value:r(e,"at").replace(/^.*:/,"").slice(0,16)}):e},"bytesOnly"),y=new WeakMap;function de(e){const s=y.get(e);if(s!==void 0)return s;if(!e.observed.length&&z(e.root,e.store))return y.set(e,[...new Set(X(e.store).flatMap(t=>(E(t)??"").split(`
|
|
2
|
+
`).filter(S)))]).get(e);const n=e.under??"",a=[...P(e.standing).values()].flatMap(t=>"regions"in t&&t.regions.some(o=>o.name==="receipts")?[t.shape]:[])[0]??"",c=n||!a?[]:K(e.root).filter(t=>t.dir&&E($(e.root,t.name,a))!==void 0).map(t=>`${t.name}/`).sort(),p=u(t=>t.startsWith(n)&&!c.some(o=>t.startsWith(o))&&(!a||!t.endsWith(a)),"own"),i=new Set(e.observed.filter(t=>r(t,"measure")==="observed"&&p(r(t,"scope"))).map(t=>`${r(t,"by")} ${r(t,"at")}`)),d=[...new Set(e.observed.filter(t=>r(t,"measure")!=="observed"&&i.has(`${r(t,"by")} ${r(t,"at")}`)))],m=new Set(d.map(t=>`${r(t,"by")} ${r(t,"at")}`)),f=new Set(e.observed.filter(t=>{if(r(t,"measure")!=="observed")return!1;const o=r(t,"at"),g=r(t,"by");return o.startsWith("witness:")?m.has(`${g} place:${o.slice(8)}`):p(r(t,"scope"))&&m.has(`${g} ${o}`)}).map(N)),v=G(e.store,"judge").filter(t=>e.paid.some(o=>r(o,"scope")===r(t,"scope")&&!(c.length>0&&r(o,"needs").split("|").filter(Boolean).length>0&&r(o,"needs").split("|").filter(Boolean).every(g=>c.some(j=>g.startsWith(j)))))),F=c.map(t=>{const o=_(e.store,W($(e.root,t,a))??new Uint8Array);return k({scope:`${J(e.standing)}/${t}${a}`,role:"writes",form:"alphabet",measure:"digest",value:o,by:L(e.standing,"fold")??"",at:`place:${o}`})}),O=n.replace(/\/$/,""),h=[...new Set([...F,...[...f].sort(),...[...d].sort(),...v,...e.receiptHistory??[]])].map(t=>O&&!r(t,"sig")?q(t,O):t);if(!h.length){const t=(E($(e.root,n,H))??"").split(`
|
|
3
|
+
`).filter(S),o=V(e.store,t);if(o!==void 0&&o.length)return y.set(e,o).get(e)}return y.set(e,h),Q(e.store,h),h}u(de,"receiptsOf");function Q(e,s,n){const a=s.map(i=>`${i}
|
|
4
|
+
`).join(""),c=w("sha256").update(a).digest("hex"),p=b(e,"cas","carried",c);if(x(p))l(p,c);else{if(C())return`sha256:${c}`;R(I(p),{recursive:!0});const i=n===void 0?"":b(n,"cas","carried",c);if(i&&x(i)){l(i,c);try{return M(i,p),`sha256:${c}`}catch{}}B(`${p}.${process.pid}`,a),U(`${p}.${process.pid}`,p)}return`sha256:${c}`}u(Q,"keepCarried");function V(e,s){const n=u(i=>r(i,"scope")==="receipts"&&r(i,"measure")==="digest"&&r(i,"by")==="bound"&&!r(i,"sig"),"headerOf"),a=s.find(n);if(a===void 0)return s;for(let i=1;i<s.length;i+=1){const d=s[i];if(!n(d))continue;const m=r(d,"at").replace(/^place:sha256:/,""),f=s.slice(0,i);if(/^[0-9a-f]{64}$/.test(m)&&w("sha256").update(f.map(v=>`${v}
|
|
5
|
+
`).join("")).digest("hex")===m)return f}if(s.indexOf(a)>0)throw Error("REFUSE\xB7receipt public carrier bytes mismatch; a cached carrier cannot replace supplied evidence");const c=r(a,"at").replace(/^place:(?:sha256:)?/,""),p=/^[0-9a-f]{64}$/.test(c)?l(b(e,"cas","carried",c),c):void 0;return p===void 0?void 0:p.split(`
|
|
6
|
+
`).filter(S)}u(V,"carriedFrom");const X=u(e=>(s=>x(s)?T(s).filter(n=>/^[0-9a-f]{64}$/.test(n)).sort().map(n=>{const a=$(s,n);return l(a,n),a}):[])(b(e,"cas","carried")),"carriedIn");function l(e,s){const n=W(e);if(n===void 0)return;const a=w("sha256").update(n).digest("hex");if(a!==s)throw Error(`REFUSE\xB7receipt carried bytes mismatch \xB7 expected sha256:${s} \xB7 got sha256:${a}`);return new TextDecoder("utf-8",{fatal:!0}).decode(n)}u(l,"verifiedCarried");export{N as bytesOnly,V as carriedFrom,X as carriedIn,Q as keepCarried,de as receiptsOf};
|
package/dist/fold/roles.js
CHANGED
|
@@ -1,59 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import { namesAt, roleAt } from "./wire.js";
|
|
4
|
-
import { lockStanding } from "./keys.js";
|
|
5
|
-
import { placesIn } from "./places.js";
|
|
6
|
-
import { ownLockOf } from "./signed.js";
|
|
7
|
-
import { observeText } from "../observe/files.js";
|
|
8
|
-
import { fieldOf, isWire } from "./claims.js";
|
|
9
|
-
/** A lock line that gives a coordinate its role: every walk of the tree reads it. */
|
|
10
|
-
export function isRoleLock(line) {
|
|
11
|
-
const got = parse(line);
|
|
12
|
-
return got.kind === 'fact' && roleClaimsOf([got.value.fields]).length > 0;
|
|
13
|
-
}
|
|
14
|
-
/** A lock the owner signs by digest and a capsule writes: its lines stand while the bytes are the ones that were signed. */
|
|
15
|
-
export function inheritedRoles(store) {
|
|
16
|
-
const root = dirname(store);
|
|
17
|
-
const claims = [];
|
|
18
|
-
const stale = [];
|
|
19
|
-
for (const line of lockStanding(store)) {
|
|
20
|
-
if (fieldOf(line, 'measure') !== 'role' || !fieldOf(line, 'scope').startsWith('roles/'))
|
|
21
|
-
continue;
|
|
22
|
-
const at = fieldOf(line, 'needs');
|
|
23
|
-
const held = at ? observeText(join(root, at)) : undefined;
|
|
24
|
-
const digest = held === undefined ? '' : `sha256:${createHash('sha256').update(held).digest('hex')}`;
|
|
25
|
-
if (held === undefined || digest !== fieldOf(line, 'restsOn')) {
|
|
26
|
-
stale.push(fieldOf(line, 'scope'));
|
|
27
|
-
continue;
|
|
28
|
-
}
|
|
29
|
-
for (const one of held.split('\n').filter(isWire).map((row) => parse(row))) {
|
|
30
|
-
if (one.kind === 'fact')
|
|
31
|
-
claims.push(one.value.fields);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
return { claims: roleClaimsOf(claims), stale };
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* What each coordinate of the tree is: the capsule that knows a world writes the roles of that world, the owner signs the
|
|
38
|
-
* capsule's lock by digest, and this fold reads both. The instrument reads claims and never a name, and a coordinate no
|
|
39
|
-
* standing claim names is source. The steps a walk must not enter are read the same way: the claims that name a whole
|
|
40
|
-
* folder foreign or derived, as a set the walk can ask in one step instead of matching every claim at every step.
|
|
41
|
-
*/
|
|
42
|
-
export function stepsOutside(store) {
|
|
43
|
-
const own = roleClaimsOf(lockStanding(store)
|
|
44
|
-
.map((line) => parse(line))
|
|
45
|
-
.flatMap((got) => (got.kind === 'fact' ? [got.value.fields] : [])));
|
|
46
|
-
return new Set([...own, ...inheritedRoles(store).claims]
|
|
47
|
-
.filter((claim) => (claim.role === 'foreign' || claim.role === 'derived') && !claim.name.includes('/') && !claim.name.includes('*'))
|
|
48
|
-
.map((claim) => claim.name));
|
|
49
|
-
}
|
|
50
|
-
export function rolesOf(store) {
|
|
51
|
-
const fields = (lines) => lines.map((line) => parse(line)).flatMap((got) => (got.kind === 'fact' ? [got.value.fields] : []));
|
|
52
|
-
const claims = [...roleClaimsOf(fields(lockStanding(store))), ...inheritedRoles(store).claims];
|
|
53
|
-
const root = dirname(store);
|
|
54
|
-
const placed = new Map(placesIn(root).map((place) => [place, roleClaimsOf(fields(ownLockOf(root, place)))]));
|
|
55
|
-
return (coordinate) => {
|
|
56
|
-
const own = coordinate.includes('/') ? placed.get(coordinate.slice(0, coordinate.indexOf('/'))) ?? [] : [];
|
|
57
|
-
return roleAt(coordinate, own.some((claim) => namesAt(coordinate, claim.name)) ? own : claims);
|
|
58
|
-
};
|
|
59
|
-
}
|
|
1
|
+
var k=Object.defineProperty;var r=(n,o)=>k(n,"name",{value:o,configurable:!0});import{createHash as x,dirname as u,join as v}from"../host/io.js";import{library11_parse as c,library11_roleClaimsOf as a}from"../vendor/runtime.js";import{namesAt as g,roleAt as w}from"./wire.js";import{lockStanding as p}from"./keys.js";import{placesIn as b}from"./places.js";import{ownLockOf as M}from"./signed.js";import{observeText as y}from"../observe/files.js";import{fieldOf as l,isWire as A}from"./claims.js";function T(n){const o=c(n);return o.kind==="fact"&&a([o.value.fields]).length>0}r(T,"isRoleLock");function h(n){const o=u(n),e=[],f=[];for(const i of p(n)){if(l(i,"measure")!=="role"||!l(i,"scope").startsWith("roles/"))continue;const s=l(i,"needs"),t=s?y(v(o,s)):void 0,m=t===void 0?"":`sha256:${x("sha256").update(t).digest("hex")}`;if(t===void 0||m!==l(i,"restsOn")){f.push(l(i,"scope"));continue}for(const d of t.split(`
|
|
2
|
+
`).filter(A).map(O=>c(O)))d.kind==="fact"&&e.push(d.value.fields)}return{claims:a(e),stale:f}}r(h,"inheritedRoles");function $(n){const o=a(p(n).map(e=>c(e)).flatMap(e=>e.kind==="fact"?[e.value.fields]:[]));return new Set([...o,...h(n).claims].filter(e=>(e.role==="foreign"||e.role==="derived")&&!e.name.includes("/")&&!e.name.includes("*")).map(e=>e.name))}r($,"stepsOutside");function q(n){const o=r(s=>s.map(t=>c(t)).flatMap(t=>t.kind==="fact"?[t.value.fields]:[]),"fields"),e=[...a(o(p(n))),...h(n).claims],f=u(n),i=new Map(b(f).map(s=>[s,a(o(M(f,s)))]));return s=>{const t=s.includes("/")?i.get(s.slice(0,s.indexOf("/")))??[]:[];return w(s,t.some(m=>g(s,m.name))?t:e)}}r(q,"rolesOf");export{h as inheritedRoles,T as isRoleLock,q as rolesOf,$ as stepsOutside};
|
package/dist/fold/second.js
CHANGED
|
@@ -1,71 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import { ownLock } from "../observe/runner.js";
|
|
6
|
-
import { fieldOf } from "./claims.js";
|
|
7
|
-
import { keyOf, lockLines } from "./keys.js";
|
|
8
|
-
import { digestsOf, finerOf, regionsOf } from "./region.js";
|
|
9
|
-
import { said } from "./wire.js";
|
|
10
|
-
import { sha } from "../host/hash.js";
|
|
11
|
-
const asked = new Map();
|
|
12
|
-
function askedNow(store, rests) {
|
|
13
|
-
if (readOnly())
|
|
14
|
-
return undefined;
|
|
15
|
-
const root = dirname(store);
|
|
16
|
-
const key = `${root} ${rests}`;
|
|
17
|
-
if (asked.has(key))
|
|
18
|
-
return asked.get(key);
|
|
19
|
-
const argv = said(ownLock(), 'head/second');
|
|
20
|
-
const got = argv.length ? spawnSync(process.execPath, ['--disable-warning=ExperimentalWarning', '--disable-warning=MODULE_TYPELESS_PACKAGE_JSON',
|
|
21
|
-
resolve(root, argv[0]), ...argv.slice(1), root], { cwd: root, encoding: 'utf8', maxBuffer: 1 << 26 }) : undefined;
|
|
22
|
-
const line = got === undefined || got.status !== 0 || typeof got.stdout !== 'string' ? undefined : got.stdout.split('\n').find((one) => one.startsWith('VERIFY'));
|
|
23
|
-
const word = line === undefined ? undefined : line.slice('VERIFY'.length).trim().split(' ')[0];
|
|
24
|
-
const verdict = word === 'agrees' || word === 'forks' ? word : undefined;
|
|
25
|
-
asked.set(key, verdict);
|
|
26
|
-
return verdict;
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* The second head's word, read against this fold. It attests the digest of the lines it found standing and the digest
|
|
30
|
-
* of the lines of the ledger it folded, in whatever order a store landed them, so a clone that lands the same lines
|
|
31
|
-
* agrees; agreement is an encounter, disagreement a fork. A word about another lock is not read as this one's: the head
|
|
32
|
-
* bound's own lock names is asked now over the ledger as it stands, with no key, and what it says is read, never kept.
|
|
33
|
-
*/
|
|
34
|
-
export function secondHead(store, standing, admitted, owned = lockLines(store)) {
|
|
35
|
-
const head = keyOf(store, 'attest');
|
|
36
|
-
const said = head === undefined ? [] : ledgerLines(store, head).filter((line) => fieldOf(line, 'scope') === `${head}/target`);
|
|
37
|
-
const last = said.at(-1);
|
|
38
|
-
const lines = owned.filter((line) => /\bsig=/.test(line));
|
|
39
|
-
const rests = `sha256:${sha([...new Set(lines)].sort().join('\n'))}`;
|
|
40
|
-
const epoch = lines.reduce((most, line) => Math.max(most, Number(fieldOf(line, 'epoch')) || 0), 0);
|
|
41
|
-
const input = {
|
|
42
|
-
declared: head !== undefined,
|
|
43
|
-
expected: { set: lines.length ? rests : undefined, standing: `place:sha256:${sha([...new Set(standing)].sort().join('\n'))}`, epoch },
|
|
44
|
-
...(last ? { statement: { admitted: admitted(last), set: fieldOf(last, 'restsOn'), standing: fieldOf(last, 'at'), epoch: Number(fieldOf(last, 'epoch')) || 0 } } : {}),
|
|
45
|
-
priorDisagreement: said.some(line => fieldOf(line, 'value') === 'forks' && admitted(line)),
|
|
46
|
-
};
|
|
47
|
-
let result = snapshotVerdict(input);
|
|
48
|
-
if (result.verdict === 'stale' && last && lines.length) {
|
|
49
|
-
const now = askedNow(store, rests);
|
|
50
|
-
if (now !== undefined)
|
|
51
|
-
result = snapshotVerdict({ ...input, comparison: { admitted: true, set: rests, verdict: now, epoch } });
|
|
52
|
-
}
|
|
53
|
-
if (result.verdict !== 'forks' || head === undefined || last === undefined || fieldOf(last, 'restsOn') !== rests)
|
|
54
|
-
return result;
|
|
55
|
-
const theirs = new Map(ledgerLines(store, head).filter((line) => fieldOf(line, 'scope').startsWith(`${head}/region/`) && fieldOf(line, 'restsOn') === fieldOf(last, 'restsOn'))
|
|
56
|
-
.map((line) => [fieldOf(line, 'scope').slice(`${head}/region/`.length).replace(/^\.$/, ''), fieldOf(line, 'value')]));
|
|
57
|
-
if (!theirs.size)
|
|
58
|
-
return result;
|
|
59
|
-
const regions = regionsOf(standing, standing, []);
|
|
60
|
-
const [ours, finer] = [digestsOf(regions), finerOf(regions)];
|
|
61
|
-
const apart = [];
|
|
62
|
-
const descend = (region) => {
|
|
63
|
-
if (theirs.get(region) === ours.get(region))
|
|
64
|
-
return;
|
|
65
|
-
apart.push(region || '.');
|
|
66
|
-
for (const one of finer.get(region) ?? [])
|
|
67
|
-
descend(one);
|
|
68
|
-
};
|
|
69
|
-
descend('');
|
|
70
|
-
return { ...result, apart };
|
|
71
|
-
}
|
|
1
|
+
var y=Object.defineProperty;var m=(r,i)=>y(r,"name",{value:i,configurable:!0});import{readOnly as L}from"../host/read-only.js";import{snapshotVerdict as $}from"./evidence.js";import{dirname as M,resolve as N,spawnSync as P}from"../host/io.js";import{ledgerLines as E}from"../land/ledger.js";import{ownLock as V}from"../observe/runner.js";import{fieldOf as s}from"./claims.js";import{keyOf as W,lockLines as Y}from"./keys.js";import{digestsOf as _,finerOf as j,regionsOf as A}from"./region.js";import{said as D}from"./wire.js";import{sha as x}from"../host/hash.js";const g=new Map;function F(r,i){if(L())return;const d=M(r),u=`${d} ${i}`;if(g.has(u))return g.get(u);const t=D(V(),"head/second"),c=t.length?P(process.execPath,["--disable-warning=ExperimentalWarning","--disable-warning=MODULE_TYPELESS_PACKAGE_JSON",N(d,t[0]),...t.slice(1),d],{cwd:d,encoding:"utf8",maxBuffer:1<<26}):void 0,n=c===void 0||c.status!==0||typeof c.stdout!="string"?void 0:c.stdout.split(`
|
|
2
|
+
`).find(p=>p.startsWith("VERIFY")),o=n===void 0?void 0:n.slice(6).trim().split(" ")[0],f=o==="agrees"||o==="forks"?o:void 0;return g.set(u,f),f}m(F,"askedNow");function q(r,i,d,u=Y(r)){const t=W(r,"attest"),c=t===void 0?[]:E(r,t).filter(e=>s(e,"scope")===`${t}/target`),n=c.at(-1),o=u.filter(e=>/\bsig=/.test(e)),f=`sha256:${x([...new Set(o)].sort().join(`
|
|
3
|
+
`))}`,p=o.reduce((e,l)=>Math.max(e,Number(s(l,"epoch"))||0),0),h={declared:t!==void 0,expected:{set:o.length?f:void 0,standing:`place:sha256:${x([...new Set(i)].sort().join(`
|
|
4
|
+
`))}`,epoch:p},...n?{statement:{admitted:d(n),set:s(n,"restsOn"),standing:s(n,"at"),epoch:Number(s(n,"epoch"))||0}}:{},priorDisagreement:c.some(e=>s(e,"value")==="forks"&&d(e))};let a=$(h);if(a.verdict==="stale"&&n&&o.length){const e=F(r,f);e!==void 0&&(a=$({...h,comparison:{admitted:!0,set:f,verdict:e,epoch:p}}))}if(a.verdict!=="forks"||t===void 0||n===void 0||s(n,"restsOn")!==f)return a;const w=new Map(E(r,t).filter(e=>s(e,"scope").startsWith(`${t}/region/`)&&s(e,"restsOn")===s(n,"restsOn")).map(e=>[s(e,"scope").slice(`${t}/region/`.length).replace(/^\.$/,""),s(e,"value")]));if(!w.size)return a;const O=A(i,i,[]),[S,b]=[_(O),j(O)],k=[],v=m(e=>{if(w.get(e)!==S.get(e)){k.push(e||".");for(const l of b.get(e)??[])v(l)}},"descend");return v(""),{...a,apart:k}}m(q,"secondHead");export{q as secondHead};
|
package/dist/fold/shards.js
CHANGED
|
@@ -1,100 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
export
|
|
13
|
-
/**
|
|
14
|
-
* What a reader said is kept by region: the region a place lies in is the longest a reader's lock names that holds it,
|
|
15
|
-
* the stamps and digests it was observed at are lines of that region's shard, and what the reader answered for the
|
|
16
|
-
* region is one observation, stored under its reader's extension, the region, the digest of the region's places and
|
|
17
|
-
* the resolution it was read at. A fold opens the shards of the regions it reaches and reads each observation by its
|
|
18
|
-
* key: nothing is scanned, the same bytes are never read twice, and an observation found under its key is the reading.
|
|
19
|
-
*/
|
|
20
|
-
export function regionIn(regions, place) {
|
|
21
|
-
let best = '';
|
|
22
|
-
for (const region of regions)
|
|
23
|
-
if (region.length > best.length && (place === region || place.startsWith(`${region}/`)))
|
|
24
|
-
best = region;
|
|
25
|
-
return best;
|
|
26
|
-
}
|
|
27
|
-
const observationAt = (store, key) => storeAt(store, 'cas', 'observations', key);
|
|
28
|
-
export const keyOf = (by, region, pairs, resolution = '1') => sha(`${by}\n${region}\n${sha([...pairs].sort().join('\n'))}\n${resolution}`);
|
|
29
|
-
export const observed = (store, key) => existsSync(observationAt(store, key));
|
|
30
|
-
export function observation(store, key) {
|
|
31
|
-
return observeText(observationAt(store, key))?.split('\n').filter(isWire);
|
|
32
|
-
}
|
|
33
|
-
export function keepObservation(store, key, lines) {
|
|
34
|
-
const at = observationAt(store, key);
|
|
35
|
-
if (existsSync(at))
|
|
36
|
-
return;
|
|
37
|
-
mkdirSync(dirname(at), { recursive: true });
|
|
38
|
-
writeFileSync(`${at}.${process.pid}`, `${[...new Set(lines)].sort().join('\n')}\n`);
|
|
39
|
-
renameSync(`${at}.${process.pid}`, at);
|
|
40
|
-
}
|
|
41
|
-
export function opened(store, speaker, region, alive) {
|
|
42
|
-
const places = new Map();
|
|
43
|
-
const keys = new Map();
|
|
44
|
-
const pointers = new Map();
|
|
45
|
-
const lines = shardLines(store, speaker, region);
|
|
46
|
-
for (const line of lines) {
|
|
47
|
-
if (OBSERVED.test(line))
|
|
48
|
-
places.set(`${readerOf(line) ?? ''} ${fieldOf(line, 'scope')}`, { at: fieldOf(line, 'at'), line });
|
|
49
|
-
else if (line.includes(' measure=observation ')) {
|
|
50
|
-
keys.set(readerOf(line) ?? '', fieldOf(line, 'value'));
|
|
51
|
-
pointers.set(readerOf(line) ?? '', line);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
const live = [...lines.filter((line) => LEVEL.test(line)), ...[...places].filter(([name]) => alive.has(name.slice(0, name.indexOf(' ')))).map(([, one]) => one.line),
|
|
55
|
-
...[...pointers].filter(([by]) => alive.has(by)).map(([, line]) => line)];
|
|
56
|
-
if (lines.length > 2 * live.length + 500) {
|
|
57
|
-
const at = shardFile(store, speaker, region);
|
|
58
|
-
writeFileSync(`${at}.${process.pid}`, `${live.join('\n')}\n`);
|
|
59
|
-
renameSync(`${at}.${process.pid}`, at);
|
|
60
|
-
}
|
|
61
|
-
return { region, places, keys };
|
|
62
|
-
}
|
|
63
|
-
export const pointer = (speaker, by, region, key, pairs) => canonical({ scope: region || '.', role: 'writes', form: 'alphabet', measure: 'observation', value: key, by: `${speaker}:${by}`, at: `place:${sha([...pairs].sort().join('\n'))}` });
|
|
64
|
-
export function legacyOf(store, speaker, regions) {
|
|
65
|
-
if (!existsSync(writerFile(store, speaker)))
|
|
66
|
-
return undefined;
|
|
67
|
-
const latest = new Map();
|
|
68
|
-
const readings = new Map();
|
|
69
|
-
const level = new Map();
|
|
70
|
-
for (const line of ledgerLines(store, speaker)) {
|
|
71
|
-
if (OBSERVED.test(line))
|
|
72
|
-
latest.set(`${readerOf(line) ?? ''} ${fieldOf(line, 'scope')}`, line);
|
|
73
|
-
else if (LEVEL.test(line)) {
|
|
74
|
-
const region = regionIn(regions, fieldOf(line, 'scope').replace(/^(?:cost\/)?reader\//, ''));
|
|
75
|
-
level.set(region, [...(level.get(region) ?? []), line]);
|
|
76
|
-
}
|
|
77
|
-
else {
|
|
78
|
-
const key = `${readerOf(line) ?? ''} ${fieldOf(line, 'at')}`;
|
|
79
|
-
readings.set(key, [...(readings.get(key) ?? []), line]);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
const shards = new Map(level);
|
|
83
|
-
for (const line of latest.values()) {
|
|
84
|
-
const region = regionIn(regions, fieldOf(line, 'scope'));
|
|
85
|
-
shards.set(region, [...(shards.get(region) ?? []), line]);
|
|
86
|
-
}
|
|
87
|
-
for (const [region, lines] of shards)
|
|
88
|
-
landShard(store, speaker, region, lines);
|
|
89
|
-
return readings;
|
|
90
|
-
}
|
|
91
|
-
export function setAside(store, speaker) {
|
|
92
|
-
const at = writerFile(store, speaker);
|
|
93
|
-
if (!existsSync(at))
|
|
94
|
-
return;
|
|
95
|
-
const bytes = observeFile(at) ?? new Uint8Array();
|
|
96
|
-
const kept = blobAt(store, bytesDigest(store, bytes));
|
|
97
|
-
mkdirSync(dirname(kept), { recursive: true });
|
|
98
|
-
renameSync(at, kept);
|
|
99
|
-
process.stderr.write(`SHARDED ${speaker} · one file of ${bytes.length} bytes laid out by region · kept as ${bytesDigest(store, bytes)}\n`);
|
|
100
|
-
}
|
|
1
|
+
var O=Object.defineProperty;var c=(e,t)=>O(e,"name",{value:t,configurable:!0});import{dirname as x,existsSync as $,mkdirSync as v,renameSync as u,writeFileSync as y}from"../host/io.js";import{library11_canonical as A}from"../vendor/runtime.js";import{bytesDigest as g}from"./digests.js";import{blobAt as E,landShard as j,ledgerLines as D,shardFile as F,shardLines as L,storeAt as k,writerFile as h}from"../land/ledger.js";import{fieldOf as p,isWire as R}from"./claims.js";import{observeFile as V,observeText as W}from"../observe/files.js";const w=/ measure=observed /,S=/(?:^|\s)scope=(?:cost\/)?reader\//,d=c(e=>/(?:^|\s)by=reader:([0-9a-f]+)/.exec(e)?.[1],"readerOf"),z=c(e=>e.replace(/\/+$/,""),"trimmed");import{sha as m}from"../host/hash.js";import{sha as te}from"../host/hash.js";function M(e,t){let s="";for(const n of e)n.length>s.length&&(t===n||t.startsWith(`${n}/`))&&(s=n);return s}c(M,"regionIn");const b=c((e,t)=>k(e,"cas","observations",t),"observationAt"),G=c((e,t,s,n="1")=>m(`${e}
|
|
2
|
+
${t}
|
|
3
|
+
${m([...s].sort().join(`
|
|
4
|
+
`))}
|
|
5
|
+
${n}`),"keyOf"),J=c((e,t)=>$(b(e,t)),"observed");function K(e,t){return W(b(e,t))?.split(`
|
|
6
|
+
`).filter(R)}c(K,"observation");function N(e,t,s){const n=b(e,t);$(n)||(v(x(n),{recursive:!0}),y(`${n}.${process.pid}`,`${[...new Set(s)].sort().join(`
|
|
7
|
+
`)}
|
|
8
|
+
`),u(`${n}.${process.pid}`,n))}c(N,"keepObservation");function P(e,t,s,n){const a=new Map,f=new Map,l=new Map,r=L(e,t,s);for(const o of r)w.test(o)?a.set(`${d(o)??""} ${p(o,"scope")}`,{at:p(o,"at"),line:o}):o.includes(" measure=observation ")&&(f.set(d(o)??"",p(o,"value")),l.set(d(o)??"",o));const i=[...r.filter(o=>S.test(o)),...[...a].filter(([o])=>n.has(o.slice(0,o.indexOf(" ")))).map(([,o])=>o.line),...[...l].filter(([o])=>n.has(o)).map(([,o])=>o)];if(r.length>2*i.length+500){const o=F(e,t,s);y(`${o}.${process.pid}`,`${i.join(`
|
|
9
|
+
`)}
|
|
10
|
+
`),u(`${o}.${process.pid}`,o)}return{region:s,places:a,keys:f}}c(P,"opened");const Q=c((e,t,s,n,a)=>A({scope:s||".",role:"writes",form:"alphabet",measure:"observation",value:n,by:`${e}:${t}`,at:`place:${m([...a].sort().join(`
|
|
11
|
+
`))}`}),"pointer");function X(e,t,s){if(!$(h(e,t)))return;const n=new Map,a=new Map,f=new Map;for(const r of D(e,t))if(w.test(r))n.set(`${d(r)??""} ${p(r,"scope")}`,r);else if(S.test(r)){const i=M(s,p(r,"scope").replace(/^(?:cost\/)?reader\//,""));f.set(i,[...f.get(i)??[],r])}else{const i=`${d(r)??""} ${p(r,"at")}`;a.set(i,[...a.get(i)??[],r])}const l=new Map(f);for(const r of n.values()){const i=M(s,p(r,"scope"));l.set(i,[...l.get(i)??[],r])}for(const[r,i]of l)j(e,t,r,i);return a}c(X,"legacyOf");function Y(e,t){const s=h(e,t);if(!$(s))return;const n=V(s)??new Uint8Array,a=E(e,g(e,n));v(x(a),{recursive:!0}),u(s,a),process.stderr.write(`SHARDED ${t} \xB7 one file of ${n.length} bytes laid out by region \xB7 kept as ${g(e,n)}
|
|
12
|
+
`)}c(Y,"setAside");export{S as LEVEL,w as OBSERVED,N as keepObservation,G as keyOf,X as legacyOf,K as observation,J as observed,P as opened,Q as pointer,d as readerOf,M as regionIn,Y as setAside,te as sha,z as trimmed};
|