@quo-systems/quo 0.2.15 → 0.2.17
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/GETTING_STARTED.md +128 -0
- package/README.md +38 -26
- package/dist/conformance/store.js +36 -10
- package/dist/harbor/core.js +12 -9
- package/dist/harbor/index.d.ts +2 -1
- package/dist/harbor/index.js +4 -1
- package/dist/harbor/memory.d.ts +1 -0
- package/dist/harbor/memory.js +7 -1
- package/dist/harbor/store.d.ts +10 -3
- package/dist/harbor/store.js +34 -5
- package/dist/ward/arithmetic.d.ts +4 -0
- package/dist/ward/arithmetic.js +82 -12
- package/dist/ward/ground.d.ts +1 -1
- package/dist/ward/partition.d.ts +4 -0
- package/dist/ward/partition.js +53 -0
- package/dist/ward/seal.js +1 -1
- package/dist/ward/ward.js +37 -23
- package/package.json +7 -7
- package/{SPEC.md → protocol/SPEC.md} +16 -4
- package/protocol/vectors/door.json +345 -0
- package/quo-kit.md +98 -15
- package/src/conformance/store.ts +37 -10
- package/src/harbor/core.ts +17 -10
- package/src/harbor/index.ts +4 -1
- package/src/harbor/memory.ts +7 -1
- package/src/harbor/store.ts +39 -7
- package/src/ward/arithmetic.ts +83 -14
- package/src/ward/ground.ts +11 -4
- package/src/ward/partition.ts +53 -0
- package/src/ward/seal.ts +1 -1
- package/src/ward/ward.ts +37 -23
- /package/{vectors → protocol/vectors}/arithmetic.json +0 -0
- /package/{vectors → protocol/vectors}/framing.json +0 -0
- /package/{vectors → protocol/vectors}/wire.json +0 -0
package/src/ward/ward.ts
CHANGED
|
@@ -8,7 +8,7 @@ import { silence, isSilence, unreached, isWord, word } from '../being/silence.ts
|
|
|
8
8
|
import { OWNER } from '../being/types.ts';
|
|
9
9
|
import type { Asker, BeingLike, Cells, JsonObject, Reply, Stance, Wanted, Word } from '../being/types.ts';
|
|
10
10
|
import type { Ground, WardPointers } from './ground.ts';
|
|
11
|
-
import { at, drop, open, put, emptyBind, emptyCells, MINTED, type Bind, type Partition, type StandingKeys } from './partition.ts';
|
|
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';
|
|
14
14
|
import { buildStance } from './stance.ts';
|
|
@@ -50,7 +50,13 @@ class Self implements BeingLike {
|
|
|
50
50
|
this.key = key;
|
|
51
51
|
this.pk = key.pk;
|
|
52
52
|
this.p = open(ground.memory); // the partition: the ward's own state, and every being's row
|
|
53
|
-
|
|
53
|
+
// Opening is itself a write: a memory nobody has written comes back with
|
|
54
|
+
// a version stamped on it and the ward's own tables under it. A ward that
|
|
55
|
+
// said nothing here would have every being of it kept and the head that
|
|
56
|
+
// says which version they are written under kept by nobody, so the next
|
|
57
|
+
// boot would read a partition of no version and refuse it.
|
|
58
|
+
this.#wrote(HEAD);
|
|
59
|
+
this.heirs = new Heirs(this.p, () => this.#wrote(HEAD));
|
|
54
60
|
this.door = makeDoor(key, this.heirs, this.doors, () => this.p.public, (n) => ground.random(n)); // pointer one
|
|
55
61
|
this.#boot(this.pk, () => this); // the ward's ward is itself
|
|
56
62
|
// a restart is silent: every being in the cells is constructed again, unasked.
|
|
@@ -103,7 +109,7 @@ class Self implements BeingLike {
|
|
|
103
109
|
unboot: (key) => this.#unboot(key),
|
|
104
110
|
setPublic: (key) => {
|
|
105
111
|
this.p.public = key;
|
|
106
|
-
this.#wrote();
|
|
112
|
+
this.#wrote(HEAD);
|
|
107
113
|
},
|
|
108
114
|
},
|
|
109
115
|
asker,
|
|
@@ -114,10 +120,13 @@ class Self implements BeingLike {
|
|
|
114
120
|
|
|
115
121
|
// ---- ward functions. on the object. no stance reaches them.
|
|
116
122
|
|
|
117
|
-
// The partition was written
|
|
118
|
-
//
|
|
119
|
-
|
|
120
|
-
|
|
123
|
+
// The partition was written, and which row of it: a being by her key, or
|
|
124
|
+
// the head. The harbor is told, and nothing more: what it does with the
|
|
125
|
+
// word is its own, and the ward never learns. Every write says its row,
|
|
126
|
+
// because a harbor told only that something moved must keep all of it, and
|
|
127
|
+
// a being's row is the one part of a partition that grows without limit.
|
|
128
|
+
#wrote(row: string): void {
|
|
129
|
+
this.g.wrote?.(row);
|
|
121
130
|
}
|
|
122
131
|
|
|
123
132
|
// The rows no door holds this run: beings whose class threw at birth or
|
|
@@ -151,7 +160,7 @@ class Self implements BeingLike {
|
|
|
151
160
|
}
|
|
152
161
|
if (!door) return null;
|
|
153
162
|
unguarded(door.cells).class = className; // so a restart finds her. the ward's key, written behind her guard
|
|
154
|
-
this.#wrote();
|
|
163
|
+
this.#wrote(key);
|
|
155
164
|
return door;
|
|
156
165
|
}
|
|
157
166
|
|
|
@@ -184,7 +193,8 @@ class Self implements BeingLike {
|
|
|
184
193
|
drop(this.p.beings, key);
|
|
185
194
|
drop(this.p.bind, key);
|
|
186
195
|
this.doors.delete(key);
|
|
187
|
-
this.#wrote();
|
|
196
|
+
this.#wrote(key); // she is gone, and her row goes with her
|
|
197
|
+
this.#wrote(HEAD); // her heirs were closed, and the public being may have been her
|
|
188
198
|
return [...occupants, ...standings];
|
|
189
199
|
}
|
|
190
200
|
|
|
@@ -196,7 +206,7 @@ class Self implements BeingLike {
|
|
|
196
206
|
// makers: the ground's `instantiate` for a being of the ward, and the ward
|
|
197
207
|
// itself, which is the first being in its own map and is already made.
|
|
198
208
|
#boot(key: string, make: (stance: Stance) => BeingLike | null): Resident | null {
|
|
199
|
-
const cells = guardCells(at(this.p.beings, key) ?? emptyCells(), () => this.#wrote());
|
|
209
|
+
const cells = guardCells(at(this.p.beings, key) ?? emptyCells(), () => this.#wrote(key));
|
|
200
210
|
const bind = at(this.p.bind, key) ?? emptyBind();
|
|
201
211
|
const stance: Stance = buildStance(
|
|
202
212
|
{
|
|
@@ -204,10 +214,10 @@ class Self implements BeingLike {
|
|
|
204
214
|
// This stance, not merely this key: unboot and boot again under the
|
|
205
215
|
// same key makes a new being, and the old stance is not hers.
|
|
206
216
|
live: () => this.doors.get(key)?.stance === stance,
|
|
207
|
-
mintKey: (b) => this.#mintKey(b),
|
|
217
|
+
mintKey: (b) => this.#mintKey(b, key),
|
|
208
218
|
openHeir: (heir, being, id) => this.heirs.open(heir, being, id),
|
|
209
219
|
closeHeir: (heir) => this.heirs.close(heir),
|
|
210
|
-
send: (b, keys, method, args, wanted) => this.#send(b, keys, method, args, wanted),
|
|
220
|
+
send: (b, keys, method, args, wanted) => this.#send(b, keys, method, args, wanted, key),
|
|
211
221
|
// A throw at birth is null to her, not a throw in her method: she asked
|
|
212
222
|
// for a being and got none, and her own answer is still hers to give.
|
|
213
223
|
instantiate: (className, k) => {
|
|
@@ -224,7 +234,7 @@ class Self implements BeingLike {
|
|
|
224
234
|
// names there are, which ward may ask for one, and what becomes of one
|
|
225
235
|
// she did not take, is the harbor's and no word of the ward.
|
|
226
236
|
lend: async (name, take) => (await this.g.lend?.(name, take)) ?? false,
|
|
227
|
-
wrote: () => this.#wrote(),
|
|
237
|
+
wrote: () => this.#wrote(key),
|
|
228
238
|
},
|
|
229
239
|
key,
|
|
230
240
|
cells,
|
|
@@ -236,11 +246,11 @@ class Self implements BeingLike {
|
|
|
236
246
|
put(this.p.bind, key, bind);
|
|
237
247
|
const door: Resident = { key, cells, bind, stance, being };
|
|
238
248
|
this.doors.set(key, door);
|
|
239
|
-
this.#wrote();
|
|
249
|
+
this.#wrote(key);
|
|
240
250
|
return door;
|
|
241
251
|
}
|
|
242
252
|
|
|
243
|
-
async #mintKey(bind: Bind): Promise<{ seed: string; pk: string }> {
|
|
253
|
+
async #mintKey(bind: Bind, row: string): Promise<{ seed: string; pk: string }> {
|
|
244
254
|
const k = await beingKey(this.g.random(32));
|
|
245
255
|
// The last few she minted, and no more. A relation rotates on every ask,
|
|
246
256
|
// so a list of all of them is a partition that grows for as long as she
|
|
@@ -248,7 +258,7 @@ class Self implements BeingLike {
|
|
|
248
258
|
// but the keys of the moment.
|
|
249
259
|
bind.minted.push(k.pk);
|
|
250
260
|
if (bind.minted.length > MINTED) bind.minted.splice(0, bind.minted.length - MINTED);
|
|
251
|
-
this.#wrote();
|
|
261
|
+
this.#wrote(row);
|
|
252
262
|
return k;
|
|
253
263
|
}
|
|
254
264
|
|
|
@@ -257,7 +267,7 @@ class Self implements BeingLike {
|
|
|
257
267
|
// next, seals to the far ward, opens the reply with the ephemeral secret,
|
|
258
268
|
// and rotates to the announced key once the far door has answered under
|
|
259
269
|
// the current one.
|
|
260
|
-
async #send(bind: Bind, keys: StandingKeys, method: string | undefined, args: JsonObject, wanted
|
|
270
|
+
async #send(bind: Bind, keys: StandingKeys, method: string | undefined, args: JsonObject, wanted: Wanted | undefined, row: string): Promise<ReplyPayload | typeof silence | Word> {
|
|
261
271
|
// What she asked for, held to what this ward allows. Asking for nothing is
|
|
262
272
|
// the default, and asking for more than the ceiling is the ceiling: budget
|
|
263
273
|
// is granted by a ward, never minted by a being.
|
|
@@ -267,7 +277,7 @@ class Self implements BeingLike {
|
|
|
267
277
|
// whoever asked: no key it vouched for, so nothing to announce and nothing
|
|
268
278
|
// to rotate to. A standing on her signs with one key for life. Every other
|
|
269
279
|
// ask announces its next: there is no send that does not.
|
|
270
|
-
if (keys.next === null && keys.heir !== null) keys.next = (await this.#mintKey(bind)).seed;
|
|
280
|
+
if (keys.next === null && keys.heir !== null) keys.next = (await this.#mintKey(bind, row)).seed;
|
|
271
281
|
const next = keys.next === null ? null : (await beingKey(unhex(keys.next))).pk;
|
|
272
282
|
// Her count for this relation, one higher every call and never reused. The
|
|
273
283
|
// far door honours each number once. One relation sends one at a time, so
|
|
@@ -289,10 +299,14 @@ class Self implements BeingLike {
|
|
|
289
299
|
return unreached();
|
|
290
300
|
}
|
|
291
301
|
const { bytes, ephemeral } = sealed;
|
|
292
|
-
// The wait is bounded, and
|
|
293
|
-
//
|
|
294
|
-
//
|
|
295
|
-
//
|
|
302
|
+
// The wait is bounded here, and again around the lane in the stance. Two
|
|
303
|
+
// bounds and not one, because they end two different things: the stance's
|
|
304
|
+
// ends the wait a being is held in, and this one ends the occupancy of the
|
|
305
|
+
// relation's lane. A being holds three answers and a wait that does not
|
|
306
|
+
// end is none of them, and a lane nobody ever leaves is a relation the
|
|
307
|
+
// next ask never reaches. Only a bound on the wire breaks the second, and
|
|
308
|
+
// taking it out would leave one quiet far side holding the lane for good.
|
|
309
|
+
// What comes back late is not read.
|
|
296
310
|
//
|
|
297
311
|
// A wait that ran out is `late`, never unreached. Unreached promises
|
|
298
312
|
// nothing was delivered and is safe to retry; a bound that expired knows
|
|
@@ -313,7 +327,7 @@ class Self implements BeingLike {
|
|
|
313
327
|
keys.current = keys.next; // the far door holds `next` as announced. move to it.
|
|
314
328
|
keys.next = null;
|
|
315
329
|
}
|
|
316
|
-
this.#wrote(); // the count moved, and the keys may have
|
|
330
|
+
this.#wrote(row); // the count moved, and the keys may have
|
|
317
331
|
return reply;
|
|
318
332
|
}
|
|
319
333
|
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|