@cello-protocol/daemon 0.0.167 → 0.0.169

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 (80) hide show
  1. package/dist/daemon.d.ts.map +1 -1
  2. package/dist/daemon.js +115 -254
  3. package/dist/daemon.js.map +1 -1
  4. package/dist/document-amendment-store.d.ts +94 -46
  5. package/dist/document-amendment-store.d.ts.map +1 -1
  6. package/dist/document-amendment-store.js +217 -102
  7. package/dist/document-amendment-store.js.map +1 -1
  8. package/dist/document-delivery-transport.d.ts +41 -52
  9. package/dist/document-delivery-transport.d.ts.map +1 -1
  10. package/dist/document-delivery-transport.js +6 -156
  11. package/dist/document-delivery-transport.js.map +1 -1
  12. package/dist/document-frame-router.d.ts +13 -17
  13. package/dist/document-frame-router.d.ts.map +1 -1
  14. package/dist/document-frame-router.js +21 -93
  15. package/dist/document-frame-router.js.map +1 -1
  16. package/dist/document-handlers.d.ts +1 -1
  17. package/dist/document-handlers.d.ts.map +1 -1
  18. package/dist/document-handlers.js +471 -466
  19. package/dist/document-handlers.js.map +1 -1
  20. package/dist/document-handshake.d.ts +4 -1
  21. package/dist/document-handshake.d.ts.map +1 -1
  22. package/dist/document-handshake.js +3 -1
  23. package/dist/document-handshake.js.map +1 -1
  24. package/dist/document-inbound.d.ts +18 -5
  25. package/dist/document-inbound.d.ts.map +1 -1
  26. package/dist/document-inbound.js +94 -110
  27. package/dist/document-inbound.js.map +1 -1
  28. package/dist/document-layer.d.ts +28 -67
  29. package/dist/document-layer.d.ts.map +1 -1
  30. package/dist/document-layer.js +670 -565
  31. package/dist/document-layer.js.map +1 -1
  32. package/dist/document-lifecycle.d.ts +11 -157
  33. package/dist/document-lifecycle.d.ts.map +1 -1
  34. package/dist/document-lifecycle.js +26 -561
  35. package/dist/document-lifecycle.js.map +1 -1
  36. package/dist/document-publish.d.ts +13 -0
  37. package/dist/document-publish.d.ts.map +1 -1
  38. package/dist/document-publish.js +19 -11
  39. package/dist/document-publish.js.map +1 -1
  40. package/dist/document-reconcile-engine.d.ts +66 -0
  41. package/dist/document-reconcile-engine.d.ts.map +1 -0
  42. package/dist/document-reconcile-engine.js +225 -0
  43. package/dist/document-reconcile-engine.js.map +1 -0
  44. package/dist/document-reconcile-scheduler.d.ts +91 -0
  45. package/dist/document-reconcile-scheduler.d.ts.map +1 -0
  46. package/dist/document-reconcile-scheduler.js +153 -0
  47. package/dist/document-reconcile-scheduler.js.map +1 -0
  48. package/dist/document-rejection.d.ts +2 -0
  49. package/dist/document-rejection.d.ts.map +1 -1
  50. package/dist/document-rejection.js +5 -1
  51. package/dist/document-rejection.js.map +1 -1
  52. package/dist/document-store.d.ts +18 -220
  53. package/dist/document-store.d.ts.map +1 -1
  54. package/dist/document-store.js +95 -717
  55. package/dist/document-store.js.map +1 -1
  56. package/dist/initiate-session-handler.d.ts +5 -0
  57. package/dist/initiate-session-handler.d.ts.map +1 -1
  58. package/dist/initiate-session-handler.js +1 -0
  59. package/dist/initiate-session-handler.js.map +1 -1
  60. package/package.json +5 -5
  61. package/dist/delivery-sweep-bound.d.ts +0 -79
  62. package/dist/delivery-sweep-bound.d.ts.map +0 -1
  63. package/dist/delivery-sweep-bound.js +0 -109
  64. package/dist/delivery-sweep-bound.js.map +0 -1
  65. package/dist/document-ack-inbound.d.ts +0 -71
  66. package/dist/document-ack-inbound.d.ts.map +0 -1
  67. package/dist/document-ack-inbound.js +0 -210
  68. package/dist/document-ack-inbound.js.map +0 -1
  69. package/dist/document-control-notifier.d.ts +0 -107
  70. package/dist/document-control-notifier.d.ts.map +0 -1
  71. package/dist/document-control-notifier.js +0 -137
  72. package/dist/document-control-notifier.js.map +0 -1
  73. package/dist/document-delivery.d.ts +0 -229
  74. package/dist/document-delivery.d.ts.map +0 -1
  75. package/dist/document-delivery.js +0 -449
  76. package/dist/document-delivery.js.map +0 -1
  77. package/dist/document-join-store.d.ts +0 -80
  78. package/dist/document-join-store.d.ts.map +0 -1
  79. package/dist/document-join-store.js +0 -197
  80. package/dist/document-join-store.js.map +0 -1
@@ -1,449 +0,0 @@
1
- /**
2
- * DOD-DOC-DELIVERY-1 — daemon-autonomous delivery (§16.4).
3
- *
4
- * Publish writes the envelope to the log and returns. Delivery is somebody else's job, and that
5
- * somebody is this worker: it derives what is pending FROM THE LOG, checks the peer is reachable
6
- * before dialing, opens or reuses a session itself, delivers, and records the ack — with zero agent
7
- * attention on either end. Two agents in opposite time zones sync overnight without either agent
8
- * doing anything.
9
- *
10
- * ── PENDING IS DERIVED, NEVER HELD ────────────────────────────────────────────────────────────
11
- *
12
- * "Unacknowledged envelopes I authored" is a WHERE clause over the log, and that is the whole
13
- * definition. A queue in memory does not survive a restart — the daemon is a long-running local
14
- * process that gets restarted routinely — and a queue in its own table is a second source of truth
15
- * that can disagree with the log about what was sent. The attempt counter and the next-attempt
16
- * time live on the envelope row for the same reason: a backoff that resets on restart is not a
17
- * backoff, and a daemon restarting in a reconnect loop would hammer an unreachable peer at full
18
- * rate forever.
19
- *
20
- * ── WHY LOOKUP BEFORE DIAL ────────────────────────────────────────────────────────────────────
21
- *
22
- * §16.4's design is presence-driven push, but there is no presence subscription today (parked,
23
- * M14-P4). Without one, the honest substitute is: ask the directory whether the peer is reachable,
24
- * and if it is not, do not burn a dial — schedule a retry on a capped backoff. Dialing an offline
25
- * peer to find out it is offline is the same information at much higher cost, and it is the cost
26
- * that would be paid on every pending envelope, on every tick, for as long as the peer is away.
27
- */
28
- /**
29
- * Backoff schedule in ms: ~1s, 5s, 30s, 2m, 10m, then the last entry repeats.
30
- *
31
- * The final entry IS the cap — there is no separate ceiling constant. There was one, set to 900s,
32
- * and it was unreachable: the index clamp meant the schedule never produced a value above 600s, so
33
- * the exported "cap" was a number the code could not emit and the tests were using it as a synonym
34
- * for "much later". A documented limit the implementation cannot reach is worse than none.
35
- *
36
- * Capped at all because the peer coming back online is the event we are waiting for and it can
37
- * happen at any moment — an uncapped curve leaves a peer that returned after a long absence waiting
38
- * hours for a delivery that has been ready the whole time.
39
- */
40
- /**
41
- * Total ack-grace one sweep pass may spend, across every agent, document and envelope in it.
42
- *
43
- * The wait exists so a session we opened is not torn down before the peer's answer arrives. It is
44
- * capped as a PASS budget because the loops it sits inside are sequential: a per-envelope allowance
45
- * meant one silent peer with a backlog could hold the sweep for the better part of an hour, and the
46
- * only symptom would be other agents' documents quietly not syncing.
47
- *
48
- * 30s ≈ three full graces. Enough for the ordinary case (one or two opened sessions per pass, ack
49
- * back in well under a second) without letting an unresponsive peer own the pass.
50
- */
51
- export const DELIVERY_ACK_GRACE_BUDGET_MS = 30_000;
52
- export const DELIVERY_BACKOFF_MS = [1_000, 5_000, 30_000, 120_000, 600_000];
53
- export const DELIVERY_BACKOFF_CAP_MS = DELIVERY_BACKOFF_MS[DELIVERY_BACKOFF_MS.length - 1];
54
- /**
55
- * How long to wait for an ACK after a SUCCESSFUL send, before sending again.
56
- *
57
- * Deliberately NOT the failure backoff. "How long do I wait after a failure" and "how long do I
58
- * wait for an answer" are different questions, and reusing the first for the second re-sent a
59
- * successfully-delivered envelope one second later — and every resend is not free: `sendContent`
60
- * witnesses a message-leaf hash to the relay and appends a leaf to the session chain, so a
61
- * never-acked envelope would pollute the peer's sealed conversation record forever.
62
- */
63
- export const DELIVERY_ACK_TIMEOUT_MS = DELIVERY_BACKOFF_CAP_MS;
64
- /**
65
- * How many times an envelope may be SENT without ever being acknowledged before the document
66
- * stalls.
67
- *
68
- * A peer that will never answer must eventually stop being treated as a transient. Without a
69
- * ceiling, an envelope sent to a peer whose client cannot ack — which is every peer until the
70
- * inbound handler ships on both sides — is re-sent forever and is indistinguishable, in the log
71
- * and in `list`, from one that is about to land.
72
- */
73
- export const DELIVERY_MAX_UNACKED_SENDS = 5;
74
- /**
75
- * A document whose peer cannot be resolved is not transient, so it gets the cap immediately rather
76
- * than climbing to it — but it DOES get scheduled. See the `no_peer` branch.
77
- */
78
- export const DELIVERY_UNRESOLVABLE_RETRY_MS = DELIVERY_BACKOFF_CAP_MS;
79
- export function backoffFor(attempts) {
80
- const idx = Math.min(Math.max(attempts, 0), DELIVERY_BACKOFF_MS.length - 1);
81
- return DELIVERY_BACKOFF_MS[idx];
82
- }
83
- export class DocumentDelivery {
84
- #store;
85
- #transport;
86
- #logger;
87
- #inFlight = null;
88
- constructor(store, transport, logger) {
89
- this.#store = store;
90
- this.#transport = transport;
91
- this.#logger = logger;
92
- }
93
- /**
94
- * One pass over what is due. Returns counts rather than throwing on a per-envelope failure: one
95
- * unreachable peer must not stop delivery to every other peer, which is precisely the "works
96
- * only when all nodes are healthy" shape the project forbids.
97
- */
98
- /**
99
- * One pass over what is due, PER (document, holder). Returns counts rather than throwing on a
100
- * per-target failure: one unreachable HOLDER must not stop delivery to any other — the same
101
- * "works only when all nodes are healthy" shape the project forbids, now per holder.
102
- */
103
- async tick(ownerAgentId, holdersFor, nowMs, opts = {}) {
104
- if (this.#inFlight)
105
- return this.#inFlight;
106
- const run = this.#run(ownerAgentId, holdersFor, nowMs, opts);
107
- this.#inFlight = run;
108
- try {
109
- return await run;
110
- }
111
- finally {
112
- this.#inFlight = null;
113
- }
114
- }
115
- async #run(ownerAgentId, holdersFor, nowMs, opts) {
116
- let graceBudgetRemainingMs = DELIVERY_ACK_GRACE_BUDGET_MS;
117
- const correlationId = opts.correlationId ?? `dlv-${ownerAgentId.slice(0, 8)}-${nowMs}`;
118
- const senderAgentId = opts.senderAgentId ?? ownerAgentId;
119
- // LEGACY bilateral rows gain their per-holder twin before anything is read — idempotent
120
- // insurance, journaled (Entry 14): pre-fan-out backlogs are near-empty at alpha.
121
- this.#store.backfillBilateralDeliveries(ownerAgentId, senderAgentId, nowMs);
122
- const pending = this.#store.pendingHolderDeliveries(ownerAgentId, nowMs);
123
- const result = {
124
- attempted: 0, delivered: 0, sent: 0, rejected: 0, deferred: 0, failed: 0,
125
- };
126
- // DOD-MP-INVITE-FANOUT-1 — AMENDMENTS DRAIN FIRST, and the order is the point.
127
- //
128
- // A holder must apply the admitting amendment BEFORE any edit authored at the new epoch,
129
- // otherwise they refuse that edit as coming from a non-participant — the exact symptom seen
130
- // live, where a joiner's edits were silently dropped by a holder still at the old epoch.
131
- // Draining this queue ahead of the envelope queue in every pass makes that ordering a
132
- // guarantee rather than a coincidence of timing; the store's head-of-line rule makes it hold
133
- // ACROSS passes too.
134
- //
135
- // An owed row whose amendment is not in the recorded chain can never be sent (the pending query
136
- // inner-joins the chain, deliberately: a redelivery must never send bytes this daemon's own
137
- // chain does not contain). Such a row is invisible AND owed forever, so it is named rather than
138
- // scanned past in silence.
139
- for (const orphan of this.#store.amendmentDeliveriesWithoutChainRow(ownerAgentId)) {
140
- this.#logger.error("document.amendment.chain_row_missing", {
141
- documentId: orphan.documentId,
142
- amendmentHash: orphan.amendmentHash,
143
- holderAgentId: orphan.holderAgentId,
144
- correlationId,
145
- impact: "this membership change is owed to a holder and its bytes are not in the local chain, " +
146
- "so it can never be delivered — the holder will stay at the old epoch",
147
- });
148
- }
149
- for (const owed of this.#store.pendingAmendmentDeliveries(ownerAgentId, nowMs)) {
150
- const holders = holdersFor(owed.documentId);
151
- if (holders === null) {
152
- // NOT transient, and NOT silent. The envelope pass logs `no_holders` only for documents
153
- // that also have pending ENVELOPES — a document whose content is fully acked has none, so
154
- // this row would otherwise be re-scanned every tick forever with nothing said anywhere.
155
- // Scheduled at the cap so it stops spinning, and logged so it stops being invisible.
156
- this.#store.recordAmendmentAttempt(ownerAgentId, owed.documentId, owed.amendmentHash, owed.holderAgentId, nowMs + DELIVERY_UNRESOLVABLE_RETRY_MS);
157
- this.#logger.error("document.amendment.holders_underivable", {
158
- documentId: owed.documentId,
159
- amendmentHash: owed.amendmentHash,
160
- holderAgentId: owed.holderAgentId,
161
- correlationId,
162
- impact: "the document row is gone or its chain does not derive, so this membership change " +
163
- "cannot be addressed to anyone — it stays owed",
164
- });
165
- continue;
166
- }
167
- // A holder the chain no longer contains, or one it records as removed, is owed nothing.
168
- // RETIRED, never acked: an ack here would make the durable record claim a delivery that
169
- // never happened. Both checks, because the envelope path uses both and a disagreement
170
- // between them would otherwise keep this loop dialing a locally-removed holder.
171
- const removed = this.#store.memberRemoved(ownerAgentId, owed.documentId, owed.holderAgentId);
172
- if (!holders.includes(owed.holderAgentId) || removed.removed) {
173
- this.#store.retireAmendmentDelivery(ownerAgentId, owed.documentId, owed.amendmentHash, owed.holderAgentId, nowMs);
174
- this.#logger.info("document.amendment.holder_retired", {
175
- documentId: owed.documentId,
176
- amendmentHash: owed.amendmentHash,
177
- holderAgentId: owed.holderAgentId,
178
- correlationId,
179
- });
180
- continue;
181
- }
182
- // CLAIM THE ROW BEFORE DIALING — the same rule the envelope path states and for the same
183
- // reason: a crash mid-dial would otherwise leave the row immediately due with `attempts`
184
- // unchanged, so a crash-looping daemon dials at full rate forever and never escalates. It
185
- // also closes the window where the 60s sweep fires inside the invite handler's own await and
186
- // sends the same amendment twice.
187
- const attemptsNow = this.#store.recordAmendmentAttempt(ownerAgentId, owed.documentId, owed.amendmentHash, owed.holderAgentId, nowMs + backoffFor(owed.attempts));
188
- result.attempted += 1;
189
- let sent;
190
- try {
191
- const out = await this.#transport.sendBytes({
192
- peerAgentId: owed.holderAgentId,
193
- documentId: owed.documentId,
194
- bytes: owed.bytes,
195
- correlationId,
196
- });
197
- sent = out.ok ? { ok: true, parked: out.parked === true } : out;
198
- }
199
- catch (err) {
200
- sent = { ok: false, reason: "amendment_send_threw", detail: err instanceof Error ? err.message : String(err) };
201
- }
202
- if (sent.ok && sent.parked !== true) {
203
- // SENT, NOT ACKED. Their daemon received the frame; whether it RECORDED it is a separate
204
- // fact and it can refuse (a chain gap or a failed derivation throws on the receiver and
205
- // answers nothing). The row stays owed and is re-offered, and it settles for real when the
206
- // holder acks any envelope at this epoch or later — which proves they applied it, because
207
- // the inbound epoch gate would have refused that envelope otherwise.
208
- this.#store.markAmendmentSent(ownerAgentId, owed.documentId, owed.amendmentHash, owed.holderAgentId, nowMs, DELIVERY_ACK_TIMEOUT_MS);
209
- result.sent += 1;
210
- this.#logger.info("document.amendment.sent", {
211
- documentId: owed.documentId,
212
- holderAgentId: owed.holderAgentId,
213
- amendmentHash: owed.amendmentHash,
214
- epochId: owed.epochId,
215
- attempts: attemptsNow,
216
- correlationId,
217
- });
218
- }
219
- else {
220
- // PARKED IS NOT DELIVERED. The relay took it because the holder had no live counterparty;
221
- // if that holder never drains it and the debt has been cleared, the membership change is
222
- // gone with both surfaces reporting success. It is a retry, exactly like a refusal.
223
- const reason = sent.ok ? "relay_parked" : sent.reason;
224
- result.failed += 1;
225
- // WARN, NEVER ERROR, and NEVER ABANDONED: a membership change that cannot be delivered yet
226
- // is a retry, not a loss. There is no attempt ceiling here on purpose — abandoning would
227
- // put two holders permanently out of step over exactly the fact they must agree on.
228
- this.#logger.warn("document.amendment.delivery_failed", {
229
- documentId: owed.documentId,
230
- holderAgentId: owed.holderAgentId,
231
- amendmentHash: owed.amendmentHash,
232
- epochId: owed.epochId,
233
- reason,
234
- // The CAUSE, not just the exit-point label. `session_sealed` says where it surfaced;
235
- // detail says why.
236
- detail: sent.ok ? "the relay is holding it — the holder had no live counterparty" : sent.detail,
237
- attempts: attemptsNow,
238
- correlationId,
239
- });
240
- }
241
- }
242
- // Grouped (document, holder): one derivation and one reachability probe serve every pending
243
- // envelope for that pair.
244
- const byDocument = new Map();
245
- for (const p of pending) {
246
- let holders = byDocument.get(p.documentId);
247
- if (!holders) {
248
- holders = new Map();
249
- byDocument.set(p.documentId, holders);
250
- }
251
- const list = holders.get(p.holderAgentId);
252
- if (list)
253
- list.push(p);
254
- else
255
- holders.set(p.holderAgentId, [p]);
256
- }
257
- for (const [documentId, holderGroups] of byDocument) {
258
- const currentHolders = holdersFor(documentId);
259
- if (currentHolders === null) {
260
- // The document row is gone or its chain does not derive — NOT transient. Scheduled at
261
- // the cap so the rows never starve anything, exactly the old no_peer discipline.
262
- this.#logger.error("document.delivery.no_holders", {
263
- documentId,
264
- pending: [...holderGroups.values()].reduce((n, l) => n + l.length, 0),
265
- correlationId,
266
- });
267
- for (const [holder, rows] of holderGroups) {
268
- for (const r of rows) {
269
- this.#store.scheduleHolderRetry(ownerAgentId, documentId, r.envelope.envelopeHash, holder, nowMs + DELIVERY_UNRESOLVABLE_RETRY_MS);
270
- }
271
- result.failed += rows.length;
272
- }
273
- continue;
274
- }
275
- const currentSet = new Set(currentHolders);
276
- for (const [holderAgentId, rows] of holderGroups) {
277
- // A holder the arrangement no longer includes — removed, or never derivable — is
278
- // RETIRED, announced: our decision, not evidence about them (DOD-MP-REMOVE-1's
279
- // delivery-stop clause, generalized per holder).
280
- if (!currentSet.has(holderAgentId) ||
281
- this.#store.memberRemoved(ownerAgentId, documentId, holderAgentId).removed) {
282
- const retiredHashes = this.#store.abandonHolderDeliveries(ownerAgentId, documentId, holderAgentId, nowMs);
283
- for (const hash of retiredHashes) {
284
- this.#store.reconcileEnvelopeSettlement(ownerAgentId, documentId, hash, nowMs);
285
- }
286
- this.#logger.info("document.delivery.peer_removed", {
287
- documentId, holderAgentId, retired: retiredHashes.length, correlationId,
288
- });
289
- continue;
290
- }
291
- let reach;
292
- try {
293
- reach = await this.#transport.isPeerReachable(holderAgentId, correlationId);
294
- }
295
- catch (err) {
296
- // A FAILED LOOKUP IS NOT AN OFFLINE HOLDER — deferred, per holder, without an attempt.
297
- this.#logger.warn("document.delivery.lookup_failed", {
298
- documentId, holderAgentId, correlationId,
299
- reason: err instanceof Error ? err.message : String(err),
300
- });
301
- for (const r of rows) {
302
- // Deferrals ESCALATE the schedule (an offline holder must not be redialed at full
303
- // rate forever) without touching the SENDS ceiling — waiting is not sending.
304
- this.#store.recordHolderAttempt(ownerAgentId, documentId, r.envelope.envelopeHash, holderAgentId, nowMs + backoffFor(r.attempts));
305
- }
306
- result.deferred += rows.length;
307
- continue;
308
- }
309
- if (!reach.reachable) {
310
- this.#logger.info(reach.unknownAgent ? "document.delivery.peer_unknown" : "document.delivery.peer_unreachable", { documentId, holderAgentId, pending: rows.length, correlationId });
311
- for (const r of rows) {
312
- this.#store.recordHolderAttempt(ownerAgentId, documentId, r.envelope.envelopeHash, holderAgentId, nowMs + backoffFor(r.attempts));
313
- }
314
- result.deferred += rows.length;
315
- continue;
316
- }
317
- for (const row of rows) {
318
- const envelope = row.envelope;
319
- result.attempted += 1;
320
- // CLAIM THE ROW BEFORE DIALING — due-forever-on-crash-mid-dial is the same hazard it
321
- // always was, per holder now.
322
- this.#store.recordHolderAttempt(ownerAgentId, documentId, envelope.envelopeHash, holderAgentId, nowMs + backoffFor(row.attempts));
323
- let outcome;
324
- const graceStartedAt = Date.now();
325
- try {
326
- outcome = await this.#transport.deliver({
327
- peerAgentId: holderAgentId,
328
- documentId,
329
- envelope,
330
- ackGraceMs: Math.max(0, graceBudgetRemainingMs),
331
- sessionHint: opts.sessionHints?.get(documentId),
332
- correlationId,
333
- });
334
- }
335
- catch (err) {
336
- outcome = {
337
- ok: false,
338
- reason: "document_delivery_threw",
339
- detail: err instanceof Error ? err.message : String(err),
340
- };
341
- }
342
- finally {
343
- graceBudgetRemainingMs -= Date.now() - graceStartedAt;
344
- }
345
- if (outcome.ok && outcome.admitted === null) {
346
- // IN FLIGHT for THIS holder. Parked and live sends want DIFFERENT retry schedules,
347
- // but both LEFT the machine — the sent-vs-never-left surface counts either (review
348
- // M7: reporting relay-parked content as "never left" mislabels a delivery that the
349
- // relay is holding for them).
350
- this.#store.markHolderDelivered(ownerAgentId, documentId, envelope.envelopeHash, holderAgentId, nowMs);
351
- const sends = this.#store.recordHolderSend(ownerAgentId, documentId, envelope.envelopeHash, holderAgentId);
352
- this.#store.scheduleHolderRetry(ownerAgentId, documentId, envelope.envelopeHash, holderAgentId, nowMs + (outcome.parked ? backoffFor(row.attempts) : DELIVERY_ACK_TIMEOUT_MS));
353
- this.#logger.info("document.delivery.sent", {
354
- documentId,
355
- envelopeHash: envelope.envelopeHash,
356
- holderAgentId,
357
- sessionId: outcome.sessionId,
358
- sessionOpened: outcome.sessionOpened,
359
- unackedSends: sends,
360
- correlationId,
361
- });
362
- result.sent += 1;
363
- if (sends >= DELIVERY_MAX_UNACKED_SENDS) {
364
- // THIS HOLDER is exhausted — retired, announced, and only theirs. The document
365
- // stalls ONLY when every current holder is exhausted: one silent peer stopping a
366
- // living collaboration is the exact availability failure the milestone forbids.
367
- this.#store.abandonSingleHolderDelivery(ownerAgentId, documentId, envelope.envelopeHash, holderAgentId, nowMs);
368
- this.#store.reconcileEnvelopeSettlement(ownerAgentId, documentId, envelope.envelopeHash, nowMs);
369
- this.#logger.error("document.delivery.unacked_limit", {
370
- documentId,
371
- envelopeHash: envelope.envelopeHash,
372
- holderAgentId,
373
- sends,
374
- correlationId,
375
- detail: `this update has been delivered ${sends} times to this holder without their ` +
376
- `daemon ever confirming it — delivery TO THEM is retired; every other holder ` +
377
- `is unaffected. Check document.delivery.ack_grace_expired, ` +
378
- `session.content.held.discarded, and whether their daemon has yet received ` +
379
- `the amendment that added you (their log would show ` +
380
- `document.inbound.sender_unknown_epoch_ahead) before concluding their client ` +
381
- `is at fault.`,
382
- });
383
- const allExhausted = currentHolders
384
- .filter((h) => h !== senderAgentId)
385
- .every((h) => !this.#store.holderHasPending(ownerAgentId, documentId, h));
386
- if (allExhausted) {
387
- this.#store.setDocumentStatus(ownerAgentId, documentId, "stalled");
388
- this.#logger.error("document.delivery.stalled_all_holders", {
389
- documentId, correlationId,
390
- });
391
- }
392
- }
393
- }
394
- else if (outcome.ok) {
395
- const first = this.#store.ackHolderDelivery(ownerAgentId, documentId, envelope.envelopeHash, holderAgentId, nowMs);
396
- // The envelope-level record follows the ONE terminal rule (review M3).
397
- this.#store.reconcileEnvelopeSettlement(ownerAgentId, documentId, envelope.envelopeHash, nowMs);
398
- this.#logger.info("document.delivery.session", {
399
- documentId, holderAgentId, sessionId: outcome.sessionId,
400
- opened: outcome.sessionOpened, correlationId,
401
- });
402
- if (outcome.admitted) {
403
- // PROOF BY EPOCH (DOD-MP-INVITE-FANOUT-1). There is no amendment ack frame, but an
404
- // ADMISSION is one: the inbound epoch gate requires the envelope's epoch to EQUAL the
405
- // receiver's own derived epoch, so a holder that admitted an envelope at epoch E
406
- // demonstrably holds every amendment up to E. Their acceptance of the content is an
407
- // acceptance of the governance that made the content admissible — which settles the
408
- // amendment row on evidence rather than on inference.
409
- //
410
- // ADMITTED ONLY, NEVER MERELY ANSWERED. A rejection is also an ack for delivery
411
- // purposes, and it proves nothing here: the checks that run BEFORE the epoch gate —
412
- // an unknown document, a failed signature — refuse terminally while the holder may be
413
- // at any epoch at all. Settling on those would ack an amendment they do not have,
414
- // which is the exact defect this queue exists to prevent, reintroduced one layer up.
415
- const settled = this.#store.ackAmendmentsThroughEpoch(ownerAgentId, documentId, holderAgentId, envelope.epochId, nowMs);
416
- if (settled > 0) {
417
- this.#logger.info("document.amendment.confirmed_by_epoch", {
418
- documentId, holderAgentId, epochId: envelope.epochId, settled, correlationId,
419
- });
420
- }
421
- this.#logger.info("document.delivery.acked", {
422
- documentId, envelopeHash: envelope.envelopeHash, holderAgentId,
423
- sessionId: outcome.sessionId, firstAck: first, correlationId,
424
- });
425
- result.delivered += 1;
426
- }
427
- else {
428
- this.#logger.warn("document.delivery.rejected", {
429
- documentId, envelopeHash: envelope.envelopeHash, holderAgentId,
430
- sessionId: outcome.sessionId, reason: outcome.rejectionReason, correlationId,
431
- });
432
- result.rejected += 1;
433
- }
434
- }
435
- else {
436
- this.#logger.warn("document.delivery.failed", {
437
- documentId, envelopeHash: envelope.envelopeHash, holderAgentId,
438
- reason: outcome.reason, detail: outcome.detail, attempts: row.attempts + 1,
439
- correlationId,
440
- });
441
- result.failed += 1;
442
- }
443
- }
444
- }
445
- }
446
- return result;
447
- }
448
- }
449
- //# sourceMappingURL=document-delivery.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"document-delivery.js","sourceRoot":"","sources":["../src/document-delivery.ts"],"names":[],"mappings":"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"}
@@ -1,80 +0,0 @@
1
- /**
2
- * DOD-MP-JOIN-1 (daemon half) — the join-offer store: pending consent, both roles, settle-once.
3
- *
4
- * One table for both sides of a join (the `document_proposals` precedent): the INVITEE holds the
5
- * offer they received — as RECEIVED BYTES, validated before recording — and the INVITER holds the
6
- * offer they authored plus the invitee's signed answer when it arrives. Keyed on
7
- * `(owner, amendment_hash)`: the admitting amendment is the fact being consented to, and a
8
- * re-invitation after a refusal is a new amendment with a new hash — a new row, never a
9
- * reopened one.
10
- *
11
- * A refused-at-arrival offer (bad chain, wrong invitee, version mismatch) is RECORDED refused
12
- * with its reason rather than dropped — a dropped offer is indistinguishable from an inviter who
13
- * never sent one.
14
- */
15
- import { type DocumentJoinOffer, type DocumentJoinAnswer } from "@cello-protocol/protocol-types";
16
- import type { DaemonDatabase } from "./sqlcipher-db.js";
17
- import type { Logger } from "./types.js";
18
- export type JoinOfferState = "pending" | "accepted" | "refused";
19
- export type JoinOfferRole = "invitee" | "inviter";
20
- export interface JoinOfferRecord {
21
- documentId: string;
22
- amendmentHash: string;
23
- role: JoinOfferRole;
24
- inviterAgentId: string;
25
- inviteeAgentId: string;
26
- offer: DocumentJoinOffer;
27
- state: JoinOfferState;
28
- reason: string | null;
29
- createdAtMs: number;
30
- decidedAtMs: number | null;
31
- }
32
- export declare class DocumentJoinStore {
33
- #private;
34
- constructor(db: DaemonDatabase, logger: Logger);
35
- /**
36
- * Record an ARRIVING offer under the invitee's key — already validated by the caller; a
37
- * validation refusal is recorded as `refused` with its reason, never dropped. First arrival's
38
- * bytes are the permanent record; a redelivery changes nothing.
39
- */
40
- recordIncoming(ownerAgentId: string, wire: Uint8Array, amendmentHash: string, verdict: {
41
- state: "pending";
42
- } | {
43
- state: "refused";
44
- reason: string;
45
- }, nowMs: number): {
46
- state: JoinOfferState;
47
- reason?: string;
48
- };
49
- /** Record an offer WE authored, pending the invitee's answer. */
50
- recordOutgoing(ownerAgentId: string, wire: Uint8Array, amendmentHash: string, nowMs: number): void;
51
- /**
52
- * The INVITEE's local decision. Settle-once: only a pending row decides, and the caller learns
53
- * whether THIS call decided it — an already-decided offer is a fact to report, not an error.
54
- */
55
- decide(ownerAgentId: string, amendmentHash: string, accepted: boolean, reason: string | null, nowMs: number): {
56
- decided: boolean;
57
- state: JoinOfferState;
58
- };
59
- /**
60
- * Record the invitee's signed ANSWER on the inviter's side. The caller verifies the signature
61
- * against the invitee named in the STORED offer first. Settle-once: a contradicting second
62
- * answer is refused with both records retained (the stored answer stands).
63
- */
64
- recordAnswer(ownerAgentId: string, wire: Uint8Array, verify: (agentId: string, tbs: Uint8Array, signature: Uint8Array) => boolean, nowMs: number): {
65
- ok: true;
66
- answer: DocumentJoinAnswer;
67
- settled: boolean;
68
- } | {
69
- ok: false;
70
- reason: string;
71
- };
72
- get(ownerAgentId: string, amendmentHash: string): JoinOfferRecord | null;
73
- /** Auto-refused arrivals — surfaced so the refusal sentence reaches an operator. */
74
- refusedFor(ownerAgentId: string): JoinOfferRecord[];
75
- /** Offers THIS owner authored — the inviter's view of who has answered what. */
76
- outgoingFor(ownerAgentId: string): JoinOfferRecord[];
77
- /** Offers awaiting THIS owner's consent — the inbox surface. */
78
- pendingFor(ownerAgentId: string): JoinOfferRecord[];
79
- }
80
- //# sourceMappingURL=document-join-store.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"document-join-store.d.ts","sourceRoot":"","sources":["../src/document-join-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAIL,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACxB,MAAM,gCAAgC,CAAC;AACxC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAoBzC,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,CAAC;AAChE,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,SAAS,CAAC;AAElD,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,aAAa,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,iBAAiB,CAAC;IACzB,KAAK,EAAE,cAAc,CAAC;IACtB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,qBAAa,iBAAiB;;gBAIhB,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM;IAM9C;;;;OAIG;IACH,cAAc,CACZ,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,UAAU,EAChB,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE;QAAE,KAAK,EAAE,SAAS,CAAA;KAAE,GAAG;QAAE,KAAK,EAAE,SAAS,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EACpE,KAAK,EAAE,MAAM,GACZ;QAAE,KAAK,EAAE,cAAc,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE;IAmC7C,iEAAiE;IACjE,cAAc,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAqBlG;;;OAGG;IACH,MAAM,CACJ,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,OAAO,EACjB,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,KAAK,EAAE,MAAM,GACZ;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,cAAc,CAAA;KAAE;IAY9C;;;;OAIG;IACH,YAAY,CACV,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,KAAK,OAAO,EAC5E,KAAK,EAAE,MAAM,GACZ;QAAE,EAAE,EAAE,IAAI,CAAC;QAAC,MAAM,EAAE,kBAAkB,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,GAAG;QAAE,EAAE,EAAE,KAAK,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE;IAkE7F,GAAG,CAAC,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI;IASxE,oFAAoF;IACpF,UAAU,CAAC,YAAY,EAAE,MAAM,GAAG,eAAe,EAAE;IAWnD,gFAAgF;IAChF,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,eAAe,EAAE;IAWpD,gEAAgE;IAChE,UAAU,CAAC,YAAY,EAAE,MAAM,GAAG,eAAe,EAAE;CAUpD"}