@cello-protocol/daemon 0.0.166 → 0.0.167

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.
@@ -123,6 +123,122 @@ export class DocumentDelivery {
123
123
  const result = {
124
124
  attempted: 0, delivered: 0, sent: 0, rejected: 0, deferred: 0, failed: 0,
125
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
+ }
126
242
  // Grouped (document, holder): one derivation and one reachability probe serve every pending
127
243
  // envelope for that pair.
128
244
  const byDocument = new Map();
@@ -284,6 +400,24 @@ export class DocumentDelivery {
284
400
  opened: outcome.sessionOpened, correlationId,
285
401
  });
286
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
+ }
287
421
  this.#logger.info("document.delivery.acked", {
288
422
  documentId, envelopeHash: envelope.envelopeHash, holderAgentId,
289
423
  sessionId: outcome.sessionId, firstAck: first, correlationId,
@@ -1 +1 @@
1
- {"version":3,"file":"document-delivery.js","sourceRoot":"","sources":["../src/document-delivery.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"document-delivery.js","sourceRoot":"","sources":["../src/document-delivery.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"document-handlers.d.ts","sourceRoot":"","sources":["../src/document-handlers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAiCH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AAYxE,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,aAAa,CAAC;IACrB,OAAO,EAAE,eAAe,CAAC;IACzB,qFAAqF;IACrF,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,yBAAyB,CAAC;IAC3D,uFAAuF;IACvF,YAAY,CAAC,YAAY,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACrE,mFAAmF;IACnF,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC9C,+BAA+B;IAC/B,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAC9D,GAAG,IAAI,MAAM,CAAC;CACf;AAOD,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,mBAAmB,GAAG,IAAI,CAy+DxE"}
1
+ {"version":3,"file":"document-handlers.d.ts","sourceRoot":"","sources":["../src/document-handlers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAiCH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AAaxE,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,aAAa,CAAC;IACrB,OAAO,EAAE,eAAe,CAAC;IACzB,qFAAqF;IACrF,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,yBAAyB,CAAC;IAC3D,uFAAuF;IACvF,YAAY,CAAC,YAAY,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACrE,mFAAmF;IACnF,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC9C,+BAA+B;IAC/B,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAC9D,GAAG,IAAI,MAAM,CAAC;CACf;AAOD,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,mBAAmB,GAAG,IAAI,CAkmExE"}
@@ -26,6 +26,7 @@
26
26
  import { randomBytes, randomUUID } from "node:crypto";
27
27
  import * as Y from "yjs";
28
28
  import { encodeDocumentProposal, deriveArrangement, documentGovernancePolicy, arrangementGenesisFromProposal, documentAmendmentHash, buildDocumentMultisigTbs, encodeDocumentAmendment, buildDocumentJoinOfferTbs, encodeDocumentJoinOffer, validateDocumentJoinOffer, encodeDocumentUpdateEnvelope, DOCUMENT_UPDATE_ENCODING_V1, buildDocumentProposalTbs, documentIdFromProposal, seamViolation, ASSURANCE_TIER_V1, TOPOLOGY_DEFAULT, DOCUMENT_FEATURE_VERSION, encodeDocumentProposalAck, buildDocumentProposalAckTbs, DOCUMENT_PROPOSAL_ACK_VERSION, MAX_PROPOSAL_REFUSAL_REASON_LENGTH, } from "@cello-protocol/protocol-types";
29
+ import { DELIVERY_ACK_TIMEOUT_MS } from "./document-delivery.js";
29
30
  import { lineHunks, isSupportedDocumentType, SUPPORTED_DOCUMENT_TYPES } from "./document-write-path.js";
30
31
  import { openingNoticeFor, rootForDocumentType } from "./document-types.js";
31
32
  import { projectDocumentText, parseJsonDocument, applyJsonToMap } from "./document-json.js";
@@ -579,6 +580,67 @@ export function registerDocumentHandlers(deps) {
579
580
  : {}),
580
581
  };
581
582
  });
583
+ /**
584
+ * DOD-MP-INVITE-FANOUT-1 — fan a governance amendment to the CURRENT holders, durably.
585
+ *
586
+ * ONE implementation for every site that fans one. There were four — invite, re-invite, remove,
587
+ * and remove's re-send — each with its own copy of the same best-effort loop, and the review found
588
+ * that wiring durability into one of them left the other three losing membership changes exactly
589
+ * as before. The re-invite is the verb the tool's own guidance tells an operator to run when a
590
+ * holder is out of step, so it carrying the defect meant the documented cure did nothing.
591
+ *
592
+ * RECORD THE DEBT FIRST. The send below is a fast path, never the guarantee: a daemon that dies
593
+ * between here and the send still owes the amendment on restart.
594
+ *
595
+ * A successful send is recorded as SENT, not acked — their daemon received the frame, and whether
596
+ * it RECORDED it is a separate fact it can refuse. The row settles for real when that holder acks
597
+ * any envelope at this epoch or later, which proves they applied it.
598
+ */
599
+ const fanOutAmendment = async (args) => {
600
+ layer.store.seedAmendmentDeliveries(args.ownerAgentId, args.documentId, args.amendmentHashHex, args.holders, deps.now());
601
+ const told = {};
602
+ for (const holder of args.holders) {
603
+ try {
604
+ const sent = await deps.transportFor(args.agentName).sendBytes({
605
+ peerAgentId: holder,
606
+ documentId: args.documentId,
607
+ bytes: args.amendmentBytes,
608
+ correlationId: randomUUID(),
609
+ });
610
+ // PARKED IS NOT NOTIFIED. The relay took it because the holder had no live counterparty.
611
+ const landed = sent.ok && sent.parked !== true;
612
+ told[holder] = landed;
613
+ if (landed) {
614
+ layer.store.markAmendmentSent(args.ownerAgentId, args.documentId, args.amendmentHashHex, holder, deps.now(), DELIVERY_ACK_TIMEOUT_MS);
615
+ }
616
+ else {
617
+ // NAMED, NOT JUST COUNTED. This used to record `false` with no log line anywhere, so the
618
+ // only trace of a lost membership change was a boolean inside an `ok: true` response.
619
+ logger.warn("document.amendment.holder_unnotified", {
620
+ documentId: args.documentId,
621
+ holderAgentId: holder,
622
+ verb: args.verb,
623
+ reason: sent.ok ? "relay_parked" : sent.reason,
624
+ detail: sent.ok
625
+ ? "the relay is holding it — the holder had no live counterparty"
626
+ : sent.detail,
627
+ });
628
+ }
629
+ }
630
+ catch (err) {
631
+ told[holder] = false;
632
+ // A throw used to be swallowed whole.
633
+ logger.warn("document.amendment.holder_unnotified", {
634
+ documentId: args.documentId,
635
+ holderAgentId: holder,
636
+ verb: args.verb,
637
+ reason: "amendment_send_threw",
638
+ detail: err instanceof Error ? err.message : String(err),
639
+ });
640
+ }
641
+ }
642
+ return told;
643
+ };
582
644
  /**
583
645
  * M14B / DOD-MP-JOIN-1 — invite a third party into an existing document.
584
646
  *
@@ -670,24 +732,20 @@ export function registerDocumentHandlers(deps) {
670
732
  // re-sent the amendment. The re-invite is the healing verb: it re-fans the admitting
671
733
  // amendment to every other current holder, best-effort, reported per holder.
672
734
  const admittingBytes = outgoing.offer.amendments[outgoing.offer.amendments.length - 1];
673
- const holdersNotified = {};
674
- if (admittingBytes !== undefined) {
675
- for (const holder of derived.arrangement.participants) {
676
- if (holder === who.ownerAgentId || holder === invitee)
677
- continue;
678
- try {
679
- const sentAmend = await deps.transportFor(who.agentName).sendBytes({
680
- peerAgentId: holder,
681
- documentId,
682
- bytes: new Uint8Array(admittingBytes),
683
- correlationId: randomUUID(),
684
- });
685
- holdersNotified[holder] = sentAmend.ok;
686
- }
687
- catch {
688
- holdersNotified[holder] = false;
689
- }
690
- }
735
+ let holdersNotified = {};
736
+ // `priorHash` is non-null whenever `outgoing` is — the lookup is keyed by it — but the
737
+ // narrowing does not survive the branch, and an amendment seeded under a null key would be
738
+ // owed to a row nothing can ever join.
739
+ if (admittingBytes !== undefined && priorHash !== null) {
740
+ holdersNotified = await fanOutAmendment({
741
+ agentName: who.agentName,
742
+ ownerAgentId: who.ownerAgentId,
743
+ documentId,
744
+ amendmentHashHex: priorHash,
745
+ amendmentBytes: new Uint8Array(admittingBytes),
746
+ holders: [...derived.arrangement.participants].filter((holder) => holder !== who.ownerAgentId && holder !== invitee),
747
+ verb: "re-invite",
748
+ });
691
749
  }
692
750
  return {
693
751
  ok: true,
@@ -793,20 +851,25 @@ export function registerDocumentHandlers(deps) {
793
851
  documentId, error: err instanceof Error ? err.message : String(err),
794
852
  });
795
853
  }
796
- const holdersTold = {};
797
- for (const holder of derived.arrangement.participants) {
798
- if (holder === who.ownerAgentId || holder === invitee)
799
- continue;
800
- try {
801
- const sent = await deps.transportFor(who.agentName).sendBytes({
802
- peerAgentId: holder, documentId, bytes: amendmentBytes, correlationId: randomUUID(),
803
- });
804
- holdersTold[holder] = sent.ok;
805
- }
806
- catch {
807
- holdersTold[holder] = false;
808
- }
809
- }
854
+ // DOD-MP-INVITE-FANOUT-1 RECORD WHAT IS OWED BEFORE TRYING TO SEND IT.
855
+ //
856
+ // The loop below is a fast path, not the guarantee. It used to be both, and that is the whole
857
+ // defect: one failed send lost a membership change permanently, because nothing remained owing
858
+ // anywhere. A content edit has always had a pending row, a retry schedule and restart survival;
859
+ // the governance act that decides who is a party to the document had none of them.
860
+ //
861
+ // Seeding first also makes the crash window safe: a daemon that dies between here and the send
862
+ // still owes the amendment on restart.
863
+ const owedHolders = [...derived.arrangement.participants].filter((holder) => holder !== who.ownerAgentId && holder !== invitee);
864
+ const holdersTold = await fanOutAmendment({
865
+ agentName: who.agentName,
866
+ ownerAgentId: who.ownerAgentId,
867
+ documentId,
868
+ amendmentHashHex: amendHashHex,
869
+ amendmentBytes,
870
+ holders: owedHolders,
871
+ verb: "invite",
872
+ });
810
873
  logger.info("document.join.invited", { documentId, invitee, epochId: body.epoch_id, offerSent });
811
874
  return {
812
875
  ok: true,
@@ -879,20 +942,31 @@ export function registerDocumentHandlers(deps) {
879
942
  const removal = chain.find((e) => e.body.kind === "remove_holder" &&
880
943
  e.body.subject_agent_id === holder &&
881
944
  e.body.epoch_id === membership.epochId);
882
- const resendTold = {};
945
+ let resendTold = {};
883
946
  if (removal) {
884
947
  const bytes = new Uint8Array(encodeDocumentAmendment(removal));
885
- const targets = new Set([...derived.arrangement.participants, holder]);
886
- targets.delete(who.ownerAgentId);
887
- for (const member of targets) {
948
+ const remaining = [...derived.arrangement.participants].filter((m) => m !== who.ownerAgentId && m !== holder);
949
+ // The healing re-send is durable for the holders who REMAIN, for the same reason the
950
+ // re-invite is: it is the verb an operator runs precisely because someone is out of step,
951
+ // so it must not be the one that gives up quietest.
952
+ resendTold = await fanOutAmendment({
953
+ agentName: who.agentName,
954
+ ownerAgentId: who.ownerAgentId,
955
+ documentId,
956
+ amendmentHashHex: Buffer.from(documentAmendmentHash(removal.body)).toString("hex"),
957
+ amendmentBytes: bytes,
958
+ holders: remaining,
959
+ verb: "remove-resend",
960
+ });
961
+ if (holder !== who.ownerAgentId) {
888
962
  try {
889
963
  const sent = await deps.transportFor(who.agentName).sendBytes({
890
- peerAgentId: member, documentId, bytes, correlationId: randomUUID(),
964
+ peerAgentId: holder, documentId, bytes, correlationId: randomUUID(),
891
965
  });
892
- resendTold[member] = sent.ok;
966
+ resendTold[holder] = sent.ok && sent.parked !== true;
893
967
  }
894
968
  catch {
895
- resendTold[member] = false;
969
+ resendTold[holder] = false;
896
970
  }
897
971
  }
898
972
  }
@@ -957,29 +1031,43 @@ export function registerDocumentHandlers(deps) {
957
1031
  // The amendment travels to EVERY current holder INCLUDING the removed one — being told is
958
1032
  // how their daemon surfaces the removal to their operator. Best-effort at P1, per holder,
959
1033
  // reported never assumed.
960
- const holdersTold = {};
961
- for (const member of withNew.arrangement.participants) {
962
- if (member === who.ownerAgentId)
963
- continue;
964
- try {
965
- const sent = await deps.transportFor(who.agentName).sendBytes({
966
- peerAgentId: member, documentId, bytes: amendmentBytes, correlationId: randomUUID(),
967
- });
968
- holdersTold[member] = sent.ok;
969
- }
970
- catch {
971
- holdersTold[member] = false;
972
- }
973
- }
1034
+ // DOD-MP-INVITE-FANOUT-1 the REMAINING holders get the durable fan-out. A holder who misses
1035
+ // a removal keeps delivering to, and accepting edits from, someone the chain has removed —
1036
+ // silently and permanently, which is the same defect the invite had and is worse, because here
1037
+ // the stale holder keeps honouring a membership that has been revoked.
1038
+ const holdersTold = await fanOutAmendment({
1039
+ agentName: who.agentName,
1040
+ ownerAgentId: who.ownerAgentId,
1041
+ documentId,
1042
+ amendmentHashHex: Buffer.from(amendHash).toString("hex"),
1043
+ amendmentBytes,
1044
+ holders: [...withNew.arrangement.participants].filter((m) => m !== who.ownerAgentId),
1045
+ verb: "remove",
1046
+ });
1047
+ // THE REMOVED HOLDER IS TOLD ONCE, and is deliberately NOT owed a durable retry: delivery to
1048
+ // them stopping is what removal MEANS, so a queue that kept redialling them would contradict
1049
+ // the act it is announcing. Forward-only cuts both ways — we tell them, we do not pursue them.
974
1050
  if (holder !== who.ownerAgentId) {
975
1051
  try {
976
1052
  const sent = await deps.transportFor(who.agentName).sendBytes({
977
1053
  peerAgentId: holder, documentId, bytes: amendmentBytes, correlationId: randomUUID(),
978
1054
  });
979
- holdersTold[holder] = sent.ok;
1055
+ holdersTold[holder] = sent.ok && sent.parked !== true;
1056
+ if (!holdersTold[holder]) {
1057
+ logger.warn("document.amendment.holder_unnotified", {
1058
+ documentId, holderAgentId: holder, verb: "remove-subject",
1059
+ reason: sent.ok ? "relay_parked" : sent.reason,
1060
+ detail: sent.ok ? "the relay is holding it" : sent.detail,
1061
+ });
1062
+ }
980
1063
  }
981
- catch {
1064
+ catch (err) {
982
1065
  holdersTold[holder] = false;
1066
+ logger.warn("document.amendment.holder_unnotified", {
1067
+ documentId, holderAgentId: holder, verb: "remove-subject",
1068
+ reason: "amendment_send_threw",
1069
+ detail: err instanceof Error ? err.message : String(err),
1070
+ });
983
1071
  }
984
1072
  }
985
1073
  logger.info("document.holder_removed", {
@@ -1778,7 +1866,14 @@ export function registerDocumentHandlers(deps) {
1778
1866
  // Waiting cannot reopen a sealed session. The cause is known per holder; it travels.
1779
1867
  const causes = [...new Set(Object.values(holderFailures ?? {}))].filter(Boolean);
1780
1868
  const because = causes.length > 0 ? ` (${causes.join(", ")})` : "";
1781
- const sealed = causes.some((c) => c.includes("sealed"));
1869
+ // THE WHOLE FAMILY, not one substring. This tested `includes("sealed")`, so `session_sealed`
1870
+ // got the useful sentence and every other way a session's record can be over —
1871
+ // `relay_session_gone` (the relay restarted or swept it) and `session_not_found` — fell to
1872
+ // generic wait-for-them advice, which is the one thing that cannot work when there is nothing
1873
+ // left to wait for.
1874
+ const sealed = causes.some((c) => c.includes("sealed") ||
1875
+ c.includes("relay_session_gone") ||
1876
+ c.includes("session_not_found"));
1782
1877
  return (`Your ${verb} was recorded but reached none of the ${missed.length} other ` +
1783
1878
  `holder${missed.length > 1 ? "s" : ""} (${missed.join(", ")})${because}, so the document ` +
1784
1879
  `cannot settle until they hear it. ` +