@ccmsg/cli 0.11.3 → 0.11.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.
Files changed (67) hide show
  1. package/README.md +8 -12
  2. package/package.json +1 -1
  3. package/src/auth/auth.ts +23 -23
  4. package/src/auth/http.ts +3 -3
  5. package/src/auth/records.ts +2 -2
  6. package/src/auth/webauthn.ts +1 -1
  7. package/src/cli.ts +10 -10
  8. package/src/daemon/control.ts +1 -1
  9. package/src/daemon/registry.ts +11 -11
  10. package/src/daemon/snapshot.ts +1 -1
  11. package/src/daemon/supervise.ts +4 -4
  12. package/src/dispatch/caller.ts +1 -1
  13. package/src/dispatch/dispatch.ts +4 -4
  14. package/src/dispatch/handler.ts +4 -4
  15. package/src/dispatch/identity.ts +1 -1
  16. package/src/dispatch/result.ts +2 -2
  17. package/src/files/containment.ts +2 -2
  18. package/src/harness/index.ts +1 -1
  19. package/src/instance/client.ts +1 -1
  20. package/src/instance/config.ts +13 -13
  21. package/src/instance/instance.ts +42 -42
  22. package/src/instance/lock.ts +2 -2
  23. package/src/instance/log.ts +1 -1
  24. package/src/instance/paths.ts +6 -6
  25. package/src/instance/socket.ts +1 -1
  26. package/src/kv/store.ts +1 -1
  27. package/src/mesh/instances.ts +2 -2
  28. package/src/mesh/keys.ts +7 -7
  29. package/src/mesh/mesh.ts +67 -67
  30. package/src/mesh/relay.ts +8 -8
  31. package/src/mesh/wire.ts +2 -2
  32. package/src/messaging/delivery.ts +24 -24
  33. package/src/messaging/direct.ts +23 -23
  34. package/src/messaging/inbox.ts +6 -6
  35. package/src/messaging/notify.ts +5 -5
  36. package/src/plugin/codex.ts +1 -1
  37. package/src/sessions/classify.ts +6 -6
  38. package/src/sessions/dump.ts +1 -1
  39. package/src/sessions/handlers.ts +2 -2
  40. package/src/sessions/harness.ts +12 -12
  41. package/src/sessions/last-live.ts +4 -4
  42. package/src/sessions/registry.ts +32 -32
  43. package/src/sessions/status.ts +7 -7
  44. package/src/sessions/terminals.ts +1 -1
  45. package/src/transcript/files.ts +4 -4
  46. package/src/transcript/fold.ts +9 -9
  47. package/src/transcript/items/classify.ts +56 -8
  48. package/src/transcript/read.ts +1 -1
  49. package/src/transcript/tail.ts +3 -3
  50. package/src/transcript/transcripts.ts +7 -7
  51. package/src/translate/helper.ts +2 -2
  52. package/src/transport/conn.ts +3 -3
  53. package/src/transport/dial.ts +1 -1
  54. package/src/transport/driver.ts +2 -2
  55. package/src/transport/entry.ts +1 -1
  56. package/src/transport/framing.ts +1 -1
  57. package/src/transport/listener.ts +3 -3
  58. package/src/transport/uds.ts +2 -2
  59. package/src/transport/ws.ts +2 -2
  60. package/src/upstream/events.ts +3 -3
  61. package/src/upstream/gateway.ts +6 -6
  62. package/src/upstream/json.ts +1 -1
  63. package/src/upstream/requests.ts +6 -6
  64. package/src/upstream/stats.ts +1 -1
  65. package/src/upstream/status.ts +4 -4
  66. package/src/upstream/usage.ts +1 -1
  67. package/src/upstream/webhook.ts +1 -1
package/src/mesh/mesh.ts CHANGED
@@ -58,7 +58,7 @@ export interface MeshClaim {
58
58
  * In the range WebSocket leaves to applications. It exists so the far end can
59
59
  * tell this closure from a fault: losing a glare is its normal course, and
60
60
  * reconnecting on it would reopen exactly the connection both sides just
61
- * agreed to drop (§8.1). */
61
+ * agreed to drop (mesh-peer-auth §8.1). */
62
62
  export const GLARE_CLOSE = 4000;
63
63
 
64
64
  /** How often a link is asked whether it is still there, and how long silence
@@ -78,7 +78,7 @@ export const GLARE_CLOSE = 4000;
78
78
  export const HEARTBEAT_MS = 20_000;
79
79
  export const HEARTBEAT_TIMEOUT_MS = 3 * HEARTBEAT_MS;
80
80
 
81
- /** The reconnection backoff (§8.2).
81
+ /** The reconnection backoff (mesh-peer-auth §8.2).
82
82
  *
83
83
  * Loose on purpose: a peer that comes back dials us, so the moment it recovers
84
84
  * is signalled by its own start rather than found by our retries. What this
@@ -88,7 +88,7 @@ export const RECONNECT_MAX_MS = 60_000;
88
88
 
89
89
  /** How many key requests are answered per second, over all callers.
90
90
  *
91
- * The key endpoint is reached before anything is proven (§6), so it is the one
91
+ * The key endpoint is reached before anything is proven (mesh-peer-auth §6), so it is the one
92
92
  * surface an unauthenticated caller can make this instance do work on. The cap
93
93
  * is well above what a mesh of any size needs — one request per connection
94
94
  * established — and well below what would cost anything. */
@@ -96,7 +96,7 @@ const JWK_RATE_LIMIT = 20;
96
96
  const JWK_RATE_WINDOW_MS = 1_000;
97
97
 
98
98
  /** How long a forwarded op may take before its caller is told the instance
99
- * could not be reached (§7.3).
99
+ * could not be reached (DESIGN §7.3).
100
100
  *
101
101
  * Chosen rather than derived: no primary source states a deadline. The
102
102
  * reasoning is that the two outcomes this sits between are both worse than a
@@ -109,13 +109,13 @@ export const FORWARD_TIMEOUT_MS = 10_000;
109
109
  /** What the instance gives the mesh once it exists.
110
110
  *
111
111
  * The mesh is built before the instance, because the listener has to be up for
112
- * self-identification to reach it (§8.3), so the two things a link needs from
112
+ * self-identification to reach it (DESIGN §8.3), so the two things a link needs from
113
113
  * the instance arrive afterwards rather than through the constructor. */
114
114
  export interface MeshHost {
115
- /** The one door a frame goes through (§3.2). A request a peer carried here
115
+ /** The one door a frame goes through (DESIGN §2.2). A request a peer carried here
116
116
  * is answered by the same dispatch every other request is. */
117
117
  handle(frame: unknown, conn: Requester): Promise<DispatchResult>;
118
- /** Hand a relayed frame to this instance's own subscribers (§7.4). */
118
+ /** Hand a relayed frame to this instance's own subscribers (DESIGN §7.4). */
119
119
  publish(topic: string, data: unknown, instance: InstanceId): void;
120
120
  /** Take a frame on a topic the relay does not carry.
121
121
  *
@@ -125,7 +125,7 @@ export interface MeshHost {
125
125
  * receives it is the set itself, which merges by key (DR-0001 §2.6). */
126
126
  element(topic: string, instance: InstanceId, data: unknown): void;
127
127
  /** Which instances can be reached has changed, which is part of what this
128
- * instance states on `peers` (§7.5). */
128
+ * instance states on `peers` (DESIGN §7.5). */
129
129
  changed(): void;
130
130
  }
131
131
 
@@ -134,7 +134,7 @@ export interface MeshDeps {
134
134
  readonly id: InstanceId;
135
135
  /** Every mesh endpoint, this instance's own among them. */
136
136
  readonly peers: readonly Endpoint[];
137
- /** Which of them is this instance, as the data says (§7.1). */
137
+ /** Which of them is this instance, as the data says (DESIGN §7.1). */
138
138
  readonly self: Endpoint;
139
139
  readonly conns: ConnRegistry;
140
140
  readonly log?: (msg: string, fields?: Record<string, unknown>) => void;
@@ -144,7 +144,7 @@ export interface MeshDeps {
144
144
  readonly heartbeatTimeoutMs?: number;
145
145
  readonly reconnectMinMs?: number;
146
146
  readonly forwardTimeoutMs?: number;
147
- /** The clock the retention window of §7.5 is read against. */
147
+ /** The clock the retention window of DESIGN §7.5 is read against. */
148
148
  readonly now?: () => Timestamp;
149
149
  }
150
150
 
@@ -153,16 +153,16 @@ interface Link {
153
153
  readonly conn: Requester;
154
154
  /** One actor per caller this link has spoken for, keyed by the identity
155
155
  * itself. Cached rather than made per request because a subscription is held
156
- * by a connection and released when it closes (§6.3): the topic mechanism
156
+ * by a connection and released when it closes (DESIGN §6.3): the topic mechanism
157
157
  * has to see the same object each time one caller subscribes. */
158
158
  readonly actors: Map<string, PeerActor>;
159
- /** Which end opened the socket, which is what the glare rule compares (§8.1). */
159
+ /** Which end opened the socket, which is what the glare rule compares (mesh-peer-auth §8.1). */
160
160
  readonly dialledByUs: boolean;
161
161
  readonly heartbeat: ReturnType<typeof setInterval>;
162
162
  lastHeard: number;
163
163
  }
164
164
 
165
- /** One request this instance forwarded and is waiting on (§7.3). */
165
+ /** One request this instance forwarded and is waiting on (DESIGN §7.3). */
166
166
  interface Forwarded {
167
167
  readonly peer: Endpoint;
168
168
  /** The id the caller used, restored on the reply so the caller's connection
@@ -178,10 +178,10 @@ interface Forwarded {
178
178
  * The envelope's `caller` is taken as said. It is the one thing the
179
179
  * destination believes on the forwarder's word, and it can, because the link
180
180
  * is authenticated: mesh-peer-auth proved the far end is an instance on the
181
- * peer list, and a peer list is one deployment (§8.2). Everything else is
181
+ * peer list, and a peer list is one deployment (DESIGN §8.2). Everything else is
182
182
  * decided here — the role check reads this identity against this instance's
183
183
  * own attribute table, and so do the capability and locality checks, which is
184
- * what §7.3 means by putting a forwarded op through the steps again rather
184
+ * what DESIGN §7.3 means by putting a forwarded op through the steps again rather
185
185
  * than taking the forwarder's outcome for it.
186
186
  *
187
187
  * `from_instance` is not part of that judgement: the field says where the
@@ -213,11 +213,11 @@ class PeerActor implements Requester {
213
213
  }
214
214
  }
215
215
 
216
- /** One handshake this instance is verifying, as the receiving end (§5).
216
+ /** One handshake this instance is verifying, as the receiving end (mesh-peer-auth §5).
217
217
  *
218
218
  * Everything the verification needs is here and nowhere else, so the whole of
219
219
  * what a handshake leaves behind is one map entry that is deleted when it
220
- * finishes — which is what §10.5 asks be true. */
220
+ * finishes — which is what mesh-peer-auth §10.5 asks be true. */
221
221
  interface Pending {
222
222
  readonly claim: MeshClaim;
223
223
  readonly challenge: string;
@@ -225,14 +225,14 @@ interface Pending {
225
225
  readonly fail: (cause: Error) => void;
226
226
  }
227
227
 
228
- /** One key this instance minted for a connection it dialled (§7). */
228
+ /** One key this instance minted for a connection it dialled (mesh-peer-auth §7). */
229
229
  interface Minted {
230
230
  readonly key: EphemeralKey;
231
231
  readonly aud: Endpoint;
232
232
  conn?: Requester;
233
233
  }
234
234
 
235
- /** Which of two connections to one peer survives a glare (§8.1).
235
+ /** Which of two connections to one peer survives a glare (mesh-peer-auth §8.1).
236
236
  *
237
237
  * The connection opened by the smaller `iss` is the one that stays. Neither is
238
238
  * better than the other — both were verified before either was dropped — so
@@ -249,7 +249,7 @@ export function glareKeepsNew(self: Endpoint, peer: Endpoint, dialledByUs: boole
249
249
  * what each of them is.
250
250
  *
251
251
  * Every instance dials every peer, so there is no side that owns a link and no
252
- * peer that cannot be recovered from the other end (§8, and §12's reason for
252
+ * peer that cannot be recovered from the other end (mesh-peer-auth §8, and mesh-peer-auth §12's reason for
253
253
  * not assigning the duty to one side). */
254
254
  export class Mesh {
255
255
  readonly #links = new Map<Endpoint, Link>();
@@ -258,7 +258,7 @@ export class Mesh {
258
258
  readonly #retries = new Map<Endpoint, ReturnType<typeof setTimeout>>();
259
259
  readonly #backoff = new Map<Endpoint, number>();
260
260
  /** Which of the configured endpoints is this instance, as the data said
261
- * before anything is dialled and fixed from then on (§5.5). */
261
+ * before anything is dialled and fixed from then on (mesh-peer-auth §5.5). */
262
262
  readonly #self: Endpoint;
263
263
  /** The authenticated endpoint-to-id mapping (DR-0001 §2.1), in both
264
264
  * directions: a handshake writes it, `to_instance` reads it to find the link
@@ -280,13 +280,13 @@ export class Mesh {
280
280
  readonly #linkOf = new Map<Requester, Link>();
281
281
  readonly #forwarded = new Map<string, Forwarded>();
282
282
  /** The relayed topics local subscribers are asking for right now. `peers` is
283
- * always among them: it is the routing table of §7.3, and a question about
283
+ * always among them: it is the routing table of DESIGN §7.3, and a question about
284
284
  * where a session lives is answered whether or not anyone is subscribed
285
- * (§6.3, "reading the current value is not what subscription drives"). */
285
+ * (DESIGN §6.3, "reading the current value is not what subscription drives"). */
286
286
  readonly #demanded = new Set<string>(["peers", AUTH_TOPIC]);
287
287
  #host: MeshHost | undefined;
288
288
 
289
- /** What the peers said, kept across a disconnection (§7.5). */
289
+ /** What the peers said, kept across a disconnection (DESIGN §7.5). */
290
290
  readonly relay: Relay;
291
291
 
292
292
  constructor(private readonly deps: MeshDeps) {
@@ -304,13 +304,13 @@ export class Mesh {
304
304
  });
305
305
  }
306
306
 
307
- /** Give the mesh the instance it belongs to (§8.3). */
307
+ /** Give the mesh the instance it belongs to (DESIGN §8.3). */
308
308
  bind(host: MeshHost): void {
309
309
  this.#host = host;
310
310
  }
311
311
 
312
312
  /** The registry the mesh's own connections are in. It is the instance's, and
313
- * is shared because a mesh link is one of its connections (§3.1). */
313
+ * is shared because a mesh link is one of its connections (DESIGN §2.1). */
314
314
  get conns(): ConnRegistry {
315
315
  return this.deps.conns;
316
316
  }
@@ -332,7 +332,7 @@ export class Mesh {
332
332
  /** The peers this instance dials: the configured list without itself.
333
333
  *
334
334
  * The list is the same on every instance, which is what lets one file be
335
- * distributed to all of them (§8.2) — and it names this instance too, so
335
+ * distributed to all of them (DESIGN §8.2) — and it names this instance too, so
336
336
  * removing ourselves is the reader's job rather than the writer's. `identify`
337
337
  * is what found which entry that is. */
338
338
  get peers(): Endpoint[] {
@@ -342,7 +342,7 @@ export class Mesh {
342
342
 
343
343
  /** The peers taken off this host's list while this instance was running.
344
344
  *
345
- * Config is read once (DV-Q8) and this does not change that: what a person
345
+ * Config is read once (DR-0004) and this does not change that: what a person
346
346
  * writes goes on taking effect at the next start. What this holds is the one
347
347
  * edit that cannot wait for one — an endpoint this host is no longer to be
348
348
  * talking to, which would otherwise stay connected until somebody restarted
@@ -369,7 +369,7 @@ export class Mesh {
369
369
  }
370
370
 
371
371
  /** Where peers reach this instance: the row of the mesh carrying its own id
372
- * (§7.1). Everything that reads it — the handshake's `aud`, the mesh's own
372
+ * (DESIGN §7.1). Everything that reads it — the handshake's `aud`, the mesh's own
373
373
  * routes, what `hello` reports — is the one address the data states. */
374
374
  get self(): Endpoint {
375
375
  return this.#self;
@@ -385,7 +385,7 @@ export class Mesh {
385
385
  }
386
386
 
387
387
  /** What `hello` reports: this instance, then every configured peer, with
388
- * whether it can be reached right now (§7.5).
388
+ * whether it can be reached right now (DESIGN §7.5).
389
389
  *
390
390
  * A peer no handshake has settled yet is listed without an id. The operator
391
391
  * configured that endpoint, so it is an entry of the cluster whether or not
@@ -409,7 +409,7 @@ export class Mesh {
409
409
  /** Whether any peer is currently out of reach.
410
410
  *
411
411
  * What separates "no instance in the cluster knows this session" from "an
412
- * instance that might know it cannot be asked" — the one distinction §4.2
412
+ * instance that might know it cannot be asked" — the one distinction DESIGN §6.6
413
413
  * says rests on the mesh's connection state and on nothing else. */
414
414
  anyUnreachable(): boolean {
415
415
  return this.peers.some((peer) => !this.reachable(peer));
@@ -420,7 +420,7 @@ export class Mesh {
420
420
  * A session the cluster has named belongs to the instance its `peers` row
421
421
  * states. One nobody has named while a peer is out of reach is answered with
422
422
  * that peer: forwarding there fails and the caller is told
423
- * `instance_unreachable`, which is what §4.2 asks for in place of deciding
423
+ * `instance_unreachable`, which is what DESIGN §6.6 asks for in place of deciding
424
424
  * the session does not exist. */
425
425
  ownerOf(sid: Sid): InstanceId | undefined {
426
426
  const owner = this.relay.owner(sid);
@@ -436,7 +436,7 @@ export class Mesh {
436
436
  return undefined;
437
437
  }
438
438
 
439
- // --- op forwarding (§7.3) ---
439
+ // --- op forwarding (DESIGN §7.3) ---
440
440
 
441
441
  /** Carry one op to the instance that owns its subject, and bring the answer
442
442
  * back.
@@ -499,7 +499,7 @@ export class Mesh {
499
499
  * What the person's authentication needs of a peer (`auth.resolve`,
500
500
  * `auth.rotate`) is a fact only its issuer holds, asked for by the instance
501
501
  * that needs it — so the `caller` is this instance's own role, and the
502
- * request travels the ordinary forwarding path (§7.3, DR-0001 §2.6).
502
+ * request travels the ordinary forwarding path (DESIGN §7.3, DR-0001 §2.6).
503
503
  *
504
504
  * The body of the reply is answered, and a refusal is thrown as the error the
505
505
  * far end named, so a caller reads one outcome rather than a result kind. */
@@ -528,7 +528,7 @@ export class Mesh {
528
528
  return this.#linkOf.has(conn);
529
529
  }
530
530
 
531
- /** The connection a forwarded request is dispatched as (§7.3).
531
+ /** The connection a forwarded request is dispatched as (DESIGN §7.3).
532
532
  *
533
533
  * The caller the envelope names, on the link it arrived over. A request that
534
534
  * names none is dispatched as the link itself, whose role is `instance` —
@@ -549,7 +549,7 @@ export class Mesh {
549
549
  return actor;
550
550
  }
551
551
 
552
- // --- event relay (§7.4) ---
552
+ // --- event relay (DESIGN §7.4) ---
553
553
 
554
554
  /** The current value of a relayed topic, one entry per instance that has
555
555
  * stated one. Handed to a fresh local subscriber beside this instance's own
@@ -561,12 +561,12 @@ export class Mesh {
561
561
  /** A local subscriber appeared on a cluster topic, or the last one left.
562
562
  *
563
563
  * The subscription travels: what a subscriber asks of this instance, this
564
- * instance asks of every peer, and the frames come back unchanged (§7.4).
564
+ * instance asks of every peer, and the frames come back unchanged (DESIGN §7.4).
565
565
  * `peers` is never given up, because it is also the routing table. */
566
566
  demand(topic: string, wanted: boolean): void {
567
567
  // `auth.records` is never given up and never asked for on demand: every
568
568
  // instance holds the whole set whether or not anything local is watching
569
- // it, the way `peers` is also the routing table (§7.4, DR-0001 §2.6).
569
+ // it, the way `peers` is also the routing table (DESIGN §7.4, DR-0001 §2.6).
570
570
  if (topic === AUTH_TOPIC || !isClusterTopic(topic)) return;
571
571
  if (wanted) {
572
572
  if (this.#demanded.has(topic)) return;
@@ -594,7 +594,7 @@ export class Mesh {
594
594
  // The instance asks on behalf of whoever subscribed to it, and what they
595
595
  // have in common is that they are this deployment's people rather than
596
596
  // any one session: a cluster topic is the same value for all of them
597
- // (§6.2), so there is nothing narrower to name.
597
+ // (DESIGN §6.2), so there is nothing narrower to name.
598
598
  //
599
599
  // `auth.records` is the exception, and the one topic no person may hear:
600
600
  // it carries the tokens that authenticate them, so the instance asks for
@@ -621,10 +621,10 @@ export class Mesh {
621
621
  * The whole judgement is here, inside the op that dispatch already validated
622
622
  * and allowed: nothing settles an identity on another path, and a handshake
623
623
  * that fails any step throws, which is what leaves the connection anonymous
624
- * (§3.2 step 7). */
624
+ * (DESIGN §2.2 step 7). */
625
625
  async greet(conn: Requester, claim: MeshClaim): Promise<void> {
626
626
  const self = this.self;
627
- // 1-3 of §5.7, asked before the key is fetched: the cheap comparisons come
627
+ // 1-3 of mesh-peer-auth §5.7, asked before the key is fetched: the cheap comparisons come
628
628
  // first because the fetch reaches out to another host.
629
629
  if (claim.ver !== MESH_VER) {
630
630
  throw new OpError("invalid_args", `this instance speaks mesh handshake ${MESH_VER}`);
@@ -657,7 +657,7 @@ export class Mesh {
657
657
  try {
658
658
  // The key comes over a connection of its own, opened to the endpoint the
659
659
  // greeting names. Asking for it on this connection would let whoever
660
- // opened it answer with their own key and pass their own signature (§6).
660
+ // opened it answer with their own key and pass their own signature (mesh-peer-auth §6).
661
661
  const jwk = await this.#fetchKey(claim, challenge);
662
662
  const jws = await withTimeout(
663
663
  proof.promise,
@@ -674,7 +674,7 @@ export class Mesh {
674
674
  );
675
675
  } finally {
676
676
  // The challenge is spent whatever happened, so there is no record of it
677
- // anywhere once the handshake ends (§5.5, §10.5).
677
+ // anywhere once the handshake ends (mesh-peer-auth §5.5, §10.5).
678
678
  this.#pending.delete(conn);
679
679
  }
680
680
  // The claim is checked again now that it is trusted: the fetch and the wait
@@ -709,7 +709,7 @@ export class Mesh {
709
709
  /** A frame that is not an op. True when the mesh took it.
710
710
  *
711
711
  * The proof arrives here because it belongs on the connection being
712
- * authenticated (§5), which is the one connection the op vocabulary has no
712
+ * authenticated (mesh-peer-auth §5), which is the one connection the op vocabulary has no
713
713
  * name for: mesh carries no ops of its own (contract, `Plane`). */
714
714
  frame(conn: Requester, frame: unknown): boolean {
715
715
  const mesh = meshFrameOf(frame);
@@ -724,7 +724,7 @@ export class Mesh {
724
724
  }
725
725
  const pending = this.#pending.get(conn);
726
726
  // A proof with no handshake waiting for it: either none was started, or the
727
- // challenge it answers has already been spent. Neither is retried (§5.5).
727
+ // challenge it answers has already been spent. Neither is retried (mesh-peer-auth §5.5).
728
728
  if (pending === undefined) {
729
729
  conn.close();
730
730
  return true;
@@ -734,7 +734,7 @@ export class Mesh {
734
734
  }
735
735
 
736
736
  /** What a proven link wrote that is not a request: a topic frame to relay
737
- * (§7.4), or the reply to something this instance forwarded (§7.3).
737
+ * (DESIGN §7.4), or the reply to something this instance forwarded (DESIGN §7.3).
738
738
  *
739
739
  * Only a link is read this way. A client connection could otherwise guess a
740
740
  * forwarded id and settle a request it has nothing to do with, and could
@@ -777,12 +777,12 @@ export class Mesh {
777
777
  }
778
778
 
779
779
  /** Whether this connection is mid-handshake, which is what makes an ordinary
780
- * request on it a protocol violation rather than an early call (§5.8). */
780
+ * request on it a protocol violation rather than an early call (mesh-peer-auth §5.8). */
781
781
  handshaking(conn: Requester): boolean {
782
782
  return this.#pending.has(conn);
783
783
  }
784
784
 
785
- // --- the HTTP surface: the key of §6 ---
785
+ // --- the HTTP surface: the key of mesh-peer-auth §6 ---
786
786
 
787
787
  /** Answer the one request that is served before anything is proven, or
788
788
  * nothing when the request is not it. */
@@ -813,7 +813,7 @@ export class Mesh {
813
813
  }
814
814
  const minted = this.#minted.get(kid);
815
815
  // Unknown to us, or known and no longer connected to the handshake it was
816
- // made for. Either way there is no key to give (§6.1).
816
+ // made for. Either way there is no key to give (mesh-peer-auth §6.1).
817
817
  if (minted === undefined || minted.conn === undefined) {
818
818
  return new Response("no such key", { status: 404 });
819
819
  }
@@ -846,7 +846,7 @@ export class Mesh {
846
846
  return this.#jwkServed <= JWK_RATE_LIMIT;
847
847
  }
848
848
 
849
- // --- the dialling end (§5, steps 1-3 and 13) ---
849
+ // --- the dialling end (mesh-peer-auth §5, steps 1-3 and 13) ---
850
850
 
851
851
  async #dial(peer: Endpoint): Promise<void> {
852
852
  if (this.#stopping || this.#links.has(peer)) return;
@@ -887,7 +887,7 @@ export class Mesh {
887
887
 
888
888
  /** What the far end wrote on a connection we opened.
889
889
  *
890
- * The greeting's reply is the acknowledgement of §5.8: it is what says the
890
+ * The greeting's reply is the acknowledgement of mesh-peer-auth §5.8: it is what says the
891
891
  * peer finished verifying, which is both the moment this instance may speak
892
892
  * and the moment its key has no further use. */
893
893
  #dialledFrame(peer: Endpoint, conn: Requester, frame: unknown, kid: string): void {
@@ -897,7 +897,7 @@ export class Mesh {
897
897
  // A request the peer forwarded to us. A dialled connection is answered by
898
898
  // whoever dialled it (transport, `DialOptions`), so the reply goes out
899
899
  // here rather than through the driver — but what decides it is the same
900
- // dispatch every other request goes through (§7.3).
900
+ // dispatch every other request goes through (DESIGN §7.3).
901
901
  if (typeof fields["op"] === "string") this.#answer(conn, fields);
902
902
  return;
903
903
  }
@@ -962,7 +962,7 @@ export class Mesh {
962
962
  * one is already held.
963
963
  *
964
964
  * Both connections are verified before either is dropped, so whichever
965
- * survives is one that was proven (§8.1). */
965
+ * survives is one that was proven (mesh-peer-auth §8.1). */
966
966
  #hold(peer: Endpoint, conn: Requester, dialledByUs: boolean): void {
967
967
  const self = this.self;
968
968
  const held = this.#links.get(peer);
@@ -996,7 +996,7 @@ export class Mesh {
996
996
  this.#drop(peer, conn);
997
997
  });
998
998
  // What it said before is still held and stops being marked; what it says
999
- // now replaces it, which is the whole of "restored by reconnection" (§7.5).
999
+ // now replaces it, which is the whole of "restored by reconnection" (DESIGN §7.5).
1000
1000
  // Under the id, because that is what its frames name themselves with: the
1001
1001
  // endpoint is where the link was dialled and says nothing about the value.
1002
1002
  const id = this.#idOf.get(peer);
@@ -1008,7 +1008,7 @@ export class Mesh {
1008
1008
 
1009
1009
  /** Say that the set of reachable instances moved. Two listeners: whatever
1010
1010
  * the deps gave, and the instance, which restates `peers` — the topic the
1011
- * view rides on (§7.5). */
1011
+ * view rides on (DESIGN §7.5). */
1012
1012
  #changed(): void {
1013
1013
  this.deps.onChanged?.();
1014
1014
  this.#host?.changed();
@@ -1021,7 +1021,7 @@ export class Mesh {
1021
1021
  if (silence > (this.deps.heartbeatTimeoutMs ?? HEARTBEAT_TIMEOUT_MS)) {
1022
1022
  // Nothing has come back for long enough that the link is gone whatever
1023
1023
  // the socket believes — which is the whole reason for the heartbeat
1024
- // (§8.3): a middlebox drops a connection without telling either end.
1024
+ // (mesh-peer-auth §8.3): a middlebox drops a connection without telling either end.
1025
1025
  this.deps.log?.("mesh peer went silent", { peer, silence_ms: silence });
1026
1026
  link.conn.close();
1027
1027
  this.#drop(peer, link.conn);
@@ -1043,7 +1043,7 @@ export class Mesh {
1043
1043
  this.#links.delete(peer);
1044
1044
  this.#linkOf.delete(conn);
1045
1045
  // Its sessions become a kind of Disappeared and its values are marked
1046
- // rather than dropped (§7.5), and anything on its way there is answered
1046
+ // rather than dropped (DESIGN §7.5), and anything on its way there is answered
1047
1047
  // now instead of waiting out a deadline it can no longer beat.
1048
1048
  const id = this.#idOf.get(peer);
1049
1049
  if (id !== undefined) this.relay.lost(id);
@@ -1080,7 +1080,7 @@ export class Mesh {
1080
1080
  this.#retries.set(peer, timer);
1081
1081
  }
1082
1082
 
1083
- /** Let every link and every timer go. Called from the stop order (§8.5). */
1083
+ /** Let every link and every timer go. Called from the stop order (DESIGN §8.5). */
1084
1084
  stop(): void {
1085
1085
  this.#stopping = true;
1086
1086
  for (const timer of this.#retries.values()) clearTimeout(timer);
@@ -1091,14 +1091,14 @@ export class Mesh {
1091
1091
  // The far end has no other way to learn this instance is going: it would
1092
1092
  // keep the link, keep answering `reachable`, and keep routing
1093
1093
  // `instance-local` ops here until its own heartbeat gave up minutes later,
1094
- // where the disconnection of §7.5 is supposed to be immediate. Which side
1094
+ // where the disconnection of DESIGN §7.5 is supposed to be immediate. Which side
1095
1095
  // dialled a link is decided by the glare rule from a comparison of
1096
- // endpoint strings (§8.1), so which of a peer's links this instance
1096
+ // endpoint strings (mesh-peer-auth §8.1), so which of a peer's links this instance
1097
1097
  // accepted is not something either end chose — leaving those open makes a
1098
1098
  // clean stop look like a silent one to whichever half of the cluster the
1099
1099
  // comparison put on this side.
1100
1100
  //
1101
- // An accepted socket is transport's to release (§8.5 step 5), and left to
1101
+ // An accepted socket is transport's to release (DESIGN §8.5 step 5), and left to
1102
1102
  // it the far end is told whenever the listener gets round to it: measured
1103
1103
  // against Bun 1.3.13, `stop` on a server that has itself closed a
1104
1104
  // WebSocket — which the mesh does, to drop the loser of a glare — never
@@ -1107,7 +1107,7 @@ export class Mesh {
1107
1107
  // Closing here is what makes the notice the mesh's own rather than a side
1108
1108
  // effect of a listener going down. The step-3 notice this precedes is
1109
1109
  // `restarting`, which is addressed to clients — a peer learns from the
1110
- // link, and that is the whole of what §7.5 asks for.
1110
+ // link, and that is the whole of what DESIGN §7.5 asks for.
1111
1111
  for (const link of this.#links.values()) {
1112
1112
  clearInterval(link.heartbeat);
1113
1113
  link.conn.close();
@@ -1116,7 +1116,7 @@ export class Mesh {
1116
1116
  this.#links.clear();
1117
1117
  this.#linkOf.clear();
1118
1118
  // Keys die with the connections they were made for, and none outlives this
1119
- // (§7).
1119
+ // (mesh-peer-auth §7).
1120
1120
  this.#minted.clear();
1121
1121
  for (const pending of this.#pending.values()) {
1122
1122
  pending.fail(new Error("this instance is stopping"));
@@ -1125,7 +1125,7 @@ export class Mesh {
1125
1125
  }
1126
1126
 
1127
1127
  /** What is held per handshake right now, so a test can state that nothing is
1128
- * kept once one has finished (§10.5). */
1128
+ * kept once one has finished (mesh-peer-auth §10.5). */
1129
1129
  get held(): { keys: number; handshakes: number; links: number } {
1130
1130
  return {
1131
1131
  keys: this.#minted.size,
@@ -1141,7 +1141,7 @@ export class Mesh {
1141
1141
  const response = await fetch(jwkEndpoint(claim.iss, claim.kid), {
1142
1142
  method: "POST",
1143
1143
  // One request and close, which is what the second connection is
1144
- // (§6.2): it exists to carry the key and the challenge, and keeping it
1144
+ // (mesh-peer-auth §6.2): it exists to carry the key and the challenge, and keeping it
1145
1145
  // pooled afterwards would leave a connection nothing speaks on.
1146
1146
  headers: { "content-type": "application/json", connection: "close" },
1147
1147
  body: JSON.stringify(body),
@@ -1149,14 +1149,14 @@ export class Mesh {
1149
1149
  });
1150
1150
  if (!response.ok) throw new Error(`${claim.iss} did not hand out the key ${claim.kid}`);
1151
1151
  const jwk = (await response.json()) as MeshJwk;
1152
- // §5.7-8, the third of the three ids that have to agree: a key served under
1152
+ // mesh-peer-auth §5.7-8, the third of the three ids that have to agree: a key served under
1153
1153
  // one id and answering to another would break the correspondence the whole
1154
1154
  // exchange is keyed on.
1155
1155
  if (jwk.kid !== claim.kid) throw new Error("the key served is not the key asked for");
1156
1156
  return jwk;
1157
1157
  }
1158
1158
 
1159
- /** §5.7, steps 4 to 8. */
1159
+ /** mesh-peer-auth §5.7, steps 4 to 8. */
1160
1160
  #verify(jws: string, claim: MeshClaim, challenge: string, jwk: MeshJwk): void {
1161
1161
  let parsed;
1162
1162
  try {
package/src/mesh/relay.ts CHANGED
@@ -21,7 +21,7 @@ const ROW_TOPICS: readonly string[] = ["peers", "agents"];
21
21
 
22
22
  /** The topics a subscriber sees the whole cluster on.
23
23
  *
24
- * A per-instance whole is relayable by construction (§6.2): a frame replaces
24
+ * A per-instance whole is relayable by construction (DESIGN §6.2): a frame replaces
25
25
  * its own instance's entries and leaves every other instance's alone, so
26
26
  * several instances can state the same topic name without colliding. The rows
27
27
  * above are relayable for the same reason read one element at a time. */
@@ -56,7 +56,7 @@ function rowsOf(topic: string, data: unknown): readonly SessionRow[] {
56
56
 
57
57
  export interface RelayDeps {
58
58
  /** Hand a relayed frame to this instance's own subscribers, under the
59
- * instance that produced it (§7.4). */
59
+ * instance that produced it (DESIGN §7.4). */
60
60
  readonly publish: (topic: string, data: unknown, instance: InstanceId) => void;
61
61
  /** The clock, so a test can move the retention window without waiting it
62
62
  * out. */
@@ -64,7 +64,7 @@ export interface RelayDeps {
64
64
  }
65
65
 
66
66
  /** What the peers said, held on this instance so that losing a peer does not
67
- * empty the cluster view (§7.5).
67
+ * empty the cluster view (DESIGN §7.5).
68
68
  *
69
69
  * Two things live here and nowhere else: the last whole value each instance
70
70
  * stated per topic, and whether that instance can be reached right now. The
@@ -78,7 +78,7 @@ export interface RelayDeps {
78
78
  export class Relay {
79
79
  /** Per instance, the last whole value it stated per topic. */
80
80
  readonly #held = new Map<InstanceId, Map<string, unknown>>();
81
- /** The mark of §7.5: when this instance stopped being reachable. Absent
81
+ /** The mark of DESIGN §7.5: when this instance stopped being reachable. Absent
82
82
  * while it is reachable. */
83
83
  readonly #lostAt = new Map<InstanceId, Timestamp>();
84
84
 
@@ -97,7 +97,7 @@ export class Relay {
97
97
  * peer it arrived from: a mesh of three relays transitively, and the frame
98
98
  * names its origin the whole way. Held under that origin, and passed on
99
99
  * unchanged — recomputing it would put the same judgement in two places
100
- * (§7.4). */
100
+ * (DESIGN §7.4). */
101
101
  accept(instance: InstanceId, topic: string, data: unknown, snapshot = false): void {
102
102
  if (!isClusterTopic(topic)) return;
103
103
  this.#sweep();
@@ -134,7 +134,7 @@ export class Relay {
134
134
 
135
135
  /** The link to this instance is gone. What it said is kept and marked,
136
136
  * because dropping it would empty the view until the instance comes back
137
- * and restates everything (§7.5). */
137
+ * and restates everything (DESIGN §7.5). */
138
138
  lost(instance: InstanceId): void {
139
139
  if (!this.#lostAt.has(instance)) this.#lostAt.set(instance, this.#now());
140
140
  this.#sweep();
@@ -175,7 +175,7 @@ export class Relay {
175
175
  }
176
176
 
177
177
  /** Which instance a session belongs to, read from the cluster values the
178
- * peers stated (§7.3).
178
+ * peers stated (DESIGN §7.3).
179
179
  *
180
180
  * `peers` names every session an instance holds, connected and lost alike,
181
181
  * and is checked first. A session whose greeting has not reached its
@@ -199,7 +199,7 @@ export class Relay {
199
199
  /** Drop what an instance said once it has been gone for the retention
200
200
  * window. The window is the contract's, shared with `last_live` and the
201
201
  * inbox: past it, everything the value would point at is gone too
202
- * (§7.5, DV-Q12). */
202
+ * (DESIGN §7.5, DR-0014). */
203
203
  #sweep(): void {
204
204
  const now = this.#now();
205
205
  for (const [instance, since] of this.#lostAt) {
package/src/mesh/wire.ts CHANGED
@@ -24,7 +24,7 @@ export function wsEndpoint(endpoint: Endpoint): string {
24
24
  /** Where one connection's key is fetched, and the challenge for it left.
25
25
  *
26
26
  * A plain request rather than a frame on the link, because this is the second
27
- * connection of §6: the protocol asks that the key be fetched outside the
27
+ * connection of mesh-peer-auth §6: the protocol asks that the key be fetched outside the
28
28
  * connection being authenticated. */
29
29
  export function jwkEndpoint(endpoint: Endpoint, kid: string): string {
30
30
  return `${endpoint}${JWK_ROUTE}${encodeURIComponent(kid)}`;
@@ -66,7 +66,7 @@ export function meshFrameOf(frame: unknown): MeshFrame | undefined {
66
66
  return typeof jws === "string" ? { mesh: "proof", jws } : undefined;
67
67
  }
68
68
 
69
- /** What a key request carries: the challenge the proof must sign (§6). */
69
+ /** What a key request carries: the challenge the proof must sign (mesh-peer-auth §6). */
70
70
  export interface JwkRequest {
71
71
  readonly ver: number;
72
72
  readonly challenge: string;