nervur 0.18.0 → 0.19.0
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/README.md +7 -7
- package/dist/being/index.d.ts +1 -0
- package/dist/being/index.js +1 -0
- package/dist/being/lent.d.ts +32 -0
- package/dist/being/lent.js +63 -0
- package/dist/being/types.js +1 -1
- package/dist/conformance/beings.d.ts +2 -1
- package/dist/conformance/beings.js +7 -2
- package/dist/conformance/index.d.ts +0 -1
- package/dist/conformance/index.js +8 -5
- package/dist/harbor/box.d.ts +121 -0
- package/dist/harbor/box.js +121 -0
- package/dist/harbor/core.d.ts +5 -5
- package/dist/harbor/core.js +73 -72
- package/dist/harbor/index.d.ts +3 -1
- package/dist/harbor/index.js +3 -0
- package/dist/harbor/memory.d.ts +8 -4
- package/dist/harbor/memory.js +43 -11
- package/dist/harbor/store.js +1 -1
- package/dist/vector/cases.d.ts +4 -3
- package/dist/vector/cases.js +33 -5
- package/dist/vector/world.d.ts +1 -0
- package/dist/vector/world.js +17 -6
- package/dist/ward/ground.d.ts +13 -7
- package/dist/ward/ground.js +29 -11
- package/dist/ward/heirs.js +4 -2
- package/dist/ward/index.d.ts +2 -1
- package/dist/ward/index.js +1 -0
- package/dist/ward/partition.js +2 -2
- package/dist/ward/seal.js +1 -1
- package/dist/ward/stance.d.ts +0 -5
- package/dist/ward/ward.d.ts +1 -1
- package/dist/ward/ward.js +62 -27
- package/package.json +7 -5
- package/src/being/index.ts +1 -0
- package/src/being/lent.ts +66 -0
- package/src/being/types.ts +1 -1
- package/src/conformance/beings.ts +8 -3
- package/src/conformance/index.ts +18 -15
- package/src/harbor/box.ts +131 -0
- package/src/harbor/core.ts +23 -22
- package/src/harbor/index.ts +4 -1
- package/src/harbor/memory.ts +52 -12
- package/src/harbor/store.ts +1 -1
- package/src/vector/cases.ts +37 -9
- package/src/vector/world.ts +18 -6
- package/src/ward/ground.ts +85 -103
- package/src/ward/heirs.ts +4 -2
- package/src/ward/index.ts +2 -1
- package/src/ward/partition.ts +2 -2
- package/src/ward/seal.ts +1 -1
- package/src/ward/stance.ts +1 -1
- package/src/ward/ward.ts +59 -27
package/src/ward/index.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
2
|
// nervur/ward — one function. Every ward is the same ward.
|
|
3
3
|
export { Ward } from './ward.ts';
|
|
4
|
-
export type { Ground, WardPointers,
|
|
4
|
+
export type { Ground, WardPointers, Memory } from './ground.ts';
|
|
5
|
+
export { BOX, OFFER, RETRACT, volatile } from './ground.ts';
|
|
5
6
|
export type { Partition, Heir, Bind, StandingKeys } from './partition.ts';
|
|
6
7
|
// The three bounds on what a partition may hold, for a kit that must keep
|
|
7
8
|
// the same ones and for a test that pins them.
|
package/src/ward/partition.ts
CHANGED
|
@@ -312,7 +312,7 @@ export const restoreRow = (p: Partition, row: string, value: Record<string, unkn
|
|
|
312
312
|
drop(p.beings ?? {}, row);
|
|
313
313
|
// Her bind goes with her: a being the store never kept has no relation
|
|
314
314
|
// anybody is standing on, so there is nothing to leave forward.
|
|
315
|
-
drop(
|
|
315
|
+
drop(p.bind ?? {}, row);
|
|
316
316
|
return;
|
|
317
317
|
}
|
|
318
318
|
// Behind the guard and never through it: a being's cells in a partition
|
|
@@ -326,7 +326,7 @@ export const restoreRow = (p: Partition, row: string, value: Record<string, unkn
|
|
|
326
326
|
for (const k of Object.keys(held)) drop(held, k);
|
|
327
327
|
for (const [k, v] of Object.entries(kept)) put(held, k, v);
|
|
328
328
|
};
|
|
329
|
-
into(
|
|
329
|
+
into(p.beings ?? {}, (value.cells ?? emptyCells()) as unknown as Record<string, unknown>);
|
|
330
330
|
};
|
|
331
331
|
|
|
332
332
|
// The partition back from its rows. A head that is absent is a partition
|
package/src/ward/seal.ts
CHANGED
|
@@ -54,7 +54,7 @@ export const SIZE = 1024 * 1024;
|
|
|
54
54
|
// designs and no separation at all: one secret would be doing two jobs with
|
|
55
55
|
// nothing said about it, and a second kit would have to reproduce a
|
|
56
56
|
// construction nobody named. HKDF-SHA-256 under a label is the separation
|
|
57
|
-
// said out loud, and it is what `
|
|
57
|
+
// said out loud, and it is what `quo/vectors/framing.json` pins.
|
|
58
58
|
//
|
|
59
59
|
// Bytes are key material and text is not. A seed handed in as bytes of the
|
|
60
60
|
// key length is taken as it stands, which is what a harbor mints; anything
|
package/src/ward/stance.ts
CHANGED
|
@@ -41,7 +41,7 @@ export type Inside = {
|
|
|
41
41
|
};
|
|
42
42
|
|
|
43
43
|
// An invitation as it travels: the far ward's pk, the heir pk, the heir's secret seed. Or just the ward, for its public being.
|
|
44
|
-
|
|
44
|
+
type SealedInvitation ={ ward: string; heir?: string; secret?: string };
|
|
45
45
|
|
|
46
46
|
// The three calls on `standings` share the object with the ids she takes, so
|
|
47
47
|
// a standing named after one of them would be unreachable: `standings.knock`
|
package/src/ward/ward.ts
CHANGED
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
// a stance built by the same code. Mints every key, seals every ask that
|
|
6
6
|
// leaves, opens every one that arrives.
|
|
7
7
|
import { silence, isSilence, unreached, isWord, word } from '../being/silence.ts';
|
|
8
|
-
import { OWNER } from '../being/types.ts';
|
|
9
|
-
import type { Asker, BeingLike, Cells, JsonObject, Reply, Stance, Wanted, Word } from '../being/types.ts';
|
|
10
|
-
import type
|
|
8
|
+
import { OWNER, isInvitation } from '../being/types.ts';
|
|
9
|
+
import type { Asker, BeingLike, Cells, Invitation, JsonObject, Reply, Stance, Wanted, Word } from '../being/types.ts';
|
|
10
|
+
import { BOX, OFFER, RETRACT, type Ground, type WardPointers } from './ground.ts';
|
|
11
11
|
import { at, drop, open, put, emptyBind, emptyCells, HEAD, MINTED, type Bind, type Partition, type StandingKeys } from './partition.ts';
|
|
12
12
|
import { Heirs } from './heirs.ts';
|
|
13
13
|
import { makeDoor, type Door } from './door.ts';
|
|
@@ -41,15 +41,48 @@ class Self implements BeingLike {
|
|
|
41
41
|
readonly door: WardPointers['door'];
|
|
42
42
|
readonly ask: WardPointers['ask'];
|
|
43
43
|
|
|
44
|
+
// Birth, in order: the ward as its own first being, the box taken, and
|
|
45
|
+
// only then every being the partition names constructed again. A being
|
|
46
|
+
// who takes what her box lends does it at her birth, so the box must be
|
|
47
|
+
// hers to ask before she is born, or a restart would be the one birth at
|
|
48
|
+
// which the device lends nothing.
|
|
44
49
|
static async boot(ground: Ground): Promise<Self> {
|
|
45
|
-
|
|
50
|
+
const w = new Self(ground, await wardKey(ground.seed));
|
|
51
|
+
await w.#takeBox();
|
|
52
|
+
w.#reborn();
|
|
53
|
+
return w;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// The device, taken as one standing under `BOX` by the ward's own being,
|
|
57
|
+
// once: a ward woken from its partition already holds it. A knock that is
|
|
58
|
+
// not answered leaves the ward up and lending nothing this run.
|
|
59
|
+
async #takeBox(): Promise<void> {
|
|
60
|
+
const inv = this.g.box;
|
|
61
|
+
const mine = this.doors.get(this.pk)?.stance;
|
|
62
|
+
if (!inv || !mine || mine.standings[BOX]) return;
|
|
63
|
+
const out = await mine.standings.knock(inv);
|
|
64
|
+
if (isSilence(out) || isWord(out)) return;
|
|
65
|
+
await mine.standings.take(BOX, inv);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// What this device lends this ward's beings: the box's being, asked to
|
|
69
|
+
// offer a name, answers the lent being's own invitation, and the taker knocks
|
|
70
|
+
// and takes it. The ward reads nothing in the value but that it is one.
|
|
71
|
+
async #lend(name: string, take: (inv: Invitation) => Promise<boolean>): Promise<boolean> {
|
|
72
|
+
const box = this.doors.get(this.pk)?.stance.standings[BOX];
|
|
73
|
+
if (!box) return false;
|
|
74
|
+
const inv = await box.ask(OFFER, { name });
|
|
75
|
+
if (!isInvitation(inv)) return false;
|
|
76
|
+
const took = await take(inv);
|
|
77
|
+
if (!took) await box.ask(RETRACT, { name, heir: inv.heir ?? null });
|
|
78
|
+
return took;
|
|
46
79
|
}
|
|
47
80
|
|
|
48
81
|
private constructor(ground: Ground, key: WardKey) {
|
|
49
82
|
this.g = ground;
|
|
50
83
|
this.key = key;
|
|
51
84
|
this.pk = key.pk;
|
|
52
|
-
this.p = open(ground.memory); // the partition: the ward's own state, and every being's row
|
|
85
|
+
this.p = open(ground.memory.rows); // the partition: the ward's own state, and every being's row
|
|
53
86
|
// Opening is itself a write: a memory nobody has written comes back with
|
|
54
87
|
// a version stamped on it and the ward's own tables under it. A ward that
|
|
55
88
|
// said nothing here would have every being of it kept and the head that
|
|
@@ -66,6 +99,23 @@ class Self implements BeingLike {
|
|
|
66
99
|
() => this.#keep(),
|
|
67
100
|
); // pointer one
|
|
68
101
|
this.#boot(this.pk, () => this); // the ward's ward is itself
|
|
102
|
+
// pointer two. the owner. the same answer every named asker gets, asker filled in as owner.
|
|
103
|
+
this.ask = async (method, args = {}) => {
|
|
104
|
+
try {
|
|
105
|
+
const out = await this.answer({ id: OWNER }, method, args as JsonObject);
|
|
106
|
+
// The same question the door asks, in the same place: after she has
|
|
107
|
+
// answered and before the owner holds the answer. Silence is what a
|
|
108
|
+
// failed ask says here, so a store that refused is silence, and the
|
|
109
|
+
// owner reads it as it reads every other ask that did not take.
|
|
110
|
+
if (!(await this.#keep().catch(() => false))) return silence;
|
|
111
|
+
return isSilence(out) || isWord(out) ? silence : out;
|
|
112
|
+
} catch {
|
|
113
|
+
return silence;
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
#reborn(): void {
|
|
69
119
|
// a restart is silent: every being in the cells is constructed again, unasked.
|
|
70
120
|
// A throw on a boot the owner asked for is that boot's error, and nothing
|
|
71
121
|
// half-lives. This boot nobody asked for, and there is nobody to hand an
|
|
@@ -85,20 +135,6 @@ class Self implements BeingLike {
|
|
|
85
135
|
/* she is not here this run. the ward is, and so is everyone else. */
|
|
86
136
|
}
|
|
87
137
|
}
|
|
88
|
-
// pointer two. the owner. the same answer every named asker gets, asker filled in as owner.
|
|
89
|
-
this.ask = async (method, args = {}) => {
|
|
90
|
-
try {
|
|
91
|
-
const out = await this.answer({ id: OWNER }, method, args as JsonObject);
|
|
92
|
-
// The same question the door asks, in the same place: after she has
|
|
93
|
-
// answered and before the owner holds the answer. Silence is what a
|
|
94
|
-
// failed ask says here, so a store that refused is silence, and the
|
|
95
|
-
// owner reads it as it reads every other ask that did not take.
|
|
96
|
-
if (!(await this.#keep().catch(() => false))) return silence;
|
|
97
|
-
return isSilence(out) || isWord(out) ? silence : out;
|
|
98
|
-
} catch {
|
|
99
|
-
return silence;
|
|
100
|
-
}
|
|
101
|
-
};
|
|
102
138
|
}
|
|
103
139
|
|
|
104
140
|
// ---- the ward as a being. asked only by its owners: the root, through
|
|
@@ -138,7 +174,7 @@ class Self implements BeingLike {
|
|
|
138
174
|
// because a harbor told only that something moved must keep all of it, and
|
|
139
175
|
// a being's row is the one part of a partition that grows without limit.
|
|
140
176
|
#wrote(row: string): void {
|
|
141
|
-
this.g.
|
|
177
|
+
this.g.memory.told(row);
|
|
142
178
|
}
|
|
143
179
|
|
|
144
180
|
// Whether what was written is kept, asked once at the end of an arrival
|
|
@@ -146,7 +182,7 @@ class Self implements BeingLike {
|
|
|
146
182
|
// refuse anything, so its silence here is yes: a ward driven with no store
|
|
147
183
|
// under it answers exactly as it did before a harbor could say no.
|
|
148
184
|
async #keep(): Promise<boolean> {
|
|
149
|
-
return this.g.
|
|
185
|
+
return this.g.memory.kept();
|
|
150
186
|
}
|
|
151
187
|
|
|
152
188
|
// The rows no door holds this run: beings whose class threw at birth or
|
|
@@ -249,11 +285,7 @@ class Self implements BeingLike {
|
|
|
249
285
|
// never came about takes her out again.
|
|
250
286
|
relate: async (k, id) => (await this.doors.get(k)?.stance.occupants.invite(id)) ?? null,
|
|
251
287
|
unmake: (k) => void this.#unboot(k),
|
|
252
|
-
|
|
253
|
-
// inside the harbor's own call and reads nothing in the value: which
|
|
254
|
-
// names there are, which ward may ask for one, and what becomes of one
|
|
255
|
-
// she did not take, is the harbor's and no word of the ward.
|
|
256
|
-
lend: async (name, take) => (await this.g.lend?.(name, take)) ?? false,
|
|
288
|
+
lend: (name, take) => this.#lend(name, take),
|
|
257
289
|
wrote: () => this.#wrote(key),
|
|
258
290
|
},
|
|
259
291
|
key,
|
|
@@ -294,7 +326,7 @@ class Self implements BeingLike {
|
|
|
294
326
|
// the reply opens, and whatever the being writes on either side of her
|
|
295
327
|
// own ask. A harbor may write those rows down; what it may not do is put
|
|
296
328
|
// the ward back to them.
|
|
297
|
-
const lower = this.g.
|
|
329
|
+
const lower = this.g.memory.during();
|
|
298
330
|
try {
|
|
299
331
|
return await this.#sent(bind, keys, method, args, wanted, row);
|
|
300
332
|
} finally {
|