@cello-protocol/daemon 0.0.188 → 0.0.189

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.
@@ -81,6 +81,20 @@ export type ContentEncryptionReason = (typeof CONTENT_ENCRYPTION_REASONS)[keyof
81
81
  * reassurance attached to a fault is worse than both.
82
82
  */
83
83
  export declare const CONTENT_ENCRYPTION_GUIDANCE: Record<ContentEncryptionReason, string>;
84
+ /**
85
+ * ⚠️ **THE SAME REASONS, TOLD TO THE OTHER DIRECTION** — `029c` review F6.
86
+ *
87
+ * `CONTENT_ENCRYPTION_GUIDANCE` above is written for the SEND path: it explains what became of a
88
+ * message THIS operator tried to send. The inbound refusal (`no_session_key`) was reusing it
89
+ * verbatim, so an operator who could not open an INCOMING message read advice about their own
90
+ * outbound mail — *"A message sent before it completes … goes to your counterparty's relay
91
+ * mailbox"* — two directions and two mailboxes in one paragraph.
92
+ *
93
+ * The CAUSE is identical, so the reason set is shared; only the consequence differs, so only the
94
+ * prose is. Total over the union for the same reason the other map is: a new reason cannot be added
95
+ * without deciding what it means to the receiving side.
96
+ */
97
+ export declare const CONTENT_ENCRYPTION_INBOUND_GUIDANCE: Record<ContentEncryptionReason, string>;
84
98
  /**
85
99
  * Render a reason for an agent.
86
100
  *
@@ -1 +1 @@
1
- {"version":3,"file":"content-encryption-status.d.ts","sourceRoot":"","sources":["../src/content-encryption-status.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,6BAA6B,2BAA2B,CAAC;AAEtE,eAAO,MAAM,0BAA0B;IACrC;;;OAGG;;IAEH;;;;;;OAMG;;IAEH,mGAAmG;;IAEnG;;;;;;;;OAQG;;IAEH;;;;;OAKG;;CAEK,CAAC;AAEX,MAAM,MAAM,uBAAuB,GACjC,CAAC,OAAO,0BAA0B,CAAC,CAAC,MAAM,OAAO,0BAA0B,CAAC,CAAC;AAE/E;;;;;;GAMG;AACH,eAAO,MAAM,2BAA2B,EAAE,MAAM,CAAC,uBAAuB,EAAE,MAAM,CA6B/E,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,uBAAuB,GAAG,MAAM,CAEpF"}
1
+ {"version":3,"file":"content-encryption-status.d.ts","sourceRoot":"","sources":["../src/content-encryption-status.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,6BAA6B,2BAA2B,CAAC;AAEtE,eAAO,MAAM,0BAA0B;IACrC;;;OAGG;;IAEH;;;;;;OAMG;;IAEH,mGAAmG;;IAEnG;;;;;;;;OAQG;;IAEH;;;;;OAKG;;CAEK,CAAC;AAEX,MAAM,MAAM,uBAAuB,GACjC,CAAC,OAAO,0BAA0B,CAAC,CAAC,MAAM,OAAO,0BAA0B,CAAC,CAAC;AAE/E;;;;;;GAMG;AACH,eAAO,MAAM,2BAA2B,EAAE,MAAM,CAAC,uBAAuB,EAAE,MAAM,CA6B/E,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,mCAAmC,EAAE,MAAM,CAAC,uBAAuB,EAAE,MAAM,CA2BvF,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,uBAAuB,GAAG,MAAM,CAEpF"}
@@ -104,6 +104,42 @@ export const CONTENT_ENCRYPTION_GUIDANCE = {
104
104
  "their daemon is not answering. Check they are online, then start a new session. Nothing was sent " +
105
105
  "in the open in the meantime.",
106
106
  };
107
+ /**
108
+ * ⚠️ **THE SAME REASONS, TOLD TO THE OTHER DIRECTION** — `029c` review F6.
109
+ *
110
+ * `CONTENT_ENCRYPTION_GUIDANCE` above is written for the SEND path: it explains what became of a
111
+ * message THIS operator tried to send. The inbound refusal (`no_session_key`) was reusing it
112
+ * verbatim, so an operator who could not open an INCOMING message read advice about their own
113
+ * outbound mail — *"A message sent before it completes … goes to your counterparty's relay
114
+ * mailbox"* — two directions and two mailboxes in one paragraph.
115
+ *
116
+ * The CAUSE is identical, so the reason set is shared; only the consequence differs, so only the
117
+ * prose is. Total over the union for the same reason the other map is: a new reason cannot be added
118
+ * without deciding what it means to the receiving side.
119
+ */
120
+ export const CONTENT_ENCRYPTION_INBOUND_GUIDANCE = {
121
+ [CONTENT_ENCRYPTION_REASONS.NOT_YET_AGREED]: "This conversation had not finished agreeing its encryption key when their message arrived, " +
122
+ "which normally completes within a second of you both being connected. Nothing is wrong with " +
123
+ "their message or their build. If it keeps happening, one of you is not staying connected long " +
124
+ "enough for the exchange to finish.",
125
+ [CONTENT_ENCRYPTION_REASONS.NO_LOCAL_IDENTITY]: "THIS machine has no identity key available for this agent, so it cannot take part in the " +
126
+ "encryption exchange at all — and every conversation it opens has the same problem. Your " +
127
+ "counterparty did nothing and does not need to change anything. Check that this agent was " +
128
+ "loaded with its identity key, then start a new conversation.",
129
+ [CONTENT_ENCRYPTION_REASONS.OUR_ANNOUNCE_FAILED]: "THIS side never sent its half of the encryption key, so your counterparty could not finish the " +
130
+ "exchange and you cannot open what they sent. The fault is local — do not raise it with them. " +
131
+ "Look for session.key.announce.failed for the connection error; it re-announces on the next " +
132
+ "connect, so a new conversation usually clears it.",
133
+ [CONTENT_ENCRYPTION_REASONS.KEY_REFUSED]: "STOPPED ON PURPOSE. The encryption key your counterparty sent could not be tied to them, so " +
134
+ "this conversation was stopped rather than carried on in the open — which is why their message " +
135
+ "cannot be opened now. The ordinary cause is a build mismatch. The one that matters is " +
136
+ "something between you substituting its own key so it can read what you exchange. Confirm with " +
137
+ "them OUT OF BAND, not over CELLO, before opening another conversation.",
138
+ [CONTENT_ENCRYPTION_REASONS.PEER_SILENT]: "Your counterparty never sent their half of the encryption key, so there is nothing here to " +
139
+ "open their message with. They are running the same protocol, so this is not a version " +
140
+ "difference — either the frame was dropped between you, or their daemon is not answering. " +
141
+ "Check they are online, then start a new conversation.",
142
+ };
107
143
  /**
108
144
  * Render a reason for an agent.
109
145
  *
@@ -1 +1 @@
1
- {"version":3,"file":"content-encryption-status.js","sourceRoot":"","sources":["../src/content-encryption-status.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAG,wBAAwB,CAAC;AAEtE,MAAM,CAAC,MAAM,0BAA0B,GAAG;IACxC;;;OAGG;IACH,cAAc,EAAE,gBAAgB;IAChC;;;;;;OAMG;IACH,iBAAiB,EAAE,mBAAmB;IACtC,mGAAmG;IACnG,mBAAmB,EAAE,qBAAqB;IAC1C;;;;;;;;OAQG;IACH,WAAW,EAAE,aAAa;IAC1B;;;;;OAKG;IACH,WAAW,EAAE,aAAa;CAClB,CAAC;AAKX;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAA4C;IAClF,CAAC,0BAA0B,CAAC,cAAc,CAAC,EACzC,kGAAkG;QAClG,+FAA+F;QAC/F,6FAA6F;QAC7F,iGAAiG;QACjG,4FAA4F;QAC5F,yDAAyD;IAC3D,CAAC,0BAA0B,CAAC,iBAAiB,CAAC,EAC5C,+FAA+F;QAC/F,kGAAkG;QAClG,mGAAmG;QACnG,gCAAgC;IAClC,CAAC,0BAA0B,CAAC,mBAAmB,CAAC,EAC9C,8FAA8F;QAC9F,qFAAqF;QACrF,mGAAmG;QACnG,0FAA0F;IAC5F,CAAC,0BAA0B,CAAC,WAAW,CAAC,EACtC,6FAA6F;QAC7F,gGAAgG;QAChG,+FAA+F;QAC/F,+FAA+F;QAC/F,qFAAqF;IACvF,CAAC,0BAA0B,CAAC,WAAW,CAAC,EACtC,mGAAmG;QACnG,+FAA+F;QAC/F,mGAAmG;QACnG,8BAA8B;CACjC,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,4BAA4B,CAAC,MAA+B;IAC1E,OAAO,2BAA2B,CAAC,MAAM,CAAC,CAAC;AAC7C,CAAC"}
1
+ {"version":3,"file":"content-encryption-status.js","sourceRoot":"","sources":["../src/content-encryption-status.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAG,wBAAwB,CAAC;AAEtE,MAAM,CAAC,MAAM,0BAA0B,GAAG;IACxC;;;OAGG;IACH,cAAc,EAAE,gBAAgB;IAChC;;;;;;OAMG;IACH,iBAAiB,EAAE,mBAAmB;IACtC,mGAAmG;IACnG,mBAAmB,EAAE,qBAAqB;IAC1C;;;;;;;;OAQG;IACH,WAAW,EAAE,aAAa;IAC1B;;;;;OAKG;IACH,WAAW,EAAE,aAAa;CAClB,CAAC;AAKX;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAA4C;IAClF,CAAC,0BAA0B,CAAC,cAAc,CAAC,EACzC,kGAAkG;QAClG,+FAA+F;QAC/F,6FAA6F;QAC7F,iGAAiG;QACjG,4FAA4F;QAC5F,yDAAyD;IAC3D,CAAC,0BAA0B,CAAC,iBAAiB,CAAC,EAC5C,+FAA+F;QAC/F,kGAAkG;QAClG,mGAAmG;QACnG,gCAAgC;IAClC,CAAC,0BAA0B,CAAC,mBAAmB,CAAC,EAC9C,8FAA8F;QAC9F,qFAAqF;QACrF,mGAAmG;QACnG,0FAA0F;IAC5F,CAAC,0BAA0B,CAAC,WAAW,CAAC,EACtC,6FAA6F;QAC7F,gGAAgG;QAChG,+FAA+F;QAC/F,+FAA+F;QAC/F,qFAAqF;IACvF,CAAC,0BAA0B,CAAC,WAAW,CAAC,EACtC,mGAAmG;QACnG,+FAA+F;QAC/F,mGAAmG;QACnG,8BAA8B;CACjC,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,mCAAmC,GAA4C;IAC1F,CAAC,0BAA0B,CAAC,cAAc,CAAC,EACzC,6FAA6F;QAC7F,8FAA8F;QAC9F,gGAAgG;QAChG,oCAAoC;IACtC,CAAC,0BAA0B,CAAC,iBAAiB,CAAC,EAC5C,2FAA2F;QAC3F,0FAA0F;QAC1F,2FAA2F;QAC3F,8DAA8D;IAChE,CAAC,0BAA0B,CAAC,mBAAmB,CAAC,EAC9C,iGAAiG;QACjG,+FAA+F;QAC/F,6FAA6F;QAC7F,mDAAmD;IACrD,CAAC,0BAA0B,CAAC,WAAW,CAAC,EACtC,8FAA8F;QAC9F,gGAAgG;QAChG,wFAAwF;QACxF,gGAAgG;QAChG,wEAAwE;IAC1E,CAAC,0BAA0B,CAAC,WAAW,CAAC,EACtC,6FAA6F;QAC7F,wFAAwF;QACxF,2FAA2F;QAC3F,uDAAuD;CAC1D,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,4BAA4B,CAAC,MAA+B;IAC1E,OAAO,2BAA2B,CAAC,MAAM,CAAC,CAAC;AAC7C,CAAC"}
@@ -10,6 +10,37 @@ export declare class ContentParkRefusedError extends Error {
10
10
  readonly reason: string;
11
11
  constructor(reason: string);
12
12
  }
13
+ /** One relay address `#open` tried to dial, and why that dial failed. */
14
+ export interface ParkDialFailure {
15
+ addr: string;
16
+ error: string;
17
+ }
18
+ /**
19
+ * DOD-M15-PARKCONN-1 — the content-park stream could not be opened, WITH the reason there was
20
+ * nothing to open it on.
21
+ *
22
+ * `#open` dials before it opens a stream, and it used to discard every dial failure in an empty
23
+ * `catch`. That catch was the only place the reason for a missing connection ever existed, so an
24
+ * operator messaging an offline counterparty was told `No open connection to peer 12D3Koo…` — that
25
+ * there was no connection, never why — and the same action parked or failed with nothing to tell
26
+ * the two apart.
27
+ *
28
+ * A real `Error` (so `instanceof Error` and `extractErrorMessage` both work on it — the transport
29
+ * throws plain object literals, which stringify to "[object Object]") carrying the transport's own
30
+ * `reason` under the same field name the literal used, so existing `err.reason` readers are
31
+ * unaffected.
32
+ */
33
+ export declare class ContentParkUnreachableError extends Error {
34
+ readonly reason: string;
35
+ readonly relayPeerId: string;
36
+ readonly dialFailures: readonly ParkDialFailure[];
37
+ constructor(args: {
38
+ reason: string;
39
+ relayPeerId: string;
40
+ dialFailures: readonly ParkDialFailure[];
41
+ cause: string;
42
+ });
43
+ }
13
44
  /** A single parked entry returned by pull(). */
14
45
  export interface ParkedEntry {
15
46
  contentHashHex: string;
@@ -1 +1 @@
1
- {"version":3,"file":"content-park-client.d.ts","sourceRoot":"","sources":["../src/content-park-client.ts"],"names":[],"mappings":"AA6BA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAE1D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAiBzC;;;;GAIG;AACH,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBACZ,MAAM,EAAE,MAAM;CAK3B;AAED,gDAAgD;AAChD,MAAM,WAAW,WAAW;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,UAAU,CAAC;CACxB;AAED,MAAM,WAAW,wBAAwB;IACvC,sFAAsF;IACtF,WAAW,EAAE,MAAM,CAAC;IACpB,gCAAgC;IAChC,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,iBAAiB;;gBAKhB,IAAI,EAAE,wBAAwB;IAM1C;;;;OAIG;IACG,OAAO,CACX,IAAI,EAAE,SAAS,EACf,IAAI,EAAE;QAAE,eAAe,EAAE,UAAU,CAAC;QAAC,WAAW,EAAE,UAAU,CAAC;QAAC,SAAS,EAAE,UAAU,CAAC;QAAC,UAAU,EAAE,UAAU,CAAA;KAAE,GAC5G,OAAO,CAAC;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IA8CnE;;;;OAIG;IACG,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAiFrG;;;;;;OAMG;IACG,OAAO,CAAC,IAAI,EAAE,SAAS,EAAE,eAAe,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC;CAmF5H"}
1
+ {"version":3,"file":"content-park-client.d.ts","sourceRoot":"","sources":["../src/content-park-client.ts"],"names":[],"mappings":"AA6BA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAG1D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAiBzC;;;;GAIG;AACH,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBACZ,MAAM,EAAE,MAAM;CAK3B;AAED,yEAAyE;AACzE,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;;;;;;GAcG;AACH,qBAAa,2BAA4B,SAAQ,KAAK;IACpD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,YAAY,EAAE,SAAS,eAAe,EAAE,CAAC;gBAEtC,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,SAAS,eAAe,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE;CAUnH;AAED,gDAAgD;AAChD,MAAM,WAAW,WAAW;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,UAAU,CAAC;CACxB;AAED,MAAM,WAAW,wBAAwB;IACvC,sFAAsF;IACtF,WAAW,EAAE,MAAM,CAAC;IACpB,gCAAgC;IAChC,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,iBAAiB;;gBAKhB,IAAI,EAAE,wBAAwB;IAM1C;;;;OAIG;IACG,OAAO,CACX,IAAI,EAAE,SAAS,EACf,IAAI,EAAE;QAAE,eAAe,EAAE,UAAU,CAAC;QAAC,WAAW,EAAE,UAAU,CAAC;QAAC,SAAS,EAAE,UAAU,CAAC;QAAC,UAAU,EAAE,UAAU,CAAA;KAAE,GAC5G,OAAO,CAAC;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IA8CnE;;;;OAIG;IACG,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAiFrG;;;;;;OAMG;IACG,OAAO,CAAC,IAAI,EAAE,SAAS,EAAE,eAAe,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC;CA2I5H"}
@@ -27,6 +27,7 @@ import * as lp from "it-length-prefixed";
27
27
  import { decode } from "cbor-x";
28
28
  import { encodeCbor } from "@cello-protocol/protocol-types";
29
29
  import { CONTENT_PARK_PROTOCOL_ID, buildContentParkAuthMsg } from "@cello-protocol/protocol-types";
30
+ import { extractErrorMessage } from "./error-message.js";
30
31
  const FRAME_TIMEOUT_MS = 8_000;
31
32
  function toU8(chunk) {
32
33
  if (chunk instanceof Uint8Array)
@@ -56,6 +57,36 @@ export class ContentParkRefusedError extends Error {
56
57
  this.reason = reason;
57
58
  }
58
59
  }
60
+ /**
61
+ * DOD-M15-PARKCONN-1 — the content-park stream could not be opened, WITH the reason there was
62
+ * nothing to open it on.
63
+ *
64
+ * `#open` dials before it opens a stream, and it used to discard every dial failure in an empty
65
+ * `catch`. That catch was the only place the reason for a missing connection ever existed, so an
66
+ * operator messaging an offline counterparty was told `No open connection to peer 12D3Koo…` — that
67
+ * there was no connection, never why — and the same action parked or failed with nothing to tell
68
+ * the two apart.
69
+ *
70
+ * A real `Error` (so `instanceof Error` and `extractErrorMessage` both work on it — the transport
71
+ * throws plain object literals, which stringify to "[object Object]") carrying the transport's own
72
+ * `reason` under the same field name the literal used, so existing `err.reason` readers are
73
+ * unaffected.
74
+ */
75
+ export class ContentParkUnreachableError extends Error {
76
+ reason;
77
+ relayPeerId;
78
+ dialFailures;
79
+ constructor(args) {
80
+ const dials = args.dialFailures.length > 0
81
+ ? ` Dials tried: ${args.dialFailures.map((f) => `${f.addr} → ${f.error}`).join("; ")}`
82
+ : " No dial failed, so the connection existed or was never attempted.";
83
+ super(`content park relay ${args.relayPeerId} is unreachable (${args.reason}): ${args.cause}.${dials}`);
84
+ this.name = "ContentParkUnreachableError";
85
+ this.reason = args.reason;
86
+ this.relayPeerId = args.relayPeerId;
87
+ this.dialFailures = args.dialFailures;
88
+ }
89
+ }
59
90
  export class ContentParkClient {
60
91
  #relayPeerId;
61
92
  #relayAddrs;
@@ -250,18 +281,72 @@ export class ContentParkClient {
250
281
  await stream.close().catch(() => { });
251
282
  }
252
283
  }
253
- /** Dial the relay (best-effort per addr) and open a content-park stream. */
284
+ /**
285
+ * Dial the relay (best-effort per addr) and open a content-park stream.
286
+ *
287
+ * DOD-M15-PARKCONN-1 — **A DIAL FAILURE IS A NON-EVENT UNTIL THE STREAM ALSO FAILS, AND THEN IT
288
+ * IS THE ONLY EVIDENCE THERE IS.**
289
+ *
290
+ * The loop stays best-effort on purpose: the peerstore may already hold a connection, so a dial
291
+ * that fails while `newStream` succeeds anyway explains nothing and must stay silent. What used to
292
+ * happen as well is that the dial errors were discarded in ALL cases, including the one where
293
+ * `newStream` then reported `no_connection` — and the throw site's own comment calls that "the one
294
+ * condition a dial fixes". A dial had run; its verdict had been deleted by this catch.
295
+ *
296
+ * Collected here and surfaced only on the failing path, which splits the two causes an operator
297
+ * otherwise cannot tell apart: every address was unusable, or a dial succeeded and the connection
298
+ * was gone again a moment later.
299
+ */
254
300
  async #open(node) {
301
+ const dialFailures = [];
255
302
  for (const addr of this.#relayAddrs) {
256
303
  try {
257
304
  await node.dial(addr);
258
305
  break;
259
306
  }
260
- catch {
261
- /* try the next addr; newStream below may still succeed from the peerstore */
307
+ catch (err) {
308
+ // extractErrorMessage, NOT String(err): the transport rejects with plain object literals.
309
+ dialFailures.push({ addr, error: extractErrorMessage(err) });
262
310
  }
263
311
  }
264
- return node.newStream(this.#relayPeerId, CONTENT_PARK_PROTOCOL_ID);
312
+ try {
313
+ return await node.newStream(this.#relayPeerId, CONTENT_PARK_PROTOCOL_ID);
314
+ }
315
+ catch (err) {
316
+ // The transport's own reason (`no_connection`, `node_stopped`, `invalid_peer_id`, …) survives
317
+ // to the caller — Invariant 3: a downstream handler must not overwrite it with a generic one.
318
+ const reason = err !== null && typeof err === "object" && typeof err.reason === "string"
319
+ ? err.reason
320
+ : "stream_open_failed";
321
+ // The loop `break`s on the first success, so fewer failures than addresses means one worked.
322
+ const dialOutcome = this.#relayAddrs.length === 0
323
+ ? "no_address_configured"
324
+ : dialFailures.length < this.#relayAddrs.length
325
+ ? "dialed_then_lost"
326
+ : "all_addresses_failed";
327
+ this.#logger.warn("content.park.open.failed", {
328
+ relayPeerId: this.#relayPeerId,
329
+ reason,
330
+ dialOutcome,
331
+ addrsTried: this.#relayAddrs.length,
332
+ dialFailures,
333
+ error: extractErrorMessage(err),
334
+ impact: dialOutcome === "all_addresses_failed"
335
+ ? "every relay address failed to dial, so there was no connection for the stream to use — the dial errors above are the cause, not the missing connection"
336
+ : dialOutcome === "dialed_then_lost"
337
+ // Review LOW-7: state the FACT, not a prescription. "re-dialling is not the remedy"
338
+ // generalised from one sample, and a connection lost right after a successful dial is
339
+ // often exactly a re-dial case.
340
+ ? "a dial SUCCEEDED and the connection was gone by the time the stream was opened — the loss is AFTER the dial, so the question is what closed it, not whether the relay is reachable"
341
+ : "no relay address was configured for this content-park client, so no dial was attempted at all",
342
+ });
343
+ throw new ContentParkUnreachableError({
344
+ reason,
345
+ relayPeerId: this.#relayPeerId,
346
+ dialFailures,
347
+ cause: extractErrorMessage(err),
348
+ });
349
+ }
265
350
  }
266
351
  #iter(stream) {
267
352
  return lp.decode(stream)[Symbol.asyncIterator]();
@@ -1 +1 @@
1
- {"version":3,"file":"content-park-client.js","sourceRoot":"","sources":["../src/content-park-client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"content-park-client.js","sourceRoot":"","sources":["../src/content-park-client.ts"],"names":[],"mappings":"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"}
@@ -46,6 +46,7 @@ export declare function createContentPark(deps: ContentParkDeps): {
46
46
  } | {
47
47
  ok: false;
48
48
  reason: string;
49
+ guidance?: string;
49
50
  }>;
50
51
  };
51
52
  //# sourceMappingURL=content-park.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"content-park.d.ts","sourceRoot":"","sources":["../src/content-park.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,EAAE,iBAAiB,EAA2B,MAAM,0BAA0B,CAAC;AAKtF,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,cAAc,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,WAAW,GAAG,SAAS,CAAC;IAC/D;;;;;OAKG;IACH,eAAe,EAAE,qBAAqB,CAAC;IACvC;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,EAAE,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,KAAK,iBAAiB,CAAC;CACpH;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,eAAe;qCAwaP,MAAM,uBAA4B,OAAO,CAAC,IAAI,CAAC;iCAkEzD,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,KAAG,IAAI;6CA/chD;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,eACpC,MAAM,cACP,MAAM,EAAE,KACnB,OAAO,CACN;QAAE,EAAE,EAAE,IAAI,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,KAAK,CAAC;YAAE,WAAW,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KAAE,GAC7I;QAAE,EAAE,EAAE,KAAK,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAChC;EA8rBF"}
1
+ {"version":3,"file":"content-park.d.ts","sourceRoot":"","sources":["../src/content-park.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,EAAE,iBAAiB,EAAwD,MAAM,0BAA0B,CAAC;AAMnH,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,cAAc,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,WAAW,GAAG,SAAS,CAAC;IAC/D;;;;;OAKG;IACH,eAAe,EAAE,qBAAqB,CAAC;IACvC;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,EAAE,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,KAAK,iBAAiB,CAAC;CACpH;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,eAAe;qCA2hBP,MAAM,uBAA4B,OAAO,CAAC,IAAI,CAAC;iCAkEzD,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,KAAG,IAAI;6CA3dhD;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,eACpC,MAAM,cACP,MAAM,EAAE,KACnB,OAAO,CACN;QAAE,EAAE,EAAE,IAAI,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,KAAK,CAAC;YAAE,WAAW,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KAAE,GAG7I;QAAE,EAAE,EAAE,KAAK,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CACnD;EAm0BF"}
@@ -20,7 +20,7 @@
20
20
  // `contentHashFor`, so this file no longer computes a content hash without asking which algorithm
21
21
  // the sender used (`DOD-M15-SEALWIRE-1` part B2a).
22
22
  import { randomUUID } from "node:crypto";
23
- import { ContentParkClient, ContentParkRefusedError } from "./content-park-client.js";
23
+ import { ContentParkClient, ContentParkRefusedError, ContentParkUnreachableError } from "./content-park-client.js";
24
24
  import { extractErrorMessage } from "./error-message.js";
25
25
  import { decodeParkEnvelope, sealParkEnvelope } from "./park-envelope.js";
26
26
  import { contentHashFor, resolveContentHashAlg, isKnownContentHashAlg, CONTENT_HASH_ALGS } from "./wire-content-hash.js";
@@ -32,11 +32,100 @@ export function createContentPark(deps) {
32
32
  // proven (J-CONTENT increment 1) before the send/receive-path integration. The relay
33
33
  // multiaddr (with /p2p/<peerId>) comes from the session assignment's relay endpoint;
34
34
  // dials run from the standing receiver (open-gater) node.
35
+ /**
36
+ * ⚠️ THE `/p2p/` SEGMENT IS SHAPE-CHECKED — review HIGH-1.
37
+ *
38
+ * This used to accept whatever followed `/p2p/`, so a truncated or mistyped multiaddr became a
39
+ * "peer id" that only `newStream` rejected, four layers down, as `invalid_peer_id` — and the
40
+ * deposit then reported it as a relay that could not be REACHED. A payload fault wearing a
41
+ * network fault's name is the substitution this milestone is named for.
42
+ *
43
+ * This proves the segment is a plausible base58btc peer id, NOT that the peer exists — the
44
+ * multibase/multihash decode still happens in the transport, and `invalid_peer_id` is still
45
+ * mapped honestly below for anything this misses. It is defence in depth on the cheapest fault,
46
+ * not a replacement for the mapping.
47
+ */
48
+ const PEER_ID_SHAPE = /^(1[1-9A-HJ-NP-Za-km-z]{47,52}|Qm[1-9A-HJ-NP-Za-km-z]{44}|12D3Koo[1-9A-HJ-NP-Za-km-z]{45,50})$/;
35
49
  const parseRelayPeer = (multiaddr) => {
36
50
  if (!multiaddr)
37
51
  return null;
38
- const peerId = multiaddr.split("/p2p/")[1];
39
- return peerId ? { peerId, addr: multiaddr } : null;
52
+ // Up to the next `/`, so a CIRCUIT address (`…/p2p/<relay>/p2p-circuit/p2p/<target>`) yields the
53
+ // relay rather than `<relay>/p2p-circuit` which the old form produced and only `newStream`
54
+ // ever rejected, four layers down, as an invalid peer id.
55
+ const peerId = multiaddr.split("/p2p/")[1]?.split("/")[0];
56
+ return peerId && PEER_ID_SHAPE.test(peerId) ? { peerId, addr: multiaddr } : null;
57
+ };
58
+ /**
59
+ * DOD-M15-PARKCONN-1 review HIGH-1 — **ONE STREAM FAILURE IS SIX FAULTS, AND ONLY TWO ARE ABOUT
60
+ * REACHING THE RELAY.**
61
+ *
62
+ * `#open` wraps every `newStream` rejection, because the dial evidence it collects is worth having
63
+ * on all of them. Labelling them all `relay_unreachable` is a different question, and getting it
64
+ * wrong reproduces the exact defect this unit exists to remove: `invalid_peer_id` is a MALFORMED
65
+ * ARGUMENT, `node_stopped` is THIS daemon's own transport, and `protocol_not_supported` means the
66
+ * connection worked and the relay does not speak content-park. Telling any of those three
67
+ * "the relay could not be reached — retry once it is up" sends the operator to the network for a
68
+ * fault that is not there, and the guidance is the half an operator actually reads.
69
+ *
70
+ * Reasons come from `core/transport/src/node.ts` (`newStream` + `mapStreamError`). An unknown one
71
+ * gets a neutral label rather than a reachability claim, because the default is where this class
72
+ * of defect hides.
73
+ */
74
+ const parkTransportFault = (reason, relayPeerId) => {
75
+ switch (reason) {
76
+ case "no_connection":
77
+ case "connection_lost":
78
+ return {
79
+ reason: `relay_unreachable:${reason}`,
80
+ guidance: `Relay ${relayPeerId} could not be reached from this daemon (${reason}), so nothing was deposited and no content was lost. ` +
81
+ `Retry once the relay is up. A conversation cannot be moved to a different relay from here — the park relay comes from the ` +
82
+ `session assignment — so if this relay stays down, broker a new session with cello_initiate_session.`,
83
+ };
84
+ case "invalid_peer_id":
85
+ return {
86
+ reason: "relay_address_invalid",
87
+ guidance: `The /p2p/ segment of the relayMultiaddr is not a usable peer id, so no relay was ever contacted. The relay is not at fault ` +
88
+ `and retrying will not help. Pass the relay endpoint from the session assignment verbatim — a truncated paste is the usual cause.`,
89
+ };
90
+ case "node_stopped":
91
+ return {
92
+ reason: "daemon_transport_stopped",
93
+ guidance: `This daemon's own transport is stopped, so the relay was never asked. Nothing was deposited. This is local: restart the ` +
94
+ `daemon, or start the agent with cello_start_agent if it was stopped deliberately.`,
95
+ };
96
+ case "protocol_not_supported":
97
+ return {
98
+ reason: "relay_protocol_unsupported",
99
+ guidance: `Relay ${relayPeerId} is CONNECTED and does not speak the content-park protocol — a version skew, not an outage. Retrying ` +
100
+ `will not change it. Use a relay running a build that carries content-park, or update this one.`,
101
+ };
102
+ case "limited_connection_refused":
103
+ return {
104
+ reason: "relay_limited_connection",
105
+ guidance: `Relay ${relayPeerId} allowed only a limited (relayed) connection and refused a content-park stream on it. CELLO's own paths ` +
106
+ `always permit limited connections, so this points at a defect on this side rather than at the relay; report it with the daemon log.`,
107
+ };
108
+ default:
109
+ return {
110
+ reason: `park_stream_failed:${reason}`,
111
+ guidance: `The content-park stream to relay ${relayPeerId} could not be opened (${reason}), and nothing was deposited. This daemon has no ` +
112
+ `specific remedy for that reason — the dial detail below is the evidence to report.`,
113
+ };
114
+ }
115
+ };
116
+ /** The IPC refusal for a content-park stream that could not be opened, with the dial evidence. */
117
+ const parkTransportRefusal = (err) => {
118
+ const fault = parkTransportFault(err.reason, err.relayPeerId);
119
+ const dials = err.dialFailures.length > 0
120
+ ? ` Dials tried: ${err.dialFailures.map((f) => `${f.addr} → ${f.error}`).join("; ")}.`
121
+ : ` No dial was refused, so the connection existed a moment ago or was never attempted.`;
122
+ return {
123
+ ok: false,
124
+ reason: fault.reason,
125
+ guidance: fault.guidance + dials,
126
+ // DoD 1: recoverable from the RESPONSE as well as the log — this caller has no daemon log.
127
+ dialFailures: err.dialFailures,
128
+ };
40
129
  };
41
130
  // MSG-001-3b (increment 3): RECOVER parked content. Pulls the recipient's parked entries,
42
131
  // decrypts each IN-DAEMON (openContentSeal — the relay never sees plaintext), and routes the
@@ -77,6 +166,16 @@ export function createContentPark(deps) {
77
166
  logger.warn("content.recover.refused", { agentName: recipientAgent.name, relayPeerId, reason: err.reason });
78
167
  return { ok: false, reason: `relay_refused_pull:${err.reason}` };
79
168
  }
169
+ /**
170
+ * Review MEDIUM-2 — the transport wrap reaches here too, and rethrowing it made
171
+ * `content_park_recover` answer `internal_error` / "An unexpected error occurred" for a relay
172
+ * that is simply down. `content_park_recover` is one of the three failures this order was
173
+ * written from, so this is the live path, not a hypothetical.
174
+ */
175
+ if (err instanceof ContentParkUnreachableError) {
176
+ const refusal = parkTransportRefusal(err);
177
+ return { ok: false, reason: refusal.reason, guidance: refusal.guidance };
178
+ }
80
179
  throw err;
81
180
  }
82
181
  let recovered = 0;
@@ -537,7 +636,7 @@ export function createContentPark(deps) {
537
636
  * `ciphertext` (the raw path) is kept for the one caller that wants byte fidelity through the
538
637
  * relay rather than envelope semantics.
539
638
  */
540
- handlers.set("content_park_deposit", async (params, _connectionId) => {
639
+ const runDeposit = async (params, _connectionId) => {
541
640
  /**
542
641
  * `Buffer.from(x, "hex")` TRUNCATES at the first invalid pair instead of throwing — the trap
543
642
  * `park-envelope.ts` already documents. Unvalidated, a typo'd `content` is signed and sealed at
@@ -590,8 +689,54 @@ export function createContentPark(deps) {
590
689
  contentHashAlg = rawAlg;
591
690
  }
592
691
  const node = sessionNodeManager.getStandingReceiverNode();
593
- if (!node)
594
- return { ok: false, reason: "standing_receiver_unavailable", guidance: "The daemon's standing receiver is not ready yet; retry after startup." };
692
+ if (!node) {
693
+ /**
694
+ * DOD-M15-PARKCONN-1 — **NAME THE CAUSE, NOT THE EXIT POINT** (Invariant 3).
695
+ *
696
+ * `standing_receiver_unavailable` is the label that already misnamed this incident 102
697
+ * times, which is why `standingReceiverAbsenceReason()` exists — and `recoverParkedFromRelay`
698
+ * has used it since M12-P12 while this handler kept returning the bare label. The four causes
699
+ * demand opposite responses: `standing_receiver_creating` clears in seconds and a retry
700
+ * works; `agent_offline` never clears until the agent is started; `daemon_shutting_down`
701
+ * means stop.
702
+ *
703
+ * The wire reason is unchanged — a caller matching on it keeps working — and the cause rides
704
+ * alongside, which is the same shape the send path settled on.
705
+ */
706
+ /**
707
+ * ⚠️ THE GUESS USES THE SIGNABLE LIST, review MEDIUM-4 — the same filter the signing branch
708
+ * below applies, and for the same reason it documents: a `load_failed` agent holds no key
709
+ * provider, so counting it makes a daemon with ONE healthy agent say it cannot tell which.
710
+ *
711
+ * And a name that matches no agent is not an offline agent, review LOW-6:
712
+ * `standingReceiverAbsenceReason("typo")` returns `agent_offline` because the name is simply
713
+ * absent from the wanting-a-receiver set, so the operator was told to start an agent that
714
+ * does not exist — a real verb pointed at nothing.
715
+ */
716
+ const signableAgents = agents.filter((a) => a.state !== "load_failed");
717
+ const namedAgent = senderAgentName
718
+ ? (signableAgents.some((a) => a.name === senderAgentName) ? senderAgentName : undefined)
719
+ : (signableAgents.length === 1 ? signableAgents[0].name : undefined);
720
+ const cause = namedAgent
721
+ ? sessionNodeManager.standingReceiverAbsenceReason(namedAgent)
722
+ : senderAgentName
723
+ ? "sender_agent_not_found"
724
+ // Review LOW-5: zero is not "more than one". An agentless daemon was being told it had
725
+ // several and could not say which.
726
+ : signableAgents.length === 0
727
+ ? "no_loadable_agent"
728
+ : "unknown_agent";
729
+ const guidanceByCause = {
730
+ standing_receiver_creating: "The standing receiver is still being built; retry this deposit in a few seconds.",
731
+ agent_offline: `Agent '${namedAgent}' is not online, so this daemon has no node to deposit from. Start it with cello_start_agent.`,
732
+ no_standing_receiver: "No agent on this daemon has a standing receiver; start an agent with cello_start_agent first.",
733
+ daemon_shutting_down: "The daemon is shutting down — nothing was deposited, and retrying will not help until it is back up.",
734
+ unknown_agent: `This daemon has no standing receiver and ${agents.filter((a) => a.state !== "load_failed").length} signable agents, so it cannot say which one is missing it; pass senderAgentName, or start an agent with cello_start_agent.`,
735
+ sender_agent_not_found: `This daemon has no loadable agent named '${senderAgentName}', so there is nothing to check a standing receiver for. Check the name — cello_agents lists what this daemon holds.`,
736
+ no_loadable_agent: "This daemon has no loadable agent at all, so it can never have a standing receiver. Create and register one, then start it with cello_start_agent.",
737
+ };
738
+ return { ok: false, reason: "standing_receiver_unavailable", cause, guidance: guidanceByCause[cause] ?? "The daemon's standing receiver is not ready yet; retry after startup." };
739
+ }
595
740
  let payload;
596
741
  if (hasContent) {
597
742
  const content = hexOrNull(params?.content);
@@ -657,13 +802,71 @@ export function createContentPark(deps) {
657
802
  }
658
803
  payload = Buffer.from(ciphertext, "hex");
659
804
  }
660
- const client = new ContentParkClient({ relayPeerId: relay.peerId, relayAddrs: [relay.addr], logger });
661
- return await client.deposit(node, {
662
- recipientPubkey: Buffer.from(recipientPubkey, "hex"),
663
- contentHash: Buffer.from(contentHash, "hex"),
664
- sessionId: Buffer.from(sessionId, "hex"),
665
- ciphertext: payload,
666
- });
805
+ /**
806
+ * DOD-M15-PARKCONN-1 — **THE ODD HANDLER OUT NOW REFUSES LIKE ITS SIBLINGS, AND SAYS SO ONCE.**
807
+ *
808
+ * Every other exit above returns `{ ok: false, reason, guidance }`; this one ended in a bare
809
+ * `return await client.deposit(...)` with no catch and no log. An unreachable relay — the
810
+ * ordinary condition park exists for — therefore left the daemon as a THROW, which IPC shapes
811
+ * into `internal_error` + "An unexpected error occurred. Check daemon logs for details." The
812
+ * daemon logs held nothing either: this handler logged NOTHING AT ALL, which is why
813
+ * `019-PARKERROR` went looking for a deposit line and found none.
814
+ *
815
+ * Only `ContentParkUnreachableError` is converted. Anything else still throws, because a
816
+ * blanket catch here would turn a genuine defect into a tidy refusal — the failure this
817
+ * milestone is named for.
818
+ */
819
+ const client = newParkClient({ relayPeerId: relay.peerId, relayAddrs: [relay.addr], logger });
820
+ try {
821
+ return await client.deposit(node, {
822
+ recipientPubkey: Buffer.from(recipientPubkey, "hex"),
823
+ contentHash: Buffer.from(contentHash, "hex"),
824
+ sessionId: Buffer.from(sessionId, "hex"),
825
+ ciphertext: payload,
826
+ });
827
+ }
828
+ catch (err) {
829
+ // Only the transport wrap is converted. A blanket catch here would turn a genuine defect
830
+ // into a tidy refusal — the failure this milestone is named for.
831
+ if (!(err instanceof ContentParkUnreachableError))
832
+ throw err;
833
+ return parkTransportRefusal(err);
834
+ }
835
+ };
836
+ /**
837
+ * ⚠️ **THE RESULT LOG WRAPS THE WHOLE HANDLER, review MEDIUM-3.**
838
+ *
839
+ * It used to sit beside the two exits that reach the relay, so eleven refusals — every bad
840
+ * argument, `agent_not_found`, `session_not_found`, `session_recipient_mismatch` — still
841
+ * returned in total silence. That is the same hole `019-PARKERROR` fell into in this very
842
+ * handler, for a different reason: an operator greps for a deposit line and finds nothing.
843
+ *
844
+ * Wrapping rather than sprinkling is deliberate. A call per exit drifts the moment someone adds
845
+ * a fourteenth; a wrapper cannot miss one.
846
+ */
847
+ handlers.set("content_park_deposit", async (params, connectionId) => {
848
+ const res = (await runDeposit(params, connectionId));
849
+ const line = {
850
+ // Read off the CALLER's params: a refusal can fire before either is parsed, and a log line
851
+ // that omits which deposit it is about cannot be correlated with anything.
852
+ relayMultiaddr: typeof params?.["relayMultiaddr"] === "string" ? params["relayMultiaddr"] : undefined,
853
+ sessionId: typeof params?.["sessionId"] === "string" ? params["sessionId"] : undefined,
854
+ contentHash: typeof params?.["contentHash"] === "string" ? params["contentHash"] : undefined,
855
+ ok: res.ok === true,
856
+ ...(res.reason !== undefined ? { reason: res.reason } : {}),
857
+ ...(res.cause !== undefined ? { cause: res.cause } : {}),
858
+ // Review LOW-8: the relay's own "when" already rides on the response; dropping it from the
859
+ // log leaves an aggregated log unable to say when a throttled deposit clears.
860
+ ...(res.retryAfterMs !== undefined ? { retryAfterMs: res.retryAfterMs } : {}),
861
+ };
862
+ // NOT `content.park.deposit.result` — the ContentParkClient already emits that name one layer
863
+ // down, and two events from different layers under one name make an aggregated log unreadable
864
+ // (the same review finding as `content.park.pull.refused_by_relay`).
865
+ if (line.ok)
866
+ logger.info("content.park.deposit.ipc.result", line);
867
+ else
868
+ logger.warn("content.park.deposit.ipc.result", line);
869
+ return res;
667
870
  });
668
871
  handlers.set("content_park_pull", async (params, _connectionId) => {
669
872
  const relay = parseRelayPeer(params?.relayMultiaddr);
@@ -681,12 +884,22 @@ export function createContentPark(deps) {
681
884
  const node = sessionNodeManager.getStandingReceiverNode();
682
885
  if (!node)
683
886
  return { ok: false, reason: "standing_receiver_unavailable", guidance: "The daemon's standing receiver is not ready yet; retry after startup." };
684
- const client = new ContentParkClient({ relayPeerId: relay.peerId, relayAddrs: [relay.addr], logger });
887
+ // Review LOW-9: the seam, like every other client in this file. This handler was still
888
+ // constructing directly, which is why its `#open` failure path had no unit coverage.
889
+ const client = newParkClient({ relayPeerId: relay.peerId, relayAddrs: [relay.addr], logger });
685
890
  let entries;
686
891
  try {
687
892
  entries = await client.pull(node, Buffer.from(recipientPubkey, "hex"), kp);
688
893
  }
689
894
  catch (err) {
895
+ /**
896
+ * Review MEDIUM-2 — `#open` is shared, so this handler now receives the same transport wrap
897
+ * the deposit handler does. Rethrowing it turned an unreachable relay into
898
+ * `internal_error` + "An unexpected error occurred" — the exact response this unit exists to
899
+ * abolish, one handler over, on a path the order's own evidence names.
900
+ */
901
+ if (err instanceof ContentParkUnreachableError)
902
+ return parkTransportRefusal(err);
690
903
  // DOD-M15-RELAYAUTH-1 review HIGH-3: a refusal must not be reported as an empty list.
691
904
  if (err instanceof ContentParkRefusedError) {
692
905
  return {
@@ -730,7 +943,17 @@ export function createContentPark(deps) {
730
943
  // where it helps the operator without breaking a consumer that branches on the reason.
731
944
  const noReceiver = new Set(["standing_receiver_creating", "agent_offline", "no_standing_receiver", "daemon_shutting_down"]);
732
945
  const wireReason = noReceiver.has(res.reason) ? "standing_receiver_unavailable" : res.reason;
733
- return { ok: false, reason: wireReason, guidance: guidanceByReason[res.reason] ?? "Recover failed." };
946
+ /**
947
+ * Review MEDIUM-2 — a guidance the drain already computed WINS, and the bare "Recover
948
+ * failed." is the last resort rather than the answer for everything the table misses. That
949
+ * default is not an affordance: it names no next step, which is what Invariant 4 forbids on
950
+ * exactly this kind of response.
951
+ */
952
+ return {
953
+ ok: false,
954
+ reason: wireReason,
955
+ guidance: res.guidance ?? guidanceByReason[res.reason] ?? `Recover failed (${res.reason}) and this daemon has no specific remedy for that reason. The daemon log holds the detail — report it with the reason above.`,
956
+ };
734
957
  }
735
958
  /**
736
959
  * `refusals` REACHES THE CALLER — review B2a pass-2 F3, "no consumer, no ship".