@cello-protocol/daemon 0.0.211 → 0.0.213

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 (215) hide show
  1. package/dist/agent-admin-handlers.d.ts.map +1 -1
  2. package/dist/agent-admin-handlers.js +3 -0
  3. package/dist/agent-admin-handlers.js.map +1 -1
  4. package/dist/agent-handlers.d.ts.map +1 -1
  5. package/dist/agent-handlers.js +44 -0
  6. package/dist/agent-handlers.js.map +1 -1
  7. package/dist/agent-id-migration.d.ts.map +1 -1
  8. package/dist/agent-id-migration.js +11 -2
  9. package/dist/agent-id-migration.js.map +1 -1
  10. package/dist/assignment-verify.d.ts.map +1 -1
  11. package/dist/assignment-verify.js +2 -2
  12. package/dist/assignment-verify.js.map +1 -1
  13. package/dist/attendance-wiring.d.ts +2 -21
  14. package/dist/attendance-wiring.d.ts.map +1 -1
  15. package/dist/attendance-wiring.js +57 -251
  16. package/dist/attendance-wiring.js.map +1 -1
  17. package/dist/away-detection.d.ts +16 -21
  18. package/dist/away-detection.d.ts.map +1 -1
  19. package/dist/away-detection.js +34 -23
  20. package/dist/away-detection.js.map +1 -1
  21. package/dist/boot-agents.d.ts.map +1 -1
  22. package/dist/close-session-handler.d.ts.map +1 -1
  23. package/dist/close-session-handler.js +79 -6
  24. package/dist/close-session-handler.js.map +1 -1
  25. package/dist/co-attendance.d.ts +1 -1
  26. package/dist/co-attendance.js +1 -1
  27. package/dist/consortium-fingerprint.d.ts +115 -0
  28. package/dist/consortium-fingerprint.d.ts.map +1 -0
  29. package/dist/consortium-fingerprint.js +175 -0
  30. package/dist/consortium-fingerprint.js.map +1 -0
  31. package/dist/content-park.d.ts.map +1 -1
  32. package/dist/content-park.js +80 -0
  33. package/dist/content-park.js.map +1 -1
  34. package/dist/daemon-handle.d.ts +1 -1
  35. package/dist/daemon-handle.d.ts.map +1 -1
  36. package/dist/daemon-status-report.d.ts +10 -2
  37. package/dist/daemon-status-report.d.ts.map +1 -1
  38. package/dist/daemon-status-report.js +6 -3
  39. package/dist/daemon-status-report.js.map +1 -1
  40. package/dist/daemon.d.ts.map +1 -1
  41. package/dist/daemon.js +57 -27
  42. package/dist/daemon.js.map +1 -1
  43. package/dist/directory-bootstrap.d.ts +3 -1
  44. package/dist/directory-bootstrap.d.ts.map +1 -1
  45. package/dist/directory-bootstrap.js +3 -1
  46. package/dist/directory-bootstrap.js.map +1 -1
  47. package/dist/directory-connect.d.ts.map +1 -1
  48. package/dist/directory-connect.js +10 -2
  49. package/dist/directory-connect.js.map +1 -1
  50. package/dist/disconnect-cleanup.d.ts +7 -0
  51. package/dist/disconnect-cleanup.d.ts.map +1 -1
  52. package/dist/disconnect-cleanup.js +16 -1
  53. package/dist/disconnect-cleanup.js.map +1 -1
  54. package/dist/document-flag.d.ts +58 -0
  55. package/dist/document-flag.d.ts.map +1 -0
  56. package/dist/document-flag.js +70 -0
  57. package/dist/document-flag.js.map +1 -0
  58. package/dist/document-gate-wiring.d.ts +61 -0
  59. package/dist/document-gate-wiring.d.ts.map +1 -0
  60. package/dist/document-gate-wiring.js +119 -0
  61. package/dist/document-gate-wiring.js.map +1 -0
  62. package/dist/document-notify.d.ts +0 -1
  63. package/dist/document-notify.d.ts.map +1 -1
  64. package/dist/document-notify.js +0 -1
  65. package/dist/document-notify.js.map +1 -1
  66. package/dist/document-store.d.ts +0 -1
  67. package/dist/document-store.d.ts.map +1 -1
  68. package/dist/document-store.js +0 -1
  69. package/dist/document-store.js.map +1 -1
  70. package/dist/document-write-path.d.ts.map +1 -1
  71. package/dist/document-write-path.js +2 -9
  72. package/dist/document-write-path.js.map +1 -1
  73. package/dist/inbound-sessions.d.ts +3 -1
  74. package/dist/inbound-sessions.d.ts.map +1 -1
  75. package/dist/inbound-sessions.js +12 -4
  76. package/dist/inbound-sessions.js.map +1 -1
  77. package/dist/index.d.ts +5 -1
  78. package/dist/index.d.ts.map +1 -1
  79. package/dist/index.js +13 -1
  80. package/dist/index.js.map +1 -1
  81. package/dist/initiate-session-handler.d.ts.map +1 -1
  82. package/dist/initiate-session-handler.js +5 -1
  83. package/dist/initiate-session-handler.js.map +1 -1
  84. package/dist/ipc-server.d.ts.map +1 -1
  85. package/dist/ipc-server.js +52 -2
  86. package/dist/ipc-server.js.map +1 -1
  87. package/dist/park-envelope.d.ts +68 -0
  88. package/dist/park-envelope.d.ts.map +1 -1
  89. package/dist/park-envelope.js +86 -1
  90. package/dist/park-envelope.js.map +1 -1
  91. package/dist/park-recovery.d.ts +46 -0
  92. package/dist/park-recovery.d.ts.map +1 -1
  93. package/dist/park-recovery.js +100 -1
  94. package/dist/park-recovery.js.map +1 -1
  95. package/dist/relay-only.d.ts.map +1 -1
  96. package/dist/relay-only.js +7 -4
  97. package/dist/relay-only.js.map +1 -1
  98. package/dist/relay-receipt-store.d.ts +75 -17
  99. package/dist/relay-receipt-store.d.ts.map +1 -1
  100. package/dist/relay-receipt-store.js +109 -27
  101. package/dist/relay-receipt-store.js.map +1 -1
  102. package/dist/seal-carried-close.d.ts +37 -0
  103. package/dist/seal-carried-close.d.ts.map +1 -0
  104. package/dist/seal-carried-close.js +179 -0
  105. package/dist/seal-carried-close.js.map +1 -0
  106. package/dist/seal-certified-root-check.d.ts +37 -0
  107. package/dist/seal-certified-root-check.d.ts.map +1 -0
  108. package/dist/seal-certified-root-check.js +127 -0
  109. package/dist/seal-certified-root-check.js.map +1 -0
  110. package/dist/seal-coordinator.d.ts +6 -1
  111. package/dist/seal-coordinator.d.ts.map +1 -1
  112. package/dist/seal-coordinator.js +2 -1
  113. package/dist/seal-coordinator.js.map +1 -1
  114. package/dist/seal-escalation.d.ts.map +1 -1
  115. package/dist/seal-escalation.js +54 -0
  116. package/dist/seal-escalation.js.map +1 -1
  117. package/dist/seal-local-terminus.d.ts +41 -0
  118. package/dist/seal-local-terminus.d.ts.map +1 -0
  119. package/dist/seal-local-terminus.js +170 -0
  120. package/dist/seal-local-terminus.js.map +1 -0
  121. package/dist/seal-relay-silence.d.ts +51 -0
  122. package/dist/seal-relay-silence.d.ts.map +1 -0
  123. package/dist/seal-relay-silence.js +76 -0
  124. package/dist/seal-relay-silence.js.map +1 -0
  125. package/dist/seal-settle.d.ts +38 -0
  126. package/dist/seal-settle.d.ts.map +1 -0
  127. package/dist/seal-settle.js +33 -0
  128. package/dist/seal-settle.js.map +1 -0
  129. package/dist/session-assignment-parser.d.ts.map +1 -1
  130. package/dist/session-assignment-parser.js +5 -0
  131. package/dist/session-assignment-parser.js.map +1 -1
  132. package/dist/session-ceremony.d.ts +21 -14
  133. package/dist/session-ceremony.d.ts.map +1 -1
  134. package/dist/session-ceremony.js +25 -15
  135. package/dist/session-ceremony.js.map +1 -1
  136. package/dist/session-content-context.d.ts +11 -2
  137. package/dist/session-content-context.d.ts.map +1 -1
  138. package/dist/session-content-ingest.d.ts +0 -3
  139. package/dist/session-content-ingest.d.ts.map +1 -1
  140. package/dist/session-content-ingest.js +18 -111
  141. package/dist/session-content-ingest.js.map +1 -1
  142. package/dist/session-content-send.d.ts +5 -0
  143. package/dist/session-content-send.d.ts.map +1 -1
  144. package/dist/session-content-send.js +58 -0
  145. package/dist/session-content-send.js.map +1 -1
  146. package/dist/session-delivery-acks.d.ts +195 -0
  147. package/dist/session-delivery-acks.d.ts.map +1 -0
  148. package/dist/session-delivery-acks.js +674 -0
  149. package/dist/session-delivery-acks.js.map +1 -0
  150. package/dist/session-leaf-records.d.ts +28 -1
  151. package/dist/session-leaf-records.d.ts.map +1 -1
  152. package/dist/session-leaf-records.js +86 -1
  153. package/dist/session-leaf-records.js.map +1 -1
  154. package/dist/session-lifecycle.js +12 -12
  155. package/dist/session-lifecycle.js.map +1 -1
  156. package/dist/session-node-manager.d.ts +49 -22
  157. package/dist/session-node-manager.d.ts.map +1 -1
  158. package/dist/session-node-manager.js +113 -42
  159. package/dist/session-node-manager.js.map +1 -1
  160. package/dist/session-node-types.d.ts +18 -12
  161. package/dist/session-node-types.d.ts.map +1 -1
  162. package/dist/session-node-types.js +1 -9
  163. package/dist/session-node-types.js.map +1 -1
  164. package/dist/session-read-handlers.d.ts.map +1 -1
  165. package/dist/session-read-handlers.js +125 -4
  166. package/dist/session-read-handlers.js.map +1 -1
  167. package/dist/session-records.d.ts +17 -0
  168. package/dist/session-records.d.ts.map +1 -1
  169. package/dist/session-records.js +32 -0
  170. package/dist/session-records.js.map +1 -1
  171. package/dist/session-relay-client.d.ts +103 -6
  172. package/dist/session-relay-client.d.ts.map +1 -1
  173. package/dist/session-relay-client.js +380 -41
  174. package/dist/session-relay-client.js.map +1 -1
  175. package/dist/session-relay.d.ts +24 -2
  176. package/dist/session-relay.d.ts.map +1 -1
  177. package/dist/session-relay.js +23 -8
  178. package/dist/session-relay.js.map +1 -1
  179. package/dist/session-schema.d.ts.map +1 -1
  180. package/dist/session-schema.js +43 -0
  181. package/dist/session-schema.js.map +1 -1
  182. package/dist/session-seal-leaf-store.d.ts +6 -0
  183. package/dist/session-seal-leaf-store.d.ts.map +1 -1
  184. package/dist/session-seal-leaf-store.js +21 -4
  185. package/dist/session-seal-leaf-store.js.map +1 -1
  186. package/dist/session-seal.d.ts +30 -32
  187. package/dist/session-seal.d.ts.map +1 -1
  188. package/dist/session-seal.js +145 -116
  189. package/dist/session-seal.js.map +1 -1
  190. package/dist/session-views.d.ts +1 -0
  191. package/dist/session-views.d.ts.map +1 -1
  192. package/dist/session-views.js +81 -1
  193. package/dist/session-views.js.map +1 -1
  194. package/dist/signaling-connect.d.ts +1 -0
  195. package/dist/signaling-connect.d.ts.map +1 -1
  196. package/dist/signaling-connect.js +0 -1
  197. package/dist/signaling-connect.js.map +1 -1
  198. package/dist/status-handler.d.ts +9 -1
  199. package/dist/status-handler.d.ts.map +1 -1
  200. package/dist/status-handler.js +5 -2
  201. package/dist/status-handler.js.map +1 -1
  202. package/dist/test-handlers.js +4 -3
  203. package/dist/test-handlers.js.map +1 -1
  204. package/dist/trust-signal-store.d.ts +4 -2
  205. package/dist/trust-signal-store.d.ts.map +1 -1
  206. package/dist/trust-signal-store.js +4 -2
  207. package/dist/trust-signal-store.js.map +1 -1
  208. package/dist/types.d.ts +64 -0
  209. package/dist/types.d.ts.map +1 -1
  210. package/dist/types.js.map +1 -1
  211. package/dist/vocabulary.d.ts +22 -4
  212. package/dist/vocabulary.d.ts.map +1 -1
  213. package/dist/vocabulary.js +66 -21
  214. package/dist/vocabulary.js.map +1 -1
  215. package/package.json +5 -5
@@ -1 +1 @@
1
- {"version":3,"file":"session-relay-client.d.ts","sourceRoot":"","sources":["../src/session-relay-client.ts"],"names":[],"mappings":"AAkCA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAU,KAAK,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzC,OAAO,EAAoB,KAAK,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AACpF,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACzE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAGzE,eAAO,MAAM,iBAAiB,uBAAuB,CAAC;AAEtD;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,OAAQ,CAAC;AAC1C,eAAO,MAAM,iBAAiB,wBAAwB,CAAC;AACvD,iFAAiF;AACjF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,uBAAuB,EAAE,WAAW,CAAC,MAAM,CAgBtD,CAAC;AAEH,kFAAkF;AAClF,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAE1E;AAED;;;;;;GAMG;AACH,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,OAAO,CAAC;IACzB,+EAA+E;IAC/E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qDAAqD;IACrD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AA+CD,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEhE;AAED;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,MAAM,EACd,KAAK,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAO,GAC1E,gBAAgB,CA8ElB;AAED,eAAO,MAAM,aAAa,IAAO,CAAC;AAClC,iGAAiG;AACjG,eAAO,MAAM,cAAc,IAAO,CAAC;AACnC,uFAAuF;AACvF,eAAO,MAAM,aAAa,IAAO,CAAC;AAClC,uFAAuF;AACvF,eAAO,MAAM,gBAAgB,IAAO,CAAC;AAKrC;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,GAAG,UAAU,CAIvF;AAED,MAAM,WAAW,gBAAgB;IAC/B,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,UAAU,CAAC;IAC5B,eAAe,EAAE,UAAU,CAAC;IAC5B;;;;;OAKG;IACH,cAAc,EAAE,OAAO,CAAC;CACzB;AAED,gDAAgD;AAChD,MAAM,MAAM,YAAY,GACpB;IACE,EAAE,EAAE,IAAI,CAAC;IACT,eAAe,EAAE,MAAM,CAAC;IAKxB,eAAe,CAAC,EAAE,UAAU,CAAC;IAC7B,eAAe,CAAC,EAAE,UAAU,CAAC;IAC7B;;;;;;;;;;;;;OAaG;IACH,gBAAgB,CAAC,EAAE,UAAU,CAAC;CAC/B,GACD;IACE,EAAE,EAAE,KAAK,CAAC;IACV,MAAM,EAAE,MAAM,CAAC;IACf;;;;;;;;;;;;OAYG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAGN,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,sEAAsE;IACtE,WAAW,EAAE,WAAW,CAAC;IACzB,iFAAiF;IACjF,YAAY,EAAE,UAAU,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,YAAY,CAAC,EAAE,iBAAiB,CAAC;IACjC;;;;;OAKG;IACH,aAAa,CAAC,EAAE,oBAAoB,CAAC;IACrC;;;;OAIG;IACH,aAAa,CAAC,EAAE,oBAAoB,CAAC;IACrC;;;;;;;;;;;;OAYG;IACH,WAAW,CAAC,EAAE,MAAM,UAAU,GAAG,SAAS,CAAC;IAC3C;;;;;;;OAOG;IACH,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAC;IACpD;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAClE;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB;;;;;;;;OAQG;IACH,MAAM,EAAE,oCAAoC,GAAG,gCAAgC,CAAC;IAChF,oGAAoG;IACpG,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,yFAAyF;IACzF,uBAAuB,EAAE,OAAO,CAAC;IACjC;;;OAGG;IACH,aAAa,EAAE,MAAM,CAAC;IACtB;;;;;;;;;;OAUG;IACH,UAAU,EAAE,OAAO,CAAC;CACrB;AAqBD;;;;;;GAMG;AACH;;;;;;GAMG;AACH,MAAM,WAAW,gBAAgB;IAC/B,2DAA2D;IAC3D,cAAc,EAAE,UAAU,CAAC;IAC3B,oEAAoE;IACpE,eAAe,EAAE,UAAU,CAAC;CAC7B;AAED,MAAM,WAAW,oBAAoB;IACnC,YAAY,EAAE,UAAU,CAAC;IACzB,YAAY,EAAE,UAAU,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,mBAAmB,EAAE,UAAU,CAAC;CACjC;AAsDD;;;;GAIG;AACH,qBAAa,gBAAgB;;IAO3B,4EAA4E;IAC5E,kBAAkB,IAAI,MAAM,GAAG,IAAI;IA2DnC,+FAA+F;IAC/F,kBAAkB,IAAI,gBAAgB,GAAG,IAAI;gBA+FjC,IAAI,EAAE,oBAAoB;IA8BtC,2FAA2F;IAC3F,IAAI,eAAe,IAAI,MAAM,CAE5B;IAED;;;;OAIG;IACH,eAAe,CACb,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,SAAS,EACf,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,EACjD,UAAU,CAAC,EAAE,oBAAoB;IACjC;;;;;;;;;;;;;;OAcG;IACH,eAAe,CAAC,EAAE,UAAU,GAC3B,IAAI;IAoCP;;;;;;;;;;;;;;;;;OAiBG;IACG,uBAAuB,CAAC,IAAI,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAgFtF,0EAA0E;IAC1E,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI;IAM7C,WAAW,IAAI,OAAO;IAItB;;;;;;;;OAQG;IACH,UAAU,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO;IAkiBzC;;;;OAIG;IACG,OAAO,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC;IAIhD;;;;;;;;;;;;;;;;;OAiBG;IACH;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;IACG,gBAAgB,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC;IA0JzD;;;;;;;;;;;;;;;;;;OAkBG;IACG,kBAAkB,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC;IA6T3D;;;;;;;;;OASG;IACG,iBAAiB,CACrB,IAAI,EAAE,SAAS,EACf,SAAS,EAAE,UAAU,EACrB,WAAW,EAAE,UAAU;IACvB;;;;;OAKG;IACH,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,YAAY,CAAC;IAQxB;;;;;;;;;;;;;;;;;;OAkBG;IACG,mBAAmB,CACvB,IAAI,EAAE,SAAS,EACf,SAAS,EAAE,UAAU,EACrB,WAAW,EAAE,UAAU,EACvB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,YAAY,CAAC;IAIxB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA0CG;IACG,UAAU,CACd,IAAI,EAAE,SAAS,EACf,SAAS,EAAE,UAAU,EACrB,WAAW,EAAE,UAAU,EACvB,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,UAAU,GAAG,IAAI;IAC/B;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,YAAY,CAAC;IAmjBxB,yFAAyF;IACzF;;;;;;;;;;;;;;;;;;;OAmBG;IACH,gBAAgB,CAAC,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,GAAG,IAAI;IAIvF;;;;;;;;;;;;OAYG;IACH,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,UAAU,CAAA;KAAE,GAAG,SAAS;IAIhF;;;;;;;;;;;OAWG;IACH,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS;IAMzD;;;;;;OAMG;IACH,WAAW,CAAC,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,GAAG,IAAI;IAKhE,KAAK,IAAI,IAAI;CAWd"}
1
+ {"version":3,"file":"session-relay-client.d.ts","sourceRoot":"","sources":["../src/session-relay-client.ts"],"names":[],"mappings":"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"}
@@ -32,9 +32,28 @@ import { createHash } from "node:crypto";
32
32
  import * as lp from "it-length-prefixed";
33
33
  import { decode } from "cbor-x";
34
34
  import { encodeCbor, decodeSealPayload, encodeStructure1, decodeStructure1, computeGenesisPrevRoot } from "@cello-protocol/protocol-types";
35
+ import { encodeSessionLivenessQuery, decodeSessionLivenessResponse, encodeSessionAttendanceNotice, } from "@cello-protocol/protocol-types";
35
36
  import { verify } from "@cello-protocol/crypto";
36
37
  import { extractErrorMessage } from "./error-message.js";
37
- import { evaluateRelayAck } from "./relay-receipt-store.js";
38
+ import { evaluateRelayAck, readSubmittedLeaf } from "./relay-receipt-store.js";
39
+ /**
40
+ * DOD-M15-AWAYSCOPE-1 — what a liveness query answers with.
41
+ *
42
+ * `refused` is kept separate from the values rather than folded into `liveness`, because it means
43
+ * something different: the relay declined to say, most likely because this caller is not a
44
+ * participant of the session it named. The liveness is 'unknown' either way — the operator surface
45
+ * shows the same thing — but a caller that wants to tell "the relay would not tell me" from "the
46
+ * relay does not know" can, and a log line that conflated them would send the next investigation
47
+ * looking at the counterparty instead of at the session id.
48
+ */
49
+ /**
50
+ * The key an answer is matched to its question by: the two fields the RESPONSE carries back. One
51
+ * relay client serves every session an agent holds there, so two concurrent queries on one stream
52
+ * is ordinary — and an answer routed to whatever was asked last shows the wrong counterparty's row.
53
+ */
54
+ function livenessKey(sessionId, counterpartyPubkey) {
55
+ return `${Buffer.from(sessionId).toString("hex")}:${Buffer.from(counterpartyPubkey).toString("hex")}`;
56
+ }
38
57
  export const RELAY_PROTOCOL_ID = "/cello/relay/1.0.0";
39
58
  /**
40
59
  * How long to wait before re-proving after a transport-class failure.
@@ -47,7 +66,6 @@ export const RELAY_PROTOCOL_ID = "/cello/relay/1.0.0";
47
66
  */
48
67
  export const PROOF_RETRY_DELAY_MS = 1_000;
49
68
  export const RELAY_AUTH_DOMAIN = "CELLO-RELAY-AUTH-v1";
50
- /** Structure 1 leaf kind: 0x00 = message, 0x02 = control (matches the relay). */
51
69
  /**
52
70
  * DOD-WITNESS-STALL-1 — relay refusals that can NEVER resolve.
53
71
  *
@@ -218,6 +236,7 @@ export function classifyRelayAuthRefusal(reason, extra = {}) {
218
236
  ...(extra.retryAfterMs !== undefined ? { retryAfterMs: extra.retryAfterMs } : {}),
219
237
  };
220
238
  }
239
+ /** Structure 1 leaf kind — these values match the relay's. Message leaf (the `cello_send` default). */
221
240
  export const LEAF_KIND_MSG = 0x00;
222
241
  /** Control leaf (SEAL etc.) — two distinct-sender ctrl leaves trigger directory notarization. */
223
242
  export const LEAF_KIND_CTRL = 0x02;
@@ -384,9 +403,9 @@ export class AgentRelayClient {
384
403
  /**
385
404
  * PER-SESSION acknowledgement state (session_id hex → the position AND the content at it).
386
405
  *
387
- * `seq` is the highest relay-assigned sequence. The relay's `seq_counter` is per session, and it
388
- * rejects `last_seen_seq > seq_counter`, so each session's submit MUST carry that session's own
389
- * high-water mark — NOT an agent-global one (which would make a newer session's first submit look
406
+ * `seq` is the highest relay-assigned sequence, advanced by an ack or a deliver. The relay's
407
+ * `seq_counter` is per session and it rejects `last_seen_seq > seq_counter`, so each session's
408
+ * submit MUST carry that session's own high-water mark — NOT an agent-global one (which would make a newer session's first submit look
390
409
  * ahead and get rejected).
391
410
  *
392
411
  * ⚠️ `hash` IS THE SAME FACT AS `seq`, WHICH IS WHY THEY LIVE IN ONE ENTRY — 033-ACKEMIT.
@@ -431,6 +450,18 @@ export class AgentRelayClient {
431
450
  * serialized on the shared stream, exactly like `#pendingRecord`, whose ack also carries no id.
432
451
  */
433
452
  #pendingRelease = null;
453
+ /**
454
+ * DOD-M15-AWAYSCOPE-1 — in-flight liveness queries, keyed `sessionIdHex:counterpartyHex`.
455
+ *
456
+ * ⚠️ A MAP, NOT A SLOT, and the first version was a slot. One `AgentRelayClient` serves EVERY
457
+ * session an agent holds on a relay and both callers fan out with `Promise.all`, so `cello status`
458
+ * with two open conversations fired two queries on one stream: the second overwrote the first's
459
+ * resolver, the first answer resolved the WRONG session's promise, and the other waited the full
460
+ * submit timeout — blowing the caller's budget so every row came back unenriched. With more than
461
+ * one session the feature did nothing, and when it did something it could show the wrong
462
+ * counterparty. The key is what the RESPONSE carries, so an answer is matched to its question.
463
+ */
464
+ #pendingLiveness = new Map();
434
465
  /** Serializes submits so only one is in flight at a time across all sessions. */
435
466
  #submitChain = Promise.resolve();
436
467
  /** session_id hex → { the live node to (re)dial from, inbound leaf handler, Option-B assignment to present }. */
@@ -488,14 +519,28 @@ export class AgentRelayClient {
488
519
  * point has nothing for them to anchor to and every submit on it is refused by name. Registering
489
520
  * without a seed is therefore a real fault, not a degraded mode.
490
521
  */
491
- genesisPrevRoot) {
522
+ genesisPrevRoot,
523
+ /**
524
+ * 069-ORDERPROOF — the relay key this session's ordering attestations verify under, from
525
+ * `relay_id` on the directory-signed assignment. Supplied by the caller because
526
+ * `session-node-manager` is where the durable copy lives, exactly as with the genesis above.
527
+ *
528
+ * ⚠️ ABSENT IS NOT A DEGRADED MODE. A session with no anchor refuses every attestation that
529
+ * arrives on it, by name, because the only alternative is checking a signature against a key
530
+ * the signer handed us.
531
+ */
532
+ relayAnchorHex) {
492
533
  const existing = this.#sessions.get(sessionIdHex);
493
534
  const carriedAssignment = assignment ?? existing?.assignment;
535
+ // The anchor is carried forward for the same reason the assignment is: a re-registration with
536
+ // nothing in hand must not silently strip a session of the key it verifies against.
537
+ const carriedAnchor = relayAnchorHex ?? carriedAssignment?.relayPubkeyHex ?? existing?.relayAnchorHex;
494
538
  this.#sessions.set(sessionIdHex, {
495
539
  node,
496
540
  onLeafDeliver: onLeafDeliver ?? (() => { }),
497
541
  // Carry the assignment forward across re-registration; never lose a recorded flag on re-register.
498
542
  assignment: carriedAssignment,
543
+ ...(carriedAnchor ? { relayAnchorHex: carriedAnchor } : {}),
499
544
  recorded: existing?.recorded ?? false,
500
545
  recordRejected: existing?.recordRejected ?? false,
501
546
  recordTimedOut: existing?.recordTimedOut ?? false,
@@ -560,6 +605,10 @@ export class AgentRelayClient {
560
605
  const sess = this.#sessions.get(sessionIdHex);
561
606
  if (!sess || !sess.assignment)
562
607
  return true;
608
+ // Nothing to PRESENT. The carry may exist only to name the relay this session's attestations
609
+ // verify against; there is no frame to send and nothing to wait for, so the submit proceeds.
610
+ if (!sess.assignment.assignmentSignature)
611
+ return true;
563
612
  if (sess.recorded)
564
613
  return true;
565
614
  // Terminal rejection: a relay that cleanly rejected this assignment will reject it
@@ -724,52 +773,73 @@ export class AgentRelayClient {
724
773
  return Buffer.from(s1.fields.senderPubkey).equals(Buffer.from(this.#senderPubkey));
725
774
  }
726
775
  /**
727
- * Verify a relay `hash_submit_ack`'s signed ordering record and durably store the receipt.
728
- * The relay signs TBS = SHA-256(content_hash || seq_BE4 || ts_BE8) with its ack-signing key, whose hex is
729
- * `relay_id`. We verify SELF-CONSISTENCY (the signature binds the sequence ⇒ a FORGED sequence fails) and
730
- * record the immutable receipt. The authoritative registered-relay check is the directory's at seal
731
- * (OPTIONB-SEAL). No-op when there is no receipt store, no pending leaf, or the ACK is unsigned.
776
+ * The relay pubkey the DIRECTORY named for a session — 069-ORDERPROOF, and the only key a relay
777
+ * ordering attestation is ever checked against.
778
+ *
779
+ * It rides the assignment carry, which is built from an assignment whose FROST signature this
780
+ * daemon verified before the session began, so it is anchored to something the relay does not
781
+ * control. `undefined` means no such key was recorded, and every attestation on that session is
782
+ * then refused for want of an anchor — never accepted against whatever key the frame supplies.
783
+ */
784
+ #expectedRelayPubkeyHex(sessionIdHex) {
785
+ return this.#sessions.get(sessionIdHex)?.relayAnchorHex;
786
+ }
787
+ /**
788
+ * Verify a relay `hash_submit_ack`'s ordering attestation and durably store the receipt.
789
+ *
790
+ * The relay signs the session, the content hash, the position it assigned and the running root of
791
+ * the tree after this leaf. We verify it **against the relay key on the directory-signed
792
+ * assignment**, and refuse otherwise — missing, malformed and mismatched all take the one path.
793
+ *
794
+ * Returns true to REJECT the submit. A send must not settle ok on a position nothing witnessed.
732
795
  */
733
796
  #captureReceipt(frame, structure1Cbor, seq) {
734
- if (seq < 0 || !structure1Cbor)
735
- return false;
736
- // Structure 1 = [version, content_hash(32), sender_pubkey(32), session_id(16), last_seen_seq,
737
- // ts], plus last_seen_hash(32) at index 6 on a v2 claim (020-ACKHASH). content_hash is index 1
738
- // and session_id index 3 in both.
739
- const s1 = decodeStructure1(structure1Cbor);
740
- if (!s1.ok) {
741
- // Our OWN just-signed bytes — near-impossible to fail; surface it rather than drop silently.
742
- // The reason is carried because "we cannot read what we just wrote" and "we wrote a layout we
743
- // cannot name" are different faults with the same symptom.
744
- this.#logger.warn("relay.receipt.undecodable_leaf", { seq, structure1Reason: s1.reason });
797
+ // ⚠️ REJECTS WHEN THE CHECK COULD NOT BE RUN, not only when it failed — `readSubmittedLeaf`
798
+ // carries the reasoning. Both of these used to settle the send ok having verified nothing.
799
+ const leaf = readSubmittedLeaf(structure1Cbor, seq);
800
+ if (leaf.kind === "none")
745
801
  return false;
802
+ if (leaf.kind === "unreadable") {
803
+ this.#logger.warn(leaf.event, { seq, structure1Reason: leaf.reason, impact: "this side cannot read the leaf it just submitted, so the relay's ordering attestation has " +
804
+ "nothing to be checked against. The send is refused rather than settled on a position " +
805
+ "nothing witnessed." });
806
+ return true;
746
807
  }
747
- const contentHash = s1.fields.contentHash;
748
- const sessionId = s1.fields.sessionId;
808
+ const { contentHash, sessionId } = leaf;
809
+ const sessionIdHex = Buffer.from(sessionId).toString("hex");
749
810
  const ev = evaluateRelayAck({
811
+ sessionId,
750
812
  contentHash,
751
- sessionIdHex: Buffer.from(sessionId).toString("hex"),
813
+ runningRoot: frame["running_root"] instanceof Uint8Array ? frame["running_root"] : undefined,
814
+ sessionIdHex,
752
815
  agentPubkeyHex: this.senderPubkeyHex,
816
+ expectedRelayPubkeyHex: this.#expectedRelayPubkeyHex(sessionIdHex),
753
817
  relayId: typeof frame["relay_id"] === "string" ? frame["relay_id"] : undefined,
754
818
  relaySignature: frame["relay_signature"] instanceof Uint8Array ? frame["relay_signature"] : undefined,
755
819
  timestamp: typeof frame["timestamp"] === "number" ? frame["timestamp"] : undefined,
756
820
  sequenceNumber: seq,
757
821
  });
758
822
  switch (ev.kind) {
759
- case "unsigned":
760
- // A relay that SHOULD sign but didn't → no durable witness for this message. Unsigned ACKs are
761
- // tolerated, but make it diagnosable instead of invisible.
762
- this.#logger.debug("relay.receipt.unsigned", { seq, hashShort: Buffer.from(contentHash).toString("hex").slice(0, 16) });
763
- return false;
764
- case "bad_relay_id":
765
- this.#logger.warn("relay.receipt.bad_relay_id", { seq });
766
- return false;
767
- case "invalid_signature":
768
- // FORGED / corrupt ACK — the signature does not bind (hash, seq, ts). REJECT the submit so the send
769
- // does NOT settle ok on an unverified sequence (a forged ordering record must not drive ordering),
770
- // and store nothing. The send still completes via the direct
771
- // content path — the relay witness simply degrades to absent for this leaf.
772
- this.#logger.warn("relay.receipt.signature_invalid", { seq });
823
+ case "refused":
824
+ /**
825
+ * ONE OUTCOME, and the cause is in the log rather than in the control flow.
826
+ *
827
+ * The submit is rejected for all five causes. A message whose position no assigned relay
828
+ * attested has no ordering evidence behind it, and letting the send settle ok would report
829
+ * a witnessed message that nothing witnessed. `attestation_absent` takes this path with the
830
+ * rest deliberately: the party who can produce the absence is the relay, which is the party
831
+ * the check exists to constrain, so a softer answer for absence is a mute button with our
832
+ * own name on it.
833
+ */
834
+ this.#logger.warn("relay.attestation.refused", {
835
+ seq,
836
+ session: sessionIdHex,
837
+ cause: ev.cause,
838
+ hashShort: Buffer.from(contentHash).toString("hex").slice(0, 16),
839
+ impact: "the relay's ordering attestation for this message was refused, so this send did not " +
840
+ "settle and no evidence was stored. This agent holds no proof of where this message " +
841
+ "sits in the conversation, and nothing was recorded that could later be presented as one.",
842
+ });
773
843
  return true;
774
844
  case "store": {
775
845
  if (!this.#receiptStore)
@@ -821,6 +891,7 @@ export class AgentRelayClient {
821
891
  relayId: ev.receipt.relayId,
822
892
  relayTimestamp: ev.receipt.timestamp,
823
893
  relaySignatureHex: ev.receipt.signatureHex,
894
+ ...(ev.receipt.runningRootHex ? { relayRunningRootHex: ev.receipt.runningRootHex } : {}),
824
895
  }
825
896
  : {}),
826
897
  }, Date.now());
@@ -857,11 +928,77 @@ export class AgentRelayClient {
857
928
  // signed-but-INVALID ACK rejects the submit so the send does not settle ok on an unverified sequence.
858
929
  const rejectSubmit = this.#captureReceipt(frame, structure1Cbor, seq);
859
930
  this.#settlePending(rejectSubmit
860
- ? { ok: false, reason: "relay_ack_signature_invalid" }
931
+ /**
932
+ * ONE REASON for every refusal cause — 069-ORDERPROOF Done When 3. A distinct reason per
933
+ * cause would be observable, and the clause requires that a missing attestation and a
934
+ * malformed one look the same from outside. The cause is named in the log line above.
935
+ */
936
+ ? { ok: false, reason: "relay_ack_unverified" }
861
937
  : seq >= 0
862
938
  ? { ok: true, sequence_number: seq, structure1_cbor: structure1Cbor, structure2_cbor: structure2Cbor, sender_signature: senderSignature }
863
939
  : { ok: false, reason: "relay_ack_malformed" });
864
940
  }
941
+ else if (type === "session_liveness_response" || type === "session_liveness_refused") {
942
+ /**
943
+ * DOD-M15-AWAYSCOPE-1 — the relay's answer to "is my counterparty reachable, and is anyone
944
+ * attending it". Decoded through the shared codec rather than read field by field here: that
945
+ * codec is what refuses an attendance paired with a non-alive liveness, and re-reading the
946
+ * fields inline would quietly reintroduce the tolerance branch it exists to prevent.
947
+ *
948
+ * A REFUSAL resolves the waiter rather than dropping it. The relay refuses a query naming a
949
+ * session the caller is not in, and it deliberately does not say which of the two reasons —
950
+ * so the honest local answer is "unknown", not a hang until the timeout.
951
+ */
952
+ /**
953
+ * ⚠️ A REFUSAL NAMES NOTHING, so it cannot be matched. The relay refuses without echoing the
954
+ * session or the subject — deliberately, because telling "no such session" from "not your
955
+ * session" is the enumeration signal `DOD-M15-RELAYAUTH-1` closed. So there is nothing to key
956
+ * on, and the only sound reading is that every outstanding query on this stream was refused:
957
+ * the refusal is a property of the CALLER, and the caller is the same for all of them.
958
+ */
959
+ if (type === "session_liveness_refused") {
960
+ for (const r of this.#pendingLiveness.values())
961
+ r({ liveness: "unknown", observedAt: 0, refused: true });
962
+ this.#pendingLiveness.clear();
963
+ }
964
+ else {
965
+ const decoded = decodeSessionLivenessResponse(encodeCbor(frame));
966
+ if (decoded === null) {
967
+ // Malformed fails exactly like missing. A frame this build cannot read is not evidence of
968
+ // anything, and reporting it as 'gone' would invent an observation nobody made. It also
969
+ // cannot be matched to a waiter, so every outstanding query is answered 'unknown' rather
970
+ // than left to time out on a stream that just proved it speaks a shape we cannot read.
971
+ this.#logger.warn("session.relay.liveness.response_malformed", {
972
+ relayPeerId: this.#relayPeerId,
973
+ impact: "the counterparty's reachability is reported as unknown, which is what it is",
974
+ });
975
+ for (const r of this.#pendingLiveness.values())
976
+ r({ liveness: "unknown", observedAt: 0 });
977
+ this.#pendingLiveness.clear();
978
+ }
979
+ else {
980
+ // MATCHED ON WHAT THE ANSWER ITSELF NAMES. Resolving the most recent waiter instead would
981
+ // be right exactly once — when only one query is outstanding — and silently wrong the
982
+ // moment an agent holds two conversations through one relay, which is ordinary.
983
+ const key = livenessKey(decoded.session_id, decoded.counterparty_pubkey);
984
+ const r = this.#pendingLiveness.get(key);
985
+ if (r) {
986
+ this.#pendingLiveness.delete(key);
987
+ r({
988
+ liveness: decoded.liveness,
989
+ observedAt: decoded.observed_at,
990
+ ...(decoded.attendance !== undefined ? { attendance: decoded.attendance } : {}),
991
+ ...(decoded.attendance_observed_at !== undefined ? { attendanceObservedAt: decoded.attendance_observed_at } : {}),
992
+ });
993
+ }
994
+ else {
995
+ // A late answer to a query that already timed out, or one nobody asked for. Dropped —
996
+ // handing it to a different session's waiter is exactly the defect this key exists for.
997
+ this.#logger.debug("session.relay.liveness.response_unmatched", { relayPeerId: this.#relayPeerId });
998
+ }
999
+ }
1000
+ }
1001
+ }
865
1002
  else if (type === "hash_submit_error") {
866
1003
  const reason = typeof frame["reason"] === "string" ? frame["reason"] : "relay_rejected";
867
1004
  // Carry the relay's `detail` through — see `SubmitResult`. Reading the class and discarding
@@ -1046,6 +1183,69 @@ export class AgentRelayClient {
1046
1183
  this.#logger.warn("relay.seal_leaf.counterparty.capture_skipped", { seq, session: sidHex, hasS2: !!structure2Cbor, hasS1: s1.length > 0, hasSender: !!senderHex });
1047
1184
  }
1048
1185
  }
1186
+ /**
1187
+ * ─── THE RECIPIENT KEEPS THE ORDERING PROOF TOO — 069-ORDERPROOF unit 2 ──────────────────
1188
+ *
1189
+ * Before this, the relay's attestation went to the SENDER alone, on the submit
1190
+ * acknowledgement. The recipient held no proof of where a single message of the conversation
1191
+ * sat. That made one party's copy the only copy, which is the dependency this order exists to
1192
+ * remove wearing a different coat.
1193
+ *
1194
+ * It is verified here exactly as on the send path — against the relay key the DIRECTORY named
1195
+ * for this session, never `relay_id` on the frame — and an attestation that does not verify is
1196
+ * refused and NOT stored. Nothing else changes: the leaf is still delivered to the session, the
1197
+ * acknowledgement still advances, and no tree, root or leaf count is touched. This is evidence
1198
+ * recorded beside the chain, never in it.
1199
+ *
1200
+ * Our own echoed leaf comes through here too. Storing it is a no-op — the ack path already
1201
+ * wrote the same row at the same position, and the store is INSERT OR IGNORE — but it is not
1202
+ * skipped, because the echo is the only copy a leaf COUNTER-SUBMITTED by the counterparty
1203
+ * ever produces for us.
1204
+ */
1205
+ if (this.#receiptStore && seq >= 0 && deliveredS1.ok) {
1206
+ const ev = evaluateRelayAck({
1207
+ sessionId: deliveredS1.fields.sessionId,
1208
+ contentHash: deliveredS1.fields.contentHash,
1209
+ runningRoot: frame["running_root"] instanceof Uint8Array ? frame["running_root"] : undefined,
1210
+ sessionIdHex: sidHex,
1211
+ agentPubkeyHex: this.senderPubkeyHex,
1212
+ expectedRelayPubkeyHex: this.#expectedRelayPubkeyHex(sidHex),
1213
+ relayId: typeof frame["relay_id"] === "string" ? frame["relay_id"] : undefined,
1214
+ relaySignature: frame["relay_signature"] instanceof Uint8Array ? frame["relay_signature"] : undefined,
1215
+ timestamp: typeof frame["timestamp"] === "number" ? frame["timestamp"] : undefined,
1216
+ sequenceNumber: seq,
1217
+ });
1218
+ if (ev.kind === "refused") {
1219
+ /**
1220
+ * LOUD, AND THE DELIVERY STILL LANDS. This is the one place the two halves differ, and
1221
+ * deliberately: on the send path a refusal means OUR message has no witness, so the send
1222
+ * must not settle. Here the counterparty's message has already been written and read —
1223
+ * dropping it would let a relay silence a conversation by withholding its own signature,
1224
+ * which hands the party the check constrains a far better weapon than the one it takes
1225
+ * away. So the message arrives and the evidence is recorded as absent.
1226
+ */
1227
+ this.#logger.warn("relay.attestation.delivered.refused", {
1228
+ seq,
1229
+ session: sidHex,
1230
+ cause: ev.cause,
1231
+ impact: "this message arrived, but the relay's proof of WHERE it sits in the conversation did " +
1232
+ "not, so this agent cannot later show a third party that this message was ordered here. " +
1233
+ "The message itself is unaffected and is in the transcript.",
1234
+ });
1235
+ }
1236
+ else {
1237
+ try {
1238
+ this.#receiptStore.store(ev.receipt, Date.now());
1239
+ }
1240
+ catch (err) {
1241
+ // A durable-evidence write failure is LOUD: the relay never re-sends a delivery, so a
1242
+ // swallowed write permanently loses this side's only copy of the ordering proof.
1243
+ this.#logger.error("relay.attestation.delivered.store_failed", {
1244
+ seq, session: sidHex, error: extractErrorMessage(err),
1245
+ });
1246
+ }
1247
+ }
1248
+ }
1049
1249
  const session = this.#sessions.get(sidHex);
1050
1250
  if (session && seq >= 0) {
1051
1251
  session.onLeafDeliver({
@@ -1446,6 +1646,139 @@ export class AgentRelayClient {
1446
1646
  * ⚠️ **THE FRAME CARRIES NO PEER ID, deliberately.** The relay frees the peer this connection
1447
1647
  * authenticated as. A peer id on the wire would let any registered agent free another's.
1448
1648
  */
1649
+ /**
1650
+ * DOD-M15-AWAYSCOPE-1 — tell this relay whether anyone is attending this agent, for one session.
1651
+ *
1652
+ * ── WHY THIS EXISTS AT ALL ──────────────────────────────────────────────────────────────────────
1653
+ *
1654
+ * An unattended agent used to answer inbound messages with its away greeting. That greeting took a
1655
+ * hash-chain leaf inside a live conversation, and on session `e7dd3f43…` it cost two operators a
1656
+ * completed conversation's receipt, permanently. The fact itself is worth telling — a counterparty
1657
+ * mid-exchange genuinely needs to know whether to wait — but it is a fact ABOUT the session, not a
1658
+ * sentence IN it. So it rides here instead, and takes no leaf.
1659
+ *
1660
+ * ── FIRE AND FORGET, AND THAT IS THE DESIGN ─────────────────────────────────────────────────────
1661
+ *
1662
+ * Nothing is awaited and the relay sends no ack. The notice may be dropped, duplicated or arrive
1663
+ * out of order; `observed_at` settles it, last-write-wins. A failure changes nothing the operator
1664
+ * is doing — the counterparty reads "unknown" until the next notice, which is what is true.
1665
+ *
1666
+ * ⚠️ NO RETRY, NO QUEUE. Anything that made this reliable would want ordering, ordering wants a
1667
+ * witness, and a witnessed position is how machine chatter reached the leaf set. A status hint
1668
+ * that is allowed to be lost is the safe shape.
1669
+ */
1670
+ announceAttendance(node, sessionId, attendance) {
1671
+ if (this.#closed)
1672
+ return;
1673
+ void (async () => {
1674
+ try {
1675
+ if (!(await this.#ensureConnected(node)))
1676
+ return;
1677
+ const stream = this.#stream;
1678
+ if (!stream)
1679
+ return;
1680
+ stream.send(lp.encode.single(encodeSessionAttendanceNotice({
1681
+ type: "session_attendance_notice",
1682
+ session_id: sessionId,
1683
+ attendance,
1684
+ // OUR clock, stated plainly. The relay bounds it against its own and refuses a value too
1685
+ // far ahead rather than clamping — clamping would turn a hostile timestamp into a valid
1686
+ // recent one, and this client is the code an adversary gets to rewrite.
1687
+ observed_at: Date.now(),
1688
+ })));
1689
+ this.#logger.debug("session.relay.attendance.announced", {
1690
+ relayPeerId: this.#relayPeerId,
1691
+ sessionId: Buffer.from(sessionId).toString("hex").slice(0, 16),
1692
+ attendance,
1693
+ });
1694
+ }
1695
+ catch (err) {
1696
+ this.#logger.debug("session.relay.attendance.announce_failed", {
1697
+ relayPeerId: this.#relayPeerId,
1698
+ error: extractErrorMessage(err),
1699
+ impact: "the counterparty reads 'unknown' for this agent until the next notice lands",
1700
+ });
1701
+ }
1702
+ })();
1703
+ }
1704
+ /**
1705
+ * DOD-M15-AWAYSCOPE-1 — ask the relay about the counterparty: reachable, and attended?
1706
+ *
1707
+ * Two facts with two producers, which is why they are separate fields. `liveness` is the RELAY's
1708
+ * observation — it holds that agent's standing connection or it does not. `attendance` is the far
1709
+ * DAEMON's assertion about itself, which the relay was told and repeats; absent whenever
1710
+ * `liveness` is not 'alive', because a daemon nobody can reach asserts nothing.
1711
+ *
1712
+ * ⚠️ EVERY FAILURE ANSWERS 'unknown', never 'gone'. A timeout, a dead stream, a refusal and an
1713
+ * unparseable frame all mean "this side learned nothing"; reporting any as `gone` invents an
1714
+ * observation nobody made, and `gone` is the value that tells an operator their peer has left.
1715
+ */
1716
+ /**
1717
+ * Test-only seams for the liveness query path, which cannot be reached any other way.
1718
+ *
1719
+ * ⚠️ THEY EXIST BECAUSE A ONE-SESSION FAKE HID A REAL DEFECT. Every other test of this feature
1720
+ * stubs `queryLiveness` outright, so the code that matches an ANSWER to its QUESTION never ran —
1721
+ * and it was wrong: a single resolver slot handed one session's answer to another session's
1722
+ * promise the moment an agent held two conversations through one relay, which is ordinary.
1723
+ * Reaching that code needs a live stream and a dispatched frame, and both are private.
1724
+ *
1725
+ * Named `ForTest` like `__setLastActivityAtForTest` and `patchRelayClientForTest`, and doing
1726
+ * nothing production does not: one installs the stream a dial would have produced, the other
1727
+ * feeds the reader loop a frame the relay would have sent.
1728
+ */
1729
+ installStreamForTest(stream) { this.#stream = stream; }
1730
+ dispatchForTest(frame) { this.#dispatch(frame); }
1731
+ async queryLiveness(sessionId, counterpartyPubkey) {
1732
+ const unknown = { liveness: "unknown", observedAt: 0 };
1733
+ if (this.#closed)
1734
+ return unknown;
1735
+ /**
1736
+ * ⚠️ IT DOES NOT DIAL — the one place in this client that refuses to connect. Every other caller
1737
+ * here does the operator's work; this one serves a READ (`cello status`, `cello sessions`), and
1738
+ * a status command that opens a connection as a side effect changes what it is reporting on. It
1739
+ * would also make a read of a dozen sessions pay a dial each, against a budget measured in what
1740
+ * a person waits at a terminal. The cost is small and precise: right after a daemon restart a
1741
+ * status read says 'unknown' instead of dialling; the first real message establishes the stream.
1742
+ */
1743
+ const stream = this.#stream;
1744
+ if (!stream)
1745
+ return unknown;
1746
+ let resolveLiveness;
1747
+ const answer = new Promise((r) => { resolveLiveness = r; });
1748
+ const key = livenessKey(sessionId, counterpartyPubkey);
1749
+ this.#pendingLiveness.set(key, resolveLiveness);
1750
+ try {
1751
+ stream.send(lp.encode.single(encodeSessionLivenessQuery({
1752
+ type: "session_liveness_query",
1753
+ session_id: sessionId,
1754
+ counterparty_pubkey: counterpartyPubkey,
1755
+ })));
1756
+ }
1757
+ catch (err) {
1758
+ this.#pendingLiveness.delete(key);
1759
+ this.#logger.debug("session.relay.liveness.query_failed", {
1760
+ relayPeerId: this.#relayPeerId, error: extractErrorMessage(err),
1761
+ });
1762
+ return unknown;
1763
+ }
1764
+ let timer;
1765
+ const timeout = new Promise((r) => { timer = setTimeout(() => r("timeout"), HASH_SUBMIT_TIMEOUT_MS); });
1766
+ try {
1767
+ const result = await Promise.race([answer, timeout]);
1768
+ if (result === "timeout") {
1769
+ // NOT a stream reset, for the same reason a release timeout is not: a liveness query is not
1770
+ // ordered against anything, so tearing the shared stream down would cost every sibling
1771
+ // session its in-flight submits to tidy up one status read.
1772
+ this.#pendingLiveness.delete(key);
1773
+ this.#logger.debug("session.relay.liveness.query_timeout", { relayPeerId: this.#relayPeerId });
1774
+ return unknown;
1775
+ }
1776
+ return result;
1777
+ }
1778
+ finally {
1779
+ clearTimeout(timer);
1780
+ }
1781
+ }
1449
1782
  async releaseReservation(node) {
1450
1783
  if (this.#closed)
1451
1784
  return false;
@@ -1761,6 +2094,13 @@ export class AgentRelayClient {
1761
2094
  if (r)
1762
2095
  r(false);
1763
2096
  }
2097
+ // DOD-M15-AWAYSCOPE-1: and an in-flight liveness query, so a status read does not wait its
2098
+ // whole timeout on a stream that is already gone. "unknown" is the honest answer.
2099
+ {
2100
+ for (const r of this.#pendingLiveness.values())
2101
+ r({ liveness: "unknown", observedAt: 0 });
2102
+ this.#pendingLiveness.clear();
2103
+ }
1764
2104
  // A pure-receiver session issues no submit, so it would never trigger a re-dial
1765
2105
  // after the node that owned the stream is torn down. If sessions remain, proactively
1766
2106
  // re-establish from any still-live registered session node so queued leaf_delivers
@@ -2436,7 +2776,6 @@ export class AgentRelayClient {
2436
2776
  }
2437
2777
  }
2438
2778
  }
2439
- /** The highest relay-assigned sequence observed for a given session (ack or deliver). */
2440
2779
  /**
2441
2780
  * Advance this session's acknowledgement from a message that ARRIVED — 033-ACKEMIT review F1.
2442
2781
  *