termdock 1.4.240 → 1.4.242

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 (316) hide show
  1. package/dist/client/assets/App-CVuPbhP4.js +155 -0
  2. package/dist/client/assets/App-CVuPbhP4.js.br +0 -0
  3. package/dist/client/assets/App-CVuPbhP4.js.gz +0 -0
  4. package/dist/client/assets/{ChangeWalkthroughPanel-9whVVXTr.js → ChangeWalkthroughPanel-4kynRLRs.js} +1 -1
  5. package/dist/client/assets/ChangeWalkthroughPanel-4kynRLRs.js.br +0 -0
  6. package/dist/client/assets/ChangeWalkthroughPanel-4kynRLRs.js.gz +0 -0
  7. package/dist/client/assets/{DagPlayground-y80OTTQj.js → DagPlayground-Yx7XBwmM.js} +1 -1
  8. package/dist/client/assets/DagPlayground-Yx7XBwmM.js.br +0 -0
  9. package/dist/client/assets/DagPlayground-Yx7XBwmM.js.gz +0 -0
  10. package/dist/client/assets/{DiffLab-BY2wbRtg.js → DiffLab-Cn1f9iHY.js} +1 -1
  11. package/dist/client/assets/DiffLab-Cn1f9iHY.js.br +0 -0
  12. package/dist/client/assets/DiffLab-Cn1f9iHY.js.gz +0 -0
  13. package/dist/client/assets/{DiffReview-DLlDJbK1.js → DiffReview-BJQ92hBr.js} +1 -1
  14. package/dist/client/assets/DiffReview-BJQ92hBr.js.br +0 -0
  15. package/dist/client/assets/DiffReview-BJQ92hBr.js.gz +0 -0
  16. package/dist/client/assets/{DiffReviewLab-CEpa_B8I.js → DiffReviewLab-CN3a3LhH.js} +1 -1
  17. package/dist/client/assets/DiffReviewLab-CN3a3LhH.js.br +0 -0
  18. package/dist/client/assets/DiffReviewLab-CN3a3LhH.js.gz +0 -0
  19. package/dist/client/assets/{DiffViewer-GLkd1zMQ.js → DiffViewer-BFn2Gz8v.js} +1 -1
  20. package/dist/client/assets/DiffViewer-BFn2Gz8v.js.br +0 -0
  21. package/dist/client/assets/DiffViewer-BFn2Gz8v.js.gz +0 -0
  22. package/dist/client/assets/{ModelPreview-DB8tw45f.js → ModelPreview-CC8Uf4et.js} +1 -1
  23. package/dist/client/assets/ModelPreview-CC8Uf4et.js.br +0 -0
  24. package/dist/client/assets/ModelPreview-CC8Uf4et.js.gz +0 -0
  25. package/dist/client/assets/{RightSidebar-aoJjOQGX.js → RightSidebar-Bz9BkzCR.js} +4 -4
  26. package/dist/client/assets/RightSidebar-Bz9BkzCR.js.br +0 -0
  27. package/dist/client/assets/RightSidebar-Bz9BkzCR.js.gz +0 -0
  28. package/dist/client/assets/{abnfDiagram-VCTEODGH-RBGYciHa.js → abnfDiagram-VCTEODGH-hQSzKoeJ.js} +1 -1
  29. package/dist/client/assets/abnfDiagram-VCTEODGH-hQSzKoeJ.js.br +0 -0
  30. package/dist/client/assets/abnfDiagram-VCTEODGH-hQSzKoeJ.js.gz +0 -0
  31. package/dist/client/assets/{app-Ctrh4Bku.js → app-CgwJz96Y.js} +9 -9
  32. package/dist/client/assets/app-CgwJz96Y.js.br +0 -0
  33. package/dist/client/assets/app-CgwJz96Y.js.gz +0 -0
  34. package/dist/client/assets/{arc-CzQsNCup.js → arc-DNdtsFHs.js} +1 -1
  35. package/dist/client/assets/arc-DNdtsFHs.js.br +0 -0
  36. package/dist/client/assets/arc-DNdtsFHs.js.gz +0 -0
  37. package/dist/client/assets/{architectureDiagram-5GKGNRK7-sDp6hSiy.js → architectureDiagram-5GKGNRK7-ClYN-ZWK.js} +1 -1
  38. package/dist/client/assets/architectureDiagram-5GKGNRK7-ClYN-ZWK.js.br +0 -0
  39. package/dist/client/assets/architectureDiagram-5GKGNRK7-ClYN-ZWK.js.gz +0 -0
  40. package/dist/client/assets/{blockDiagram-I7D4REHJ-C-AHqZPo.js → blockDiagram-I7D4REHJ-ybw8N2u6.js} +1 -1
  41. package/dist/client/assets/blockDiagram-I7D4REHJ-ybw8N2u6.js.br +0 -0
  42. package/dist/client/assets/blockDiagram-I7D4REHJ-ybw8N2u6.js.gz +0 -0
  43. package/dist/client/assets/{c4Diagram-7LVT6UL2-B8VGhLwN.js → c4Diagram-7LVT6UL2-BUySB1D8.js} +1 -1
  44. package/dist/client/assets/c4Diagram-7LVT6UL2-BUySB1D8.js.br +0 -0
  45. package/dist/client/assets/c4Diagram-7LVT6UL2-BUySB1D8.js.gz +0 -0
  46. package/dist/client/assets/channel-C6y0-VyK.js +1 -0
  47. package/dist/client/assets/{chunk-2Q5K7J3B-D56jCJTr.js → chunk-2Q5K7J3B-DEG-dAIQ.js} +1 -1
  48. package/dist/client/assets/{chunk-5VM5RSS4-cga3WKIM.js → chunk-5VM5RSS4-DkNem54n.js} +1 -1
  49. package/dist/client/assets/{chunk-F27PBJKO-BNOR_7WA.js → chunk-F27PBJKO-D32jqKl9.js} +1 -1
  50. package/dist/client/assets/chunk-F27PBJKO-D32jqKl9.js.br +0 -0
  51. package/dist/client/assets/chunk-F27PBJKO-D32jqKl9.js.gz +0 -0
  52. package/dist/client/assets/{chunk-IMKFNOWR-Dk12DKtC.js → chunk-IMKFNOWR-JxJHaym5.js} +1 -1
  53. package/dist/client/assets/chunk-IMKFNOWR-JxJHaym5.js.br +0 -0
  54. package/dist/client/assets/chunk-IMKFNOWR-JxJHaym5.js.gz +0 -0
  55. package/dist/client/assets/{chunk-JWPE2WC7-CVqdLg0d.js → chunk-JWPE2WC7-CS7uV1GH.js} +1 -1
  56. package/dist/client/assets/{chunk-POPQ4Y6H-Y6gEzK15.js → chunk-POPQ4Y6H-B02kbaJZ.js} +1 -1
  57. package/dist/client/assets/{chunk-SVP7TREG-BIJtdFBL.js → chunk-SVP7TREG-Bc9XpKmH.js} +1 -1
  58. package/dist/client/assets/chunk-SVP7TREG-Bc9XpKmH.js.br +0 -0
  59. package/dist/client/assets/chunk-SVP7TREG-Bc9XpKmH.js.gz +0 -0
  60. package/dist/client/assets/{chunk-TICWLB2K-CS3jsxv7.js → chunk-TICWLB2K-DW69sulY.js} +1 -1
  61. package/dist/client/assets/chunk-TICWLB2K-DW69sulY.js.br +0 -0
  62. package/dist/client/assets/chunk-TICWLB2K-DW69sulY.js.gz +0 -0
  63. package/dist/client/assets/{chunk-XXDRQBXY-BYgvxPrj.js → chunk-XXDRQBXY-CqHkJ6cA.js} +1 -1
  64. package/dist/client/assets/classDiagram-ZZMXUADV-zxEN3eAk.js +1 -0
  65. package/dist/client/assets/classDiagram-v2-VYDZK3BY-zxEN3eAk.js +1 -0
  66. package/dist/client/assets/{cose-bilkent-JH36ORCC-9udJiW7h.js → cose-bilkent-JH36ORCC-DJAx_fGd.js} +1 -1
  67. package/dist/client/assets/cose-bilkent-JH36ORCC-DJAx_fGd.js.br +0 -0
  68. package/dist/client/assets/cose-bilkent-JH36ORCC-DJAx_fGd.js.gz +0 -0
  69. package/dist/client/assets/{cynefin-OW5HDTMX-D-6q-6N2.js → cynefin-OW5HDTMX-BJmu05nC.js} +1 -1
  70. package/dist/client/assets/cynefin-OW5HDTMX-BJmu05nC.js.br +0 -0
  71. package/dist/client/assets/{cynefin-OW5HDTMX-D-6q-6N2.js.gz → cynefin-OW5HDTMX-BJmu05nC.js.gz} +0 -0
  72. package/dist/client/assets/{cynefinDiagram-5FMLGOSQ-B5c37uFA.js → cynefinDiagram-5FMLGOSQ-B0m0YIa6.js} +1 -1
  73. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-B0m0YIa6.js.br +0 -0
  74. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-B0m0YIa6.js.gz +0 -0
  75. package/dist/client/assets/{dagre-GXQ25YYZ-DoFMIka4.js → dagre-GXQ25YYZ-Cbs-u5oy.js} +1 -1
  76. package/dist/client/assets/dagre-GXQ25YYZ-Cbs-u5oy.js.br +0 -0
  77. package/dist/client/assets/dagre-GXQ25YYZ-Cbs-u5oy.js.gz +0 -0
  78. package/dist/client/assets/{diagram-S7CK7UJ4-DrAwxGx7.js → diagram-S7CK7UJ4-DnFgNCva.js} +1 -1
  79. package/dist/client/assets/diagram-S7CK7UJ4-DnFgNCva.js.br +0 -0
  80. package/dist/client/assets/diagram-S7CK7UJ4-DnFgNCva.js.gz +0 -0
  81. package/dist/client/assets/{diagram-UQ7AKVKN-DbWfEzKd.js → diagram-UQ7AKVKN-CRbBEuHO.js} +1 -1
  82. package/dist/client/assets/diagram-UQ7AKVKN-CRbBEuHO.js.br +0 -0
  83. package/dist/client/assets/diagram-UQ7AKVKN-CRbBEuHO.js.gz +0 -0
  84. package/dist/client/assets/{diagram-VSXAHHWV-zKcVacRq.js → diagram-VSXAHHWV-CIPivMwW.js} +1 -1
  85. package/dist/client/assets/diagram-VSXAHHWV-CIPivMwW.js.br +0 -0
  86. package/dist/client/assets/diagram-VSXAHHWV-CIPivMwW.js.gz +0 -0
  87. package/dist/client/assets/{diagram-VX7I27RA-BNAI-5sG.js → diagram-VX7I27RA-CY8G867I.js} +1 -1
  88. package/dist/client/assets/diagram-VX7I27RA-CY8G867I.js.br +0 -0
  89. package/dist/client/assets/diagram-VX7I27RA-CY8G867I.js.gz +0 -0
  90. package/dist/client/assets/{diagram-Z3DM3KII-ChB9ZeuK.js → diagram-Z3DM3KII-owVjuxom.js} +1 -1
  91. package/dist/client/assets/diagram-Z3DM3KII-owVjuxom.js.br +0 -0
  92. package/dist/client/assets/diagram-Z3DM3KII-owVjuxom.js.gz +0 -0
  93. package/dist/client/assets/{ebnfDiagram-PWID7BFC-Fe8VFmWJ.js → ebnfDiagram-PWID7BFC-DMoOEDnf.js} +1 -1
  94. package/dist/client/assets/ebnfDiagram-PWID7BFC-DMoOEDnf.js.br +0 -0
  95. package/dist/client/assets/ebnfDiagram-PWID7BFC-DMoOEDnf.js.gz +0 -0
  96. package/dist/client/assets/{erDiagram-RLTQ6QDP-CC7DagoX.js → erDiagram-RLTQ6QDP-DuEHUYT0.js} +1 -1
  97. package/dist/client/assets/erDiagram-RLTQ6QDP-DuEHUYT0.js.br +0 -0
  98. package/dist/client/assets/erDiagram-RLTQ6QDP-DuEHUYT0.js.gz +0 -0
  99. package/dist/client/assets/{flowDiagram-HODETNUW-BBIgixMV.js → flowDiagram-HODETNUW-Duys8g5v.js} +1 -1
  100. package/dist/client/assets/flowDiagram-HODETNUW-Duys8g5v.js.br +0 -0
  101. package/dist/client/assets/flowDiagram-HODETNUW-Duys8g5v.js.gz +0 -0
  102. package/dist/client/assets/{ganttDiagram-EL5Y4UJY-CHRaIQ9P.js → ganttDiagram-EL5Y4UJY-4uNGC3eO.js} +1 -1
  103. package/dist/client/assets/ganttDiagram-EL5Y4UJY-4uNGC3eO.js.br +0 -0
  104. package/dist/client/assets/ganttDiagram-EL5Y4UJY-4uNGC3eO.js.gz +0 -0
  105. package/dist/client/assets/{gestureArbiter-5c1oGojb.js → gestureArbiter-CTk63JTf.js} +1 -1
  106. package/dist/client/assets/gestureArbiter-CTk63JTf.js.br +0 -0
  107. package/dist/client/assets/gestureArbiter-CTk63JTf.js.gz +0 -0
  108. package/dist/client/assets/{gitGraphDiagram-WWUBYQGX-iJPivC9C.js → gitGraphDiagram-WWUBYQGX-CoNcYxET.js} +1 -1
  109. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-CoNcYxET.js.br +0 -0
  110. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-CoNcYxET.js.gz +0 -0
  111. package/dist/client/assets/{index-BzglvLj5.css → index-QFRD5OND.css} +1 -1
  112. package/dist/client/assets/index-QFRD5OND.css.br +0 -0
  113. package/dist/client/assets/{index-BzglvLj5.css.gz → index-QFRD5OND.css.gz} +0 -0
  114. package/dist/client/assets/{infoDiagram-27XIBGKW-CWjxPUb1.js → infoDiagram-27XIBGKW-D1APvjL0.js} +1 -1
  115. package/dist/client/assets/{ishikawaDiagram-5VMMS53U-2dN_H6WK.js → ishikawaDiagram-5VMMS53U-B0CGmgD9.js} +1 -1
  116. package/dist/client/assets/ishikawaDiagram-5VMMS53U-B0CGmgD9.js.br +0 -0
  117. package/dist/client/assets/ishikawaDiagram-5VMMS53U-B0CGmgD9.js.gz +0 -0
  118. package/dist/client/assets/{journeyDiagram-3NMN7TZE-BqY-OLE2.js → journeyDiagram-3NMN7TZE-BIcr4OmP.js} +1 -1
  119. package/dist/client/assets/journeyDiagram-3NMN7TZE-BIcr4OmP.js.br +0 -0
  120. package/dist/client/assets/journeyDiagram-3NMN7TZE-BIcr4OmP.js.gz +0 -0
  121. package/dist/client/assets/{kanban-definition-UXKFOSKX-CSOXhjNh.js → kanban-definition-UXKFOSKX-BGY-UCFp.js} +1 -1
  122. package/dist/client/assets/kanban-definition-UXKFOSKX-BGY-UCFp.js.br +0 -0
  123. package/dist/client/assets/kanban-definition-UXKFOSKX-BGY-UCFp.js.gz +0 -0
  124. package/dist/client/assets/{layout-BxIcRRf7.js → layout-Dy-XBjcQ.js} +1 -1
  125. package/dist/client/assets/layout-Dy-XBjcQ.js.br +0 -0
  126. package/dist/client/assets/layout-Dy-XBjcQ.js.gz +0 -0
  127. package/dist/client/assets/{linear-BYWiw-Yd.js → linear-DGdoGGqI.js} +1 -1
  128. package/dist/client/assets/linear-DGdoGGqI.js.br +0 -0
  129. package/dist/client/assets/linear-DGdoGGqI.js.gz +0 -0
  130. package/dist/client/assets/{mermaid.core-DhRpdkKn.js → mermaid.core-uUtQ6Zvd.js} +5 -5
  131. package/dist/client/assets/mermaid.core-uUtQ6Zvd.js.br +0 -0
  132. package/dist/client/assets/mermaid.core-uUtQ6Zvd.js.gz +0 -0
  133. package/dist/client/assets/{mindmap-definition-YA3MSWOX-DwBcGwTF.js → mindmap-definition-YA3MSWOX-BBMP8prO.js} +1 -1
  134. package/dist/client/assets/mindmap-definition-YA3MSWOX-BBMP8prO.js.br +0 -0
  135. package/dist/client/assets/mindmap-definition-YA3MSWOX-BBMP8prO.js.gz +0 -0
  136. package/dist/client/assets/{passwordBootstrap-BkAa-DO2.js → passwordBootstrap-CazWrYzP.js} +1 -1
  137. package/dist/client/assets/{passwordBootstrap-BkAa-DO2.js.br → passwordBootstrap-CazWrYzP.js.br} +0 -0
  138. package/dist/client/assets/{passwordBootstrap-BkAa-DO2.js.gz → passwordBootstrap-CazWrYzP.js.gz} +0 -0
  139. package/dist/client/assets/{pegDiagram-XKGWAZYB-D_04AQMs.js → pegDiagram-XKGWAZYB-BvxAwgS8.js} +1 -1
  140. package/dist/client/assets/pegDiagram-XKGWAZYB-BvxAwgS8.js.br +0 -0
  141. package/dist/client/assets/pegDiagram-XKGWAZYB-BvxAwgS8.js.gz +0 -0
  142. package/dist/client/assets/{pieDiagram-E7YTZNPT-DgHIGdDc.js → pieDiagram-E7YTZNPT-DZ4F26FA.js} +1 -1
  143. package/dist/client/assets/pieDiagram-E7YTZNPT-DZ4F26FA.js.br +0 -0
  144. package/dist/client/assets/pieDiagram-E7YTZNPT-DZ4F26FA.js.gz +0 -0
  145. package/dist/client/assets/{quadrantDiagram-AXDQQJYC-BrxP_uCp.js → quadrantDiagram-AXDQQJYC-FJGBvmNp.js} +1 -1
  146. package/dist/client/assets/quadrantDiagram-AXDQQJYC-FJGBvmNp.js.br +0 -0
  147. package/dist/client/assets/quadrantDiagram-AXDQQJYC-FJGBvmNp.js.gz +0 -0
  148. package/dist/client/assets/{railroadDiagram-O6MQD6OU-Bj8aV8et.js → railroadDiagram-O6MQD6OU-B4f16qlN.js} +1 -1
  149. package/dist/client/assets/railroadDiagram-O6MQD6OU-B4f16qlN.js.br +0 -0
  150. package/dist/client/assets/railroadDiagram-O6MQD6OU-B4f16qlN.js.gz +0 -0
  151. package/dist/client/assets/{referenceLongPress-CG4k8F2W.js → referenceLongPress-4ydKrZtC.js} +1 -1
  152. package/dist/client/assets/referenceLongPress-4ydKrZtC.js.br +0 -0
  153. package/dist/client/assets/referenceLongPress-4ydKrZtC.js.gz +0 -0
  154. package/dist/client/assets/{requirementDiagram-BXWQKSXE-DHOBnmaH.js → requirementDiagram-BXWQKSXE-DDEDP28y.js} +1 -1
  155. package/dist/client/assets/requirementDiagram-BXWQKSXE-DDEDP28y.js.br +0 -0
  156. package/dist/client/assets/requirementDiagram-BXWQKSXE-DDEDP28y.js.gz +0 -0
  157. package/dist/client/assets/{sankeyDiagram-P5KCCOFB-B46rNwzQ.js → sankeyDiagram-P5KCCOFB-eZbHgAJ2.js} +1 -1
  158. package/dist/client/assets/sankeyDiagram-P5KCCOFB-eZbHgAJ2.js.br +0 -0
  159. package/dist/client/assets/sankeyDiagram-P5KCCOFB-eZbHgAJ2.js.gz +0 -0
  160. package/dist/client/assets/{sequenceDiagram-WJ2MYXX4-D8PnDgC6.js → sequenceDiagram-WJ2MYXX4-C26sID_J.js} +1 -1
  161. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-C26sID_J.js.br +0 -0
  162. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-C26sID_J.js.gz +0 -0
  163. package/dist/client/assets/{sizeCapture-INFHLROL-CjofpSnZ.js → sizeCapture-INFHLROL-CunqRjZH.js} +1 -1
  164. package/dist/client/assets/sizeCapture-INFHLROL-CunqRjZH.js.br +0 -0
  165. package/dist/client/assets/sizeCapture-INFHLROL-CunqRjZH.js.gz +0 -0
  166. package/dist/client/assets/{sparkles-Zi8g0TMb.js → sparkles-Cs8KAbL4.js} +1 -1
  167. package/dist/client/assets/{stateDiagram-D77RDMKH-BX_StFJV.js → stateDiagram-D77RDMKH-BDCgrd2K.js} +1 -1
  168. package/dist/client/assets/stateDiagram-D77RDMKH-BDCgrd2K.js.br +0 -0
  169. package/dist/client/assets/stateDiagram-D77RDMKH-BDCgrd2K.js.gz +0 -0
  170. package/dist/client/assets/stateDiagram-v2-MP3YSRHH-JBMsRqan.js +1 -0
  171. package/dist/client/assets/{swimlanes-42K2YHIH-bxGulCYh.js → swimlanes-42K2YHIH-ClJ98iVo.js} +1 -1
  172. package/dist/client/assets/swimlanes-42K2YHIH-ClJ98iVo.js.br +0 -0
  173. package/dist/client/assets/swimlanes-42K2YHIH-ClJ98iVo.js.gz +0 -0
  174. package/dist/client/assets/swimlanesDiagram-VR7AAH4N-BvtpepbK.js +8 -0
  175. package/dist/client/assets/{timeline-definition-24CTP7MA-DcHYPI0d.js → timeline-definition-24CTP7MA-CDCDunzZ.js} +1 -1
  176. package/dist/client/assets/timeline-definition-24CTP7MA-CDCDunzZ.js.br +0 -0
  177. package/dist/client/assets/{timeline-definition-24CTP7MA-DcHYPI0d.js.gz → timeline-definition-24CTP7MA-CDCDunzZ.js.gz} +0 -0
  178. package/dist/client/assets/{triangle-alert-BXXcxTk8.js → triangle-alert-B0gXRJJm.js} +1 -1
  179. package/dist/client/assets/{vennDiagram-4TSXK5OY-CjIGwkZf.js → vennDiagram-4TSXK5OY-BBqRUM5-.js} +1 -1
  180. package/dist/client/assets/{vennDiagram-4TSXK5OY-CjIGwkZf.js.br → vennDiagram-4TSXK5OY-BBqRUM5-.js.br} +0 -0
  181. package/dist/client/assets/vennDiagram-4TSXK5OY-BBqRUM5-.js.gz +0 -0
  182. package/dist/client/assets/{wardleyDiagram-VM6X3IG4-B-WK3Fil.js → wardleyDiagram-VM6X3IG4-DKpVgjww.js} +1 -1
  183. package/dist/client/assets/wardleyDiagram-VM6X3IG4-DKpVgjww.js.br +0 -0
  184. package/dist/client/assets/wardleyDiagram-VM6X3IG4-DKpVgjww.js.gz +0 -0
  185. package/dist/client/assets/{xychartDiagram-S5SC5T6Z-4RzKQfNK.js → xychartDiagram-S5SC5T6Z-CHwA2dfA.js} +1 -1
  186. package/dist/client/assets/xychartDiagram-S5SC5T6Z-CHwA2dfA.js.br +0 -0
  187. package/dist/client/assets/{xychartDiagram-S5SC5T6Z-4RzKQfNK.js.gz → xychartDiagram-S5SC5T6Z-CHwA2dfA.js.gz} +0 -0
  188. package/dist/client/index.html +2 -2
  189. package/dist/client/index.html.br +0 -0
  190. package/dist/client/index.html.gz +0 -0
  191. package/dist/client/sw.js +1 -1
  192. package/dist/client/sw.js.br +0 -0
  193. package/dist/client/sw.js.gz +0 -0
  194. package/dist/server/cli.js +56 -42
  195. package/dist/server/entry.js +24 -2
  196. package/dist/server/federation/relay.js +3 -0
  197. package/dist/server/federation/routeAccess.js +39 -2
  198. package/dist/server/federation/runtime.js +5 -0
  199. package/dist/server/federation/selfRelay.js +182 -0
  200. package/package.json +1 -1
  201. package/runtime-manifest.json +3 -3
  202. package/dist/client/assets/App-CmlGDKDj.js +0 -155
  203. package/dist/client/assets/App-CmlGDKDj.js.br +0 -0
  204. package/dist/client/assets/App-CmlGDKDj.js.gz +0 -0
  205. package/dist/client/assets/ChangeWalkthroughPanel-9whVVXTr.js.br +0 -0
  206. package/dist/client/assets/ChangeWalkthroughPanel-9whVVXTr.js.gz +0 -0
  207. package/dist/client/assets/DagPlayground-y80OTTQj.js.br +0 -0
  208. package/dist/client/assets/DagPlayground-y80OTTQj.js.gz +0 -0
  209. package/dist/client/assets/DiffLab-BY2wbRtg.js.br +0 -0
  210. package/dist/client/assets/DiffLab-BY2wbRtg.js.gz +0 -0
  211. package/dist/client/assets/DiffReview-DLlDJbK1.js.br +0 -0
  212. package/dist/client/assets/DiffReview-DLlDJbK1.js.gz +0 -0
  213. package/dist/client/assets/DiffReviewLab-CEpa_B8I.js.br +0 -0
  214. package/dist/client/assets/DiffReviewLab-CEpa_B8I.js.gz +0 -0
  215. package/dist/client/assets/DiffViewer-GLkd1zMQ.js.br +0 -0
  216. package/dist/client/assets/DiffViewer-GLkd1zMQ.js.gz +0 -0
  217. package/dist/client/assets/ModelPreview-DB8tw45f.js.br +0 -0
  218. package/dist/client/assets/ModelPreview-DB8tw45f.js.gz +0 -0
  219. package/dist/client/assets/RightSidebar-aoJjOQGX.js.br +0 -0
  220. package/dist/client/assets/RightSidebar-aoJjOQGX.js.gz +0 -0
  221. package/dist/client/assets/abnfDiagram-VCTEODGH-RBGYciHa.js.br +0 -0
  222. package/dist/client/assets/abnfDiagram-VCTEODGH-RBGYciHa.js.gz +0 -0
  223. package/dist/client/assets/app-Ctrh4Bku.js.br +0 -0
  224. package/dist/client/assets/app-Ctrh4Bku.js.gz +0 -0
  225. package/dist/client/assets/arc-CzQsNCup.js.br +0 -0
  226. package/dist/client/assets/arc-CzQsNCup.js.gz +0 -0
  227. package/dist/client/assets/architectureDiagram-5GKGNRK7-sDp6hSiy.js.br +0 -0
  228. package/dist/client/assets/architectureDiagram-5GKGNRK7-sDp6hSiy.js.gz +0 -0
  229. package/dist/client/assets/blockDiagram-I7D4REHJ-C-AHqZPo.js.br +0 -0
  230. package/dist/client/assets/blockDiagram-I7D4REHJ-C-AHqZPo.js.gz +0 -0
  231. package/dist/client/assets/c4Diagram-7LVT6UL2-B8VGhLwN.js.br +0 -0
  232. package/dist/client/assets/c4Diagram-7LVT6UL2-B8VGhLwN.js.gz +0 -0
  233. package/dist/client/assets/channel-zK78er-R.js +0 -1
  234. package/dist/client/assets/chunk-F27PBJKO-BNOR_7WA.js.br +0 -0
  235. package/dist/client/assets/chunk-F27PBJKO-BNOR_7WA.js.gz +0 -0
  236. package/dist/client/assets/chunk-IMKFNOWR-Dk12DKtC.js.br +0 -0
  237. package/dist/client/assets/chunk-IMKFNOWR-Dk12DKtC.js.gz +0 -0
  238. package/dist/client/assets/chunk-SVP7TREG-BIJtdFBL.js.br +0 -0
  239. package/dist/client/assets/chunk-SVP7TREG-BIJtdFBL.js.gz +0 -0
  240. package/dist/client/assets/chunk-TICWLB2K-CS3jsxv7.js.br +0 -0
  241. package/dist/client/assets/chunk-TICWLB2K-CS3jsxv7.js.gz +0 -0
  242. package/dist/client/assets/classDiagram-ZZMXUADV-BMh5Sak3.js +0 -1
  243. package/dist/client/assets/classDiagram-v2-VYDZK3BY-BMh5Sak3.js +0 -1
  244. package/dist/client/assets/cose-bilkent-JH36ORCC-9udJiW7h.js.br +0 -0
  245. package/dist/client/assets/cose-bilkent-JH36ORCC-9udJiW7h.js.gz +0 -0
  246. package/dist/client/assets/cynefin-OW5HDTMX-D-6q-6N2.js.br +0 -0
  247. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-B5c37uFA.js.br +0 -0
  248. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-B5c37uFA.js.gz +0 -0
  249. package/dist/client/assets/dagre-GXQ25YYZ-DoFMIka4.js.br +0 -0
  250. package/dist/client/assets/dagre-GXQ25YYZ-DoFMIka4.js.gz +0 -0
  251. package/dist/client/assets/diagram-S7CK7UJ4-DrAwxGx7.js.br +0 -0
  252. package/dist/client/assets/diagram-S7CK7UJ4-DrAwxGx7.js.gz +0 -0
  253. package/dist/client/assets/diagram-UQ7AKVKN-DbWfEzKd.js.br +0 -0
  254. package/dist/client/assets/diagram-UQ7AKVKN-DbWfEzKd.js.gz +0 -0
  255. package/dist/client/assets/diagram-VSXAHHWV-zKcVacRq.js.br +0 -0
  256. package/dist/client/assets/diagram-VSXAHHWV-zKcVacRq.js.gz +0 -0
  257. package/dist/client/assets/diagram-VX7I27RA-BNAI-5sG.js.br +0 -0
  258. package/dist/client/assets/diagram-VX7I27RA-BNAI-5sG.js.gz +0 -0
  259. package/dist/client/assets/diagram-Z3DM3KII-ChB9ZeuK.js.br +0 -0
  260. package/dist/client/assets/diagram-Z3DM3KII-ChB9ZeuK.js.gz +0 -0
  261. package/dist/client/assets/ebnfDiagram-PWID7BFC-Fe8VFmWJ.js.br +0 -0
  262. package/dist/client/assets/ebnfDiagram-PWID7BFC-Fe8VFmWJ.js.gz +0 -0
  263. package/dist/client/assets/erDiagram-RLTQ6QDP-CC7DagoX.js.br +0 -0
  264. package/dist/client/assets/erDiagram-RLTQ6QDP-CC7DagoX.js.gz +0 -0
  265. package/dist/client/assets/flowDiagram-HODETNUW-BBIgixMV.js.br +0 -0
  266. package/dist/client/assets/flowDiagram-HODETNUW-BBIgixMV.js.gz +0 -0
  267. package/dist/client/assets/ganttDiagram-EL5Y4UJY-CHRaIQ9P.js.br +0 -0
  268. package/dist/client/assets/ganttDiagram-EL5Y4UJY-CHRaIQ9P.js.gz +0 -0
  269. package/dist/client/assets/gestureArbiter-5c1oGojb.js.br +0 -0
  270. package/dist/client/assets/gestureArbiter-5c1oGojb.js.gz +0 -0
  271. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-iJPivC9C.js.br +0 -0
  272. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-iJPivC9C.js.gz +0 -0
  273. package/dist/client/assets/index-BzglvLj5.css.br +0 -0
  274. package/dist/client/assets/ishikawaDiagram-5VMMS53U-2dN_H6WK.js.br +0 -0
  275. package/dist/client/assets/ishikawaDiagram-5VMMS53U-2dN_H6WK.js.gz +0 -0
  276. package/dist/client/assets/journeyDiagram-3NMN7TZE-BqY-OLE2.js.br +0 -0
  277. package/dist/client/assets/journeyDiagram-3NMN7TZE-BqY-OLE2.js.gz +0 -0
  278. package/dist/client/assets/kanban-definition-UXKFOSKX-CSOXhjNh.js.br +0 -0
  279. package/dist/client/assets/kanban-definition-UXKFOSKX-CSOXhjNh.js.gz +0 -0
  280. package/dist/client/assets/layout-BxIcRRf7.js.br +0 -0
  281. package/dist/client/assets/layout-BxIcRRf7.js.gz +0 -0
  282. package/dist/client/assets/linear-BYWiw-Yd.js.br +0 -0
  283. package/dist/client/assets/linear-BYWiw-Yd.js.gz +0 -0
  284. package/dist/client/assets/mermaid.core-DhRpdkKn.js.br +0 -0
  285. package/dist/client/assets/mermaid.core-DhRpdkKn.js.gz +0 -0
  286. package/dist/client/assets/mindmap-definition-YA3MSWOX-DwBcGwTF.js.br +0 -0
  287. package/dist/client/assets/mindmap-definition-YA3MSWOX-DwBcGwTF.js.gz +0 -0
  288. package/dist/client/assets/pegDiagram-XKGWAZYB-D_04AQMs.js.br +0 -0
  289. package/dist/client/assets/pegDiagram-XKGWAZYB-D_04AQMs.js.gz +0 -0
  290. package/dist/client/assets/pieDiagram-E7YTZNPT-DgHIGdDc.js.br +0 -0
  291. package/dist/client/assets/pieDiagram-E7YTZNPT-DgHIGdDc.js.gz +0 -0
  292. package/dist/client/assets/quadrantDiagram-AXDQQJYC-BrxP_uCp.js.br +0 -0
  293. package/dist/client/assets/quadrantDiagram-AXDQQJYC-BrxP_uCp.js.gz +0 -0
  294. package/dist/client/assets/railroadDiagram-O6MQD6OU-Bj8aV8et.js.br +0 -0
  295. package/dist/client/assets/railroadDiagram-O6MQD6OU-Bj8aV8et.js.gz +0 -0
  296. package/dist/client/assets/referenceLongPress-CG4k8F2W.js.br +0 -0
  297. package/dist/client/assets/referenceLongPress-CG4k8F2W.js.gz +0 -0
  298. package/dist/client/assets/requirementDiagram-BXWQKSXE-DHOBnmaH.js.br +0 -0
  299. package/dist/client/assets/requirementDiagram-BXWQKSXE-DHOBnmaH.js.gz +0 -0
  300. package/dist/client/assets/sankeyDiagram-P5KCCOFB-B46rNwzQ.js.br +0 -0
  301. package/dist/client/assets/sankeyDiagram-P5KCCOFB-B46rNwzQ.js.gz +0 -0
  302. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-D8PnDgC6.js.br +0 -0
  303. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-D8PnDgC6.js.gz +0 -0
  304. package/dist/client/assets/sizeCapture-INFHLROL-CjofpSnZ.js.br +0 -0
  305. package/dist/client/assets/sizeCapture-INFHLROL-CjofpSnZ.js.gz +0 -0
  306. package/dist/client/assets/stateDiagram-D77RDMKH-BX_StFJV.js.br +0 -0
  307. package/dist/client/assets/stateDiagram-D77RDMKH-BX_StFJV.js.gz +0 -0
  308. package/dist/client/assets/stateDiagram-v2-MP3YSRHH-CMG96YGj.js +0 -1
  309. package/dist/client/assets/swimlanes-42K2YHIH-bxGulCYh.js.br +0 -0
  310. package/dist/client/assets/swimlanes-42K2YHIH-bxGulCYh.js.gz +0 -0
  311. package/dist/client/assets/swimlanesDiagram-VR7AAH4N-sPKOywKp.js +0 -8
  312. package/dist/client/assets/timeline-definition-24CTP7MA-DcHYPI0d.js.br +0 -0
  313. package/dist/client/assets/vennDiagram-4TSXK5OY-CjIGwkZf.js.gz +0 -0
  314. package/dist/client/assets/wardleyDiagram-VM6X3IG4-B-WK3Fil.js.br +0 -0
  315. package/dist/client/assets/wardleyDiagram-VM6X3IG4-B-WK3Fil.js.gz +0 -0
  316. package/dist/client/assets/xychartDiagram-S5SC5T6Z-4RzKQfNK.js.br +0 -0
@@ -14,6 +14,7 @@ import { RouteInvitationStore } from './federation/routeInvitations.js';
14
14
  import { attachRegisteredDirectTargets, verifyDirectTarget } from './federation/directRoutes.js';
15
15
  import { secureChannelOriginAllowed } from './federation/originPolicy.js';
16
16
  import { RelayRouter } from './federation/relay.js';
17
+ import { DesktopSelfRelay } from './federation/selfRelay.js';
17
18
  import { assertPublicSecurity, securityHeaders } from './utils/publicSecurity.js';
18
19
  import { apiCachePolicy } from './utils/apiCachePolicy.js';
19
20
  import 'dotenv/config';
@@ -415,13 +416,15 @@ export function startServer(options = {}) {
415
416
  let entrySubjectAllowed = (_subjectId) => false;
416
417
  let routeInvitations;
417
418
  let federationServiceId = '';
419
+ let activeRouteIds = () => [];
418
420
  const desktopTargets = () => desktopDirectTargets(path.join(homedir(), '.termdock', 'desktop.json'), federationServiceId);
419
- const routeAccess = new RouteAccess(path.join(homedir(), '.termdock', 'federation', 'routes.json'), Date.now, (subjectId, targetServiceId) => routeInvitations?.allows(subjectId, targetServiceId) === true || collaborationTransport?.canRoute(subjectId, targetServiceId) === true, desktopTargets);
421
+ const routeAccess = new RouteAccess(path.join(homedir(), '.termdock', 'federation', 'routes.json'), Date.now, (subjectId, targetServiceId) => routeInvitations?.allows(subjectId, targetServiceId) === true || collaborationTransport?.canRoute(subjectId, targetServiceId) === true, desktopTargets, () => activeRouteIds());
420
422
  const relayRouter = new RelayRouter({
421
423
  authenticate: context => context,
422
424
  allowRegister: (principal, serviceId) => routeAccess.allowRegister(principal, serviceId),
423
425
  allowRoute: (principal, serviceId) => routeAccess.allowRoute(principal, serviceId),
424
426
  });
427
+ activeRouteIds = () => relayRouter.activeRouteIds();
425
428
  const dynamicDirectTargets = new Map();
426
429
  const refreshDirectTargets = () => {
427
430
  const desired = new Map(routeAccess.configuredDirectTargets().filter(target => target.serviceId !== federationServiceId).map(target => [target.serviceId, target]));
@@ -493,6 +496,7 @@ export function startServer(options = {}) {
493
496
  },
494
497
  revokeRouteAccess: id => routeInvitations?.revoke(id) || false,
495
498
  issueRouteTicket: (subjectId, serviceId) => routeAccess.issueRouteTicket(subjectId, serviceId),
499
+ issueSelfRelayTicket: (serviceId) => routeAccess.issueSelfRelayTicket(serviceId),
496
500
  hasRouteGrant: (subjectId, serviceId) => routeInvitations?.allows(subjectId, serviceId) === true || collaborationTransport?.canRoute(subjectId, serviceId) === true,
497
501
  createRouteInvitation: (issuerId, serviceId) => {
498
502
  if (!routeInvitations)
@@ -567,6 +571,20 @@ export function startServer(options = {}) {
567
571
  issuerAllowed: subjectId => entrySubjectAllowed(subjectId),
568
572
  targetAvailable: serviceId => routeAccess.hasConfiguredTarget(serviceId) && relayRouter.hasRoute(serviceId),
569
573
  });
574
+ let localCa;
575
+ if (scheme === 'https' && options.httpsCaPath)
576
+ try {
577
+ localCa = fs.readFileSync(options.httpsCaPath);
578
+ }
579
+ catch { /* System trust may still validate the local certificate. */ }
580
+ const localHostname = ['0.0.0.0', '::'].includes(host) ? 'localhost' : host;
581
+ const localAuthority = localHostname.includes(':') && !localHostname.startsWith('[') ? `[${localHostname}]` : localHostname;
582
+ const selfRelay = new DesktopSelfRelay({
583
+ desktopFile: path.join(homedir(), '.termdock', 'desktop.json'), identity: runtime.identity, serviceId: runtime.serviceId,
584
+ localOrigin: `${scheme}://${localAuthority}:${port}`, ...(localCa ? { localCa } : {}),
585
+ });
586
+ selfRelay.start();
587
+ server.once('close', () => selfRelay.close());
570
588
  }).catch(() => console.error('Route invitations unavailable; uninitialized route grants remain denied.'));
571
589
  void federation.catch(() => console.error('Encrypted access initialization failed; business access remains closed.'));
572
590
  server.once('close', () => { void federation.then(runtime => runtime.close()).catch(() => { }); });
@@ -661,7 +679,11 @@ export function startServer(options = {}) {
661
679
  socket.end('HTTP/1.1 403 Forbidden\r\nConnection: close\r\n\r\n');
662
680
  return;
663
681
  }
664
- const principal = routeAccess.authenticate(request.headers.authorization, url.searchParams.get('routeToken'));
682
+ const routeToken = url.searchParams.get('routeToken');
683
+ const selfRelayToken = url.searchParams.get('selfRelayToken');
684
+ const principal = selfRelayToken && !request.headers.authorization && !routeToken
685
+ ? routeAccess.authenticateSelfRelay(selfRelayToken)
686
+ : !selfRelayToken ? routeAccess.authenticate(request.headers.authorization, routeToken) : null;
665
687
  if (!principal) {
666
688
  socket.end('HTTP/1.1 401 Unauthorized\r\nConnection: close\r\n\r\n');
667
689
  return;
@@ -111,6 +111,9 @@ export class RelayRouter {
111
111
  const route = this.routes.get(serviceId);
112
112
  return !this.stopped && !!route && route.expires > Date.now() && route.peer.ws.readyState === 1 && this.canRegister(route.peer, serviceId);
113
113
  }
114
+ activeRouteIds() {
115
+ return [...this.routes.keys()].filter(serviceId => this.hasRoute(serviceId));
116
+ }
114
117
  /** Trusted local configuration only. Clients never supply a target URL or factory. */
115
118
  registerDirect(serviceId, connect) {
116
119
  if (this.stopped || !identifier(serviceId) || typeof connect !== 'function' || this.hasRoute(serviceId))
@@ -9,12 +9,15 @@ export class RouteAccess {
9
9
  now;
10
10
  canRouteSubject;
11
11
  additionalTargets;
12
+ additionalTargetIds;
12
13
  tickets = new Map();
13
- constructor(filePath, now = Date.now, canRouteSubject = () => false, additionalTargets = () => []) {
14
+ selfRelayTickets = new Map();
15
+ constructor(filePath, now = Date.now, canRouteSubject = () => false, additionalTargets = () => [], additionalTargetIds = () => []) {
14
16
  this.filePath = filePath;
15
17
  this.now = now;
16
18
  this.canRouteSubject = canRouteSubject;
17
19
  this.additionalTargets = additionalTargets;
20
+ this.additionalTargetIds = additionalTargetIds;
18
21
  }
19
22
  registry() {
20
23
  const empty = { relays: [], directTargets: [] };
@@ -62,6 +65,34 @@ export class RouteAccess {
62
65
  this.tickets.set(digest(routeToken).toString('hex'), { subjectId, serviceId, expiresAt });
63
66
  return { routeToken, expiresAt };
64
67
  }
68
+ /** A Noise-authenticated service can advertise only its own identity. The
69
+ * short-lived token merely transfers that identity onto the relay socket; it
70
+ * grants neither route use nor target-service access. */
71
+ issueSelfRelayTicket(serviceId) {
72
+ if (!validId(serviceId))
73
+ throw new Error('INVALID_SELF_RELAY_IDENTITY');
74
+ for (const [key, value] of this.selfRelayTickets)
75
+ if (value.expiresAt <= this.now())
76
+ this.selfRelayTickets.delete(key);
77
+ if (this.selfRelayTickets.size >= 1024)
78
+ throw new Error('SELF_RELAY_TICKET_LIMIT');
79
+ const selfRelayToken = randomBytes(32).toString('base64url');
80
+ const expiresAt = this.now() + 30_000;
81
+ this.selfRelayTickets.set(digest(selfRelayToken).toString('hex'), { serviceId, expiresAt });
82
+ return { selfRelayToken, expiresAt };
83
+ }
84
+ /** Single-use, fail-closed transfer from the authenticated Noise channel to
85
+ * the opaque relay transport. */
86
+ authenticateSelfRelay(selfRelayToken) {
87
+ if (!selfRelayToken || selfRelayToken.length > 512)
88
+ return null;
89
+ const key = digest(selfRelayToken).toString('hex');
90
+ const ticket = this.selfRelayTickets.get(key);
91
+ this.selfRelayTickets.delete(key);
92
+ if (!ticket || ticket.expiresAt <= this.now())
93
+ return null;
94
+ return { kind: 'self-relay', serviceId: ticket.serviceId };
95
+ }
65
96
  /** Called once before upgrading. A route ticket is consumed even if expired. */
66
97
  authenticate(authorization, routeToken) {
67
98
  if (authorization && routeToken)
@@ -83,6 +114,8 @@ export class RouteAccess {
83
114
  return { kind: 'client', subjectId: ticket.subjectId, serviceId: ticket.serviceId };
84
115
  }
85
116
  allowRegister(principal, serviceId) {
117
+ if (principal.kind === 'self-relay')
118
+ return principal.serviceId === serviceId;
86
119
  return principal.kind === 'relay' && this.relays().some(r => r.id === principal.id && digest(r.token).toString('hex') === principal.tokenHash && r.targets.includes(serviceId));
87
120
  }
88
121
  allowRoute(principal, serviceId) {
@@ -92,7 +125,8 @@ export class RouteAccess {
92
125
  if (!validId(serviceId))
93
126
  return false;
94
127
  const registry = this.registry();
95
- return registry.relays.some(relay => relay.targets.includes(serviceId)) || registry.directTargets.some(target => target.serviceId === serviceId) || this.additionalTargets().some(target => target.serviceId === serviceId);
128
+ return registry.relays.some(relay => relay.targets.includes(serviceId)) || registry.directTargets.some(target => target.serviceId === serviceId)
129
+ || this.additionalTargets().some(target => target.serviceId === serviceId) || this.additionalTargetIds().includes(serviceId);
96
130
  }
97
131
  addDirectTarget(target) {
98
132
  const url = new URL(target.url);
@@ -139,6 +173,9 @@ export class RouteAccess {
139
173
  url.protocol = 'https:';
140
174
  targets.set(target.serviceId, { serviceId: target.serviceId, url: url.origin, ...(target.label ? { label: target.label } : {}) });
141
175
  }
176
+ for (const serviceId of this.additionalTargetIds())
177
+ if (validId(serviceId) && !targets.has(serviceId))
178
+ targets.set(serviceId, { serviceId });
142
179
  return [...targets.values()];
143
180
  }
144
181
  }
@@ -356,6 +356,11 @@ export async function createFederationRuntime(app, directory, handlers, options
356
356
  });
357
357
  send({ type: 'result', id: packet.id, items });
358
358
  }
359
+ else if (packet.type === 'self-relay-ticket') {
360
+ if (!options.issueSelfRelayTicket)
361
+ throw new Error('SELF_RELAY_UNAVAILABLE');
362
+ send({ type: 'result', id: packet.id, serviceId: subjectId, ...options.issueSelfRelayTicket(subjectId) });
363
+ }
359
364
  else if (packet.type === 'route-invite-create') {
360
365
  check('authorization.manage');
361
366
  if (!options.createRouteInvitation || typeof packet.serviceId !== 'string' || !packet.serviceId || packet.serviceId.length > 512)
@@ -0,0 +1,182 @@
1
+ import WebSocket from 'ws';
2
+ import { desktopDirectTargets } from './desktopTargets.js';
3
+ import { RelayClient } from './relay.js';
4
+ import { readPinnedCertificateAuthority } from './trustedCa.js';
5
+ import { connectCollaborationRpc } from '../agent/collaborationPeerTransport.js';
6
+ function relayEndpoint(origin, selfRelayToken) {
7
+ const url = new URL('/api/federation/relay', origin);
8
+ url.protocol = 'wss:';
9
+ url.searchParams.set('selfRelayToken', selfRelayToken);
10
+ return url.href;
11
+ }
12
+ function secureEndpoint(origin) {
13
+ const url = new URL('/api/federation/secure', origin);
14
+ url.protocol = url.protocol === 'https:' ? 'wss:' : 'ws:';
15
+ return url.href;
16
+ }
17
+ function openSocket(url, ca, maxPayload = 256 * 1024) {
18
+ return new Promise((resolve, reject) => {
19
+ const secure = new URL(url).protocol === 'wss:';
20
+ const socket = new WebSocket(url, {
21
+ ...(secure ? { ...(ca ? { ca } : {}), rejectUnauthorized: true } : {}),
22
+ followRedirects: false,
23
+ handshakeTimeout: 10_000,
24
+ maxPayload,
25
+ });
26
+ const failed = () => { cleanup(); socket.terminate(); reject(new Error('SELF_RELAY_CONNECTION_FAILED')); };
27
+ const opened = () => { cleanup(); socket.on('error', () => socket.terminate()); resolve(socket); };
28
+ const cleanup = () => { socket.off('open', opened); socket.off('error', failed); socket.off('close', failed); };
29
+ socket.once('open', opened);
30
+ socket.once('error', failed);
31
+ socket.once('close', failed);
32
+ });
33
+ }
34
+ function waitForReady(socket) {
35
+ return new Promise((resolve, reject) => {
36
+ const timer = setTimeout(() => fail(), 10_000);
37
+ timer.unref?.();
38
+ const cleanup = () => { clearTimeout(timer); socket.off('message', ready); socket.off('close', fail); };
39
+ const fail = () => { cleanup(); socket.terminate(); reject(new Error('SELF_RELAY_AUTHENTICATION_FAILED')); };
40
+ const ready = (raw, binary) => {
41
+ try {
42
+ const frame = binary ? null : JSON.parse(raw.toString());
43
+ if (frame?.type !== 'ready') {
44
+ fail();
45
+ return;
46
+ }
47
+ cleanup();
48
+ resolve();
49
+ }
50
+ catch {
51
+ fail();
52
+ }
53
+ };
54
+ socket.once('message', ready);
55
+ socket.once('close', fail);
56
+ });
57
+ }
58
+ /**
59
+ * A local Termdock service may publish only its own stable identity to other
60
+ * services pinned by the same Desktop installation. Desktop supplies addresses
61
+ * and CA pins only; the service proves itself with its own Noise identity and
62
+ * no browser/device authorization is copied into this process.
63
+ */
64
+ export class DesktopSelfRelay {
65
+ options;
66
+ states = new Map();
67
+ timer;
68
+ stopped = false;
69
+ constructor(options) {
70
+ this.options = options;
71
+ }
72
+ start() {
73
+ if (this.timer || this.stopped)
74
+ return;
75
+ this.refresh();
76
+ this.timer = setInterval(() => this.refresh(), 2_000);
77
+ this.timer.unref?.();
78
+ }
79
+ close() {
80
+ if (this.stopped)
81
+ return;
82
+ this.stopped = true;
83
+ clearInterval(this.timer);
84
+ this.timer = undefined;
85
+ for (const state of this.states.values())
86
+ this.stopState(state);
87
+ this.states.clear();
88
+ }
89
+ refresh() {
90
+ if (this.stopped)
91
+ return;
92
+ const desired = new Map(desktopDirectTargets(this.options.desktopFile, this.options.serviceId)
93
+ .map(target => [target.serviceId, target]));
94
+ for (const [serviceId, state] of this.states) {
95
+ const target = desired.get(serviceId);
96
+ const signature = target && JSON.stringify([target.url, target.caFingerprint256]);
97
+ if (!target || signature !== state.signature) {
98
+ this.stopState(state);
99
+ this.states.delete(serviceId);
100
+ }
101
+ }
102
+ for (const [serviceId, target] of desired)
103
+ if (!this.states.has(serviceId)) {
104
+ const state = { signature: JSON.stringify([target.url, target.caFingerprint256]), stopped: false };
105
+ this.states.set(serviceId, state);
106
+ void this.run(state, target);
107
+ }
108
+ }
109
+ stopState(state) {
110
+ if (state.stopped)
111
+ return;
112
+ state.stopped = true;
113
+ state.wake?.();
114
+ state.wake = undefined;
115
+ state.client?.close();
116
+ state.client = undefined;
117
+ state.upstream?.terminate();
118
+ state.upstream = undefined;
119
+ }
120
+ async run(state, target) {
121
+ let delay = 1_000;
122
+ while (!this.stopped && !state.stopped) {
123
+ try {
124
+ await this.connect(state, target);
125
+ delay = 1_000;
126
+ }
127
+ catch { /* Offline and older entries remain dormant and retry with backoff. */ }
128
+ if (this.stopped || state.stopped)
129
+ break;
130
+ await new Promise(resolve => {
131
+ const timer = setTimeout(() => { state.wake = undefined; resolve(); }, delay);
132
+ timer.unref?.();
133
+ state.wake = () => { clearTimeout(timer); state.wake = undefined; resolve(); };
134
+ });
135
+ delay = Math.min(delay * 2, 30_000);
136
+ }
137
+ }
138
+ async connect(state, target) {
139
+ const peer = { serviceId: target.serviceId, origin: target.url, ...(target.caFingerprint256 ? { caFingerprint256: target.caFingerprint256 } : {}) };
140
+ const rpc = await connectCollaborationRpc(this.options.identity, peer);
141
+ let selfRelayToken;
142
+ try {
143
+ const result = await rpc.request({ type: 'self-relay-ticket' });
144
+ if (result.serviceId !== this.options.serviceId || typeof result.selfRelayToken !== 'string'
145
+ || !/^[A-Za-z0-9_-]{43}$/.test(result.selfRelayToken))
146
+ throw new Error('INVALID_SELF_RELAY_TICKET');
147
+ selfRelayToken = result.selfRelayToken;
148
+ }
149
+ finally {
150
+ rpc.close();
151
+ }
152
+ if (this.stopped || state.stopped)
153
+ return;
154
+ const ca = target.caFingerprint256 ? await readPinnedCertificateAuthority(target.url, target.caFingerprint256) : undefined;
155
+ const upstream = await openSocket(relayEndpoint(target.url, selfRelayToken), ca);
156
+ state.upstream = upstream;
157
+ try {
158
+ if (this.stopped || state.stopped)
159
+ return;
160
+ await waitForReady(upstream);
161
+ if (this.stopped || state.stopped)
162
+ return;
163
+ const client = new RelayClient(upstream, { targets: new Map([[this.options.serviceId,
164
+ () => openSocket(secureEndpoint(this.options.localOrigin), this.options.localCa, 1024 * 1024)]]) });
165
+ state.client = client;
166
+ await new Promise(resolve => {
167
+ if (upstream.readyState !== WebSocket.OPEN)
168
+ resolve();
169
+ else
170
+ upstream.once('close', () => resolve());
171
+ });
172
+ }
173
+ finally {
174
+ state.client?.close();
175
+ state.client = undefined;
176
+ if (upstream.readyState !== WebSocket.CLOSED)
177
+ upstream.terminate();
178
+ if (state.upstream === upstream)
179
+ state.upstream = undefined;
180
+ }
181
+ }
182
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "termdock",
3
- "version": "1.4.240",
3
+ "version": "1.4.242",
4
4
  "description": "A complete web-based terminal application with modern UI",
5
5
  "type": "module",
6
6
  "main": ".desktop-dist/main.js",
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "packageName": "termdock",
4
- "version": "1.4.240",
4
+ "version": "1.4.242",
5
5
  "runtimeProtocolVersion": 1,
6
6
  "minimumDesktopVersion": "1.4.46",
7
7
  "nodeMajor": 22,
8
8
  "dependencyHash": "sha256-K4KyYJuVoQDpZsBM8ZX1Rw3MddOxAzVdp/cPm0iGZz0=",
9
- "serverBundleHash": "sha256-OjLwoxfVNp7VlqCwrjCUGgjj0Yb3zlTm1sdlQGCGYIs=",
10
- "clientBundleHash": "sha256-1wPbozETRlatzFMaBkX5wcha5zbSwUdAw4I0XckzdLk=",
9
+ "serverBundleHash": "sha256-pd6lxkGXO9l4hUWug+Q8/kxaLYDXfSgODkoynCdwgBI=",
10
+ "clientBundleHash": "sha256-v2rqdMlmZKYLB5hGGTlyCG7qH299aT0k0G7gFdoGCCw=",
11
11
  "entrypoint": "dist/server/cli.js",
12
12
  "clientEntrypoint": "dist/client/index.html"
13
13
  }