termdock 1.4.356 → 1.4.358

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 (490) hide show
  1. package/README.md +22 -4
  2. package/dist/client/assets/AndroidMirrorView-COoPljXi.js +3 -0
  3. package/dist/client/assets/AndroidMirrorView-COoPljXi.js.br +0 -0
  4. package/dist/client/assets/AndroidMirrorView-COoPljXi.js.gz +0 -0
  5. package/dist/client/assets/App-7BA7Jt-V.js +178 -0
  6. package/dist/client/assets/App-7BA7Jt-V.js.br +0 -0
  7. package/dist/client/assets/App-7BA7Jt-V.js.gz +0 -0
  8. package/dist/client/assets/ArchitecturePanel-B51eVL3I.js +9 -0
  9. package/dist/client/assets/ArchitecturePanel-B51eVL3I.js.br +0 -0
  10. package/dist/client/assets/ArchitecturePanel-B51eVL3I.js.gz +0 -0
  11. package/dist/client/assets/{ChangeWalkthroughPanel-DO_zJfZr.js → ChangeWalkthroughPanel-ZGMybE0m.js} +2 -2
  12. package/dist/client/assets/ChangeWalkthroughPanel-ZGMybE0m.js.br +0 -0
  13. package/dist/client/assets/ChangeWalkthroughPanel-ZGMybE0m.js.gz +0 -0
  14. package/dist/client/assets/{ChatRichContent-Cu1E1cJ8.js → ChatRichContent-KkN7aIGv.js} +29 -29
  15. package/dist/client/assets/ChatRichContent-KkN7aIGv.js.br +0 -0
  16. package/dist/client/assets/ChatRichContent-KkN7aIGv.js.gz +0 -0
  17. package/dist/client/assets/CollaborationMainWorkspace-BVeBgGMT.js +1 -0
  18. package/dist/client/assets/CollaborationMainWorkspace-BVeBgGMT.js.br +0 -0
  19. package/dist/client/assets/CollaborationMainWorkspace-BVeBgGMT.js.gz +0 -0
  20. package/dist/client/assets/CollaborationTaskContent-C3Od6xQy.js +1 -0
  21. package/dist/client/assets/ComputerControlView-CnaeZBuh.js +6 -0
  22. package/dist/client/assets/ComputerControlView-CnaeZBuh.js.br +0 -0
  23. package/dist/client/assets/ComputerControlView-CnaeZBuh.js.gz +0 -0
  24. package/dist/client/assets/{DagPlayground-CPYwfryM.js → DagPlayground-E7wKGgTF.js} +1 -1
  25. package/dist/client/assets/DagPlayground-E7wKGgTF.js.br +0 -0
  26. package/dist/client/assets/DagPlayground-E7wKGgTF.js.gz +0 -0
  27. package/dist/client/assets/{DiffLab-ptw96Q_4.js → DiffLab-BMXY4mRl.js} +1 -1
  28. package/dist/client/assets/DiffLab-BMXY4mRl.js.br +0 -0
  29. package/dist/client/assets/DiffLab-BMXY4mRl.js.gz +0 -0
  30. package/dist/client/assets/DiffReview-DHi_V-SX.js +1 -0
  31. package/dist/client/assets/DiffReview-DHi_V-SX.js.br +0 -0
  32. package/dist/client/assets/DiffReview-DHi_V-SX.js.gz +0 -0
  33. package/dist/client/assets/{DiffReviewLab-eEi3y-0G.js → DiffReviewLab-nhoosNZM.js} +1 -1
  34. package/dist/client/assets/DiffReviewLab-nhoosNZM.js.br +0 -0
  35. package/dist/client/assets/DiffReviewLab-nhoosNZM.js.gz +0 -0
  36. package/dist/client/assets/{DiffViewer-DqcQxp4Q.js → DiffViewer-CyDc8WOB.js} +1 -1
  37. package/dist/client/assets/DiffViewer-CyDc8WOB.js.br +0 -0
  38. package/dist/client/assets/DiffViewer-CyDc8WOB.js.gz +0 -0
  39. package/dist/client/assets/{GitLoadingSkeleton-DYrDIDF1.js → GitLoadingSkeleton-RRbTeMuA.js} +1 -1
  40. package/dist/client/assets/GitLoadingSkeleton-RRbTeMuA.js.br +0 -0
  41. package/dist/client/assets/GitLoadingSkeleton-RRbTeMuA.js.gz +0 -0
  42. package/dist/client/assets/Markdown-DKQhs57e.css +1 -0
  43. package/dist/client/assets/Markdown-DKQhs57e.css.br +0 -0
  44. package/dist/client/assets/Markdown-DKQhs57e.css.gz +0 -0
  45. package/dist/client/assets/Markdown-Ip0FYCJ1.js +23 -0
  46. package/dist/client/assets/Markdown-Ip0FYCJ1.js.br +0 -0
  47. package/dist/client/assets/Markdown-Ip0FYCJ1.js.gz +0 -0
  48. package/dist/client/assets/{ModelPreview-DjtHLlqP.js → ModelPreview-DuwBl4st.js} +3 -3
  49. package/dist/client/assets/ModelPreview-DuwBl4st.js.br +0 -0
  50. package/dist/client/assets/ModelPreview-DuwBl4st.js.gz +0 -0
  51. package/dist/client/assets/RecordingSaveDialog-Czkjuaeu.js +1 -0
  52. package/dist/client/assets/RecordingSaveDialog-Czkjuaeu.js.br +0 -0
  53. package/dist/client/assets/RecordingSaveDialog-Czkjuaeu.js.gz +0 -0
  54. package/dist/client/assets/RightSidebar-BvYh2_n2.js +1662 -0
  55. package/dist/client/assets/RightSidebar-BvYh2_n2.js.br +0 -0
  56. package/dist/client/assets/RightSidebar-BvYh2_n2.js.gz +0 -0
  57. package/dist/client/assets/SessionChatView-hFOVLdHC.js +13 -0
  58. package/dist/client/assets/SessionChatView-hFOVLdHC.js.br +0 -0
  59. package/dist/client/assets/SessionChatView-hFOVLdHC.js.gz +0 -0
  60. package/dist/client/assets/SessionResourceSidebar-D-VXNdmE.js +2 -0
  61. package/dist/client/assets/SessionResourceSidebar-D-VXNdmE.js.br +0 -0
  62. package/dist/client/assets/SessionResourceSidebar-D-VXNdmE.js.gz +0 -0
  63. package/dist/client/assets/TodoWorkspace-CCL-wZTu.js +1 -0
  64. package/dist/client/assets/TodoWorkspace-CCL-wZTu.js.br +0 -0
  65. package/dist/client/assets/TodoWorkspace-CCL-wZTu.js.gz +0 -0
  66. package/dist/client/assets/{abnfDiagram-VCTEODGH-Cvf_KWZ0.js → abnfDiagram-VCTEODGH-CdEUK_s_.js} +1 -1
  67. package/dist/client/assets/abnfDiagram-VCTEODGH-CdEUK_s_.js.br +0 -0
  68. package/dist/client/assets/abnfDiagram-VCTEODGH-CdEUK_s_.js.gz +0 -0
  69. package/dist/client/assets/app-DZ6mCJiW.js +37 -0
  70. package/dist/client/assets/app-DZ6mCJiW.js.br +0 -0
  71. package/dist/client/assets/app-DZ6mCJiW.js.gz +0 -0
  72. package/dist/client/assets/{arc-UvdowQOf.js → arc-Dmbeqzc-.js} +1 -1
  73. package/dist/client/assets/arc-Dmbeqzc-.js.br +0 -0
  74. package/dist/client/assets/arc-Dmbeqzc-.js.gz +0 -0
  75. package/dist/client/assets/{architectureDiagram-5GKGNRK7-DotsbCCA.js → architectureDiagram-5GKGNRK7-CZcdXQrP.js} +1 -1
  76. package/dist/client/assets/architectureDiagram-5GKGNRK7-CZcdXQrP.js.br +0 -0
  77. package/dist/client/assets/{architectureDiagram-5GKGNRK7-DotsbCCA.js.gz → architectureDiagram-5GKGNRK7-CZcdXQrP.js.gz} +0 -0
  78. package/dist/client/assets/{arrow-down-FGzRy9D-.js → arrow-down-Ty3zwcgl.js} +1 -1
  79. package/dist/client/assets/{blockDiagram-I7D4REHJ-CoOfSG4k.js → blockDiagram-I7D4REHJ-D9jFhXcb.js} +1 -1
  80. package/dist/client/assets/blockDiagram-I7D4REHJ-D9jFhXcb.js.br +0 -0
  81. package/dist/client/assets/blockDiagram-I7D4REHJ-D9jFhXcb.js.gz +0 -0
  82. package/dist/client/assets/{c4Diagram-7LVT6UL2-BAfjgs8B.js → c4Diagram-7LVT6UL2-c9o0rNTP.js} +1 -1
  83. package/dist/client/assets/c4Diagram-7LVT6UL2-c9o0rNTP.js.br +0 -0
  84. package/dist/client/assets/c4Diagram-7LVT6UL2-c9o0rNTP.js.gz +0 -0
  85. package/dist/client/assets/channel-BzD84hIE.js +1 -0
  86. package/dist/client/assets/{chevron-left-xqARwD-7.js → chevron-left-CVjGQZf0.js} +1 -1
  87. package/dist/client/assets/{chunk-2Q5K7J3B-DiiQ7BvG.js → chunk-2Q5K7J3B-Bl_5wWZ4.js} +1 -1
  88. package/dist/client/assets/{chunk-5VM5RSS4-CczSK8wW.js → chunk-5VM5RSS4-D9XQn27m.js} +1 -1
  89. package/dist/client/assets/{chunk-F27PBJKO-BI3Di4Ve.js → chunk-F27PBJKO-DWyskKWD.js} +1 -1
  90. package/dist/client/assets/chunk-F27PBJKO-DWyskKWD.js.br +0 -0
  91. package/dist/client/assets/chunk-F27PBJKO-DWyskKWD.js.gz +0 -0
  92. package/dist/client/assets/{chunk-IMKFNOWR-Cvvs1wmn.js → chunk-IMKFNOWR-DrWbExPc.js} +1 -1
  93. package/dist/client/assets/chunk-IMKFNOWR-DrWbExPc.js.br +0 -0
  94. package/dist/client/assets/chunk-IMKFNOWR-DrWbExPc.js.gz +0 -0
  95. package/dist/client/assets/{chunk-JWPE2WC7-lrJRD9WA.js → chunk-JWPE2WC7-B7O1zrh6.js} +1 -1
  96. package/dist/client/assets/{chunk-POPQ4Y6H-CnPC9D8B.js → chunk-POPQ4Y6H-D7TlizKK.js} +1 -1
  97. package/dist/client/assets/{chunk-SVP7TREG-BZfMhm64.js → chunk-SVP7TREG-DNK10F6v.js} +1 -1
  98. package/dist/client/assets/chunk-SVP7TREG-DNK10F6v.js.br +0 -0
  99. package/dist/client/assets/chunk-SVP7TREG-DNK10F6v.js.gz +0 -0
  100. package/dist/client/assets/{chunk-TICWLB2K-DmkEaRK3.js → chunk-TICWLB2K-zVD9YIYY.js} +1 -1
  101. package/dist/client/assets/chunk-TICWLB2K-zVD9YIYY.js.br +0 -0
  102. package/dist/client/assets/chunk-TICWLB2K-zVD9YIYY.js.gz +0 -0
  103. package/dist/client/assets/{chunk-XXDRQBXY-BP9Lccpe.js → chunk-XXDRQBXY-bRScHSGz.js} +1 -1
  104. package/dist/client/assets/{circle-DGZOpG8V.js → circle-BIJQEbCa.js} +1 -1
  105. package/dist/client/assets/classDiagram-ZZMXUADV-DNwfONVW.js +1 -0
  106. package/dist/client/assets/classDiagram-v2-VYDZK3BY-DNwfONVW.js +1 -0
  107. package/dist/client/assets/{clipboard-rLx5CzbY.js → clipboard-DV8t7tww.js} +1 -1
  108. package/dist/client/assets/clipboardText-C4QKbGHg.css +1 -0
  109. package/dist/client/assets/clipboardText-C4QKbGHg.css.br +0 -0
  110. package/dist/client/assets/clipboardText-C4QKbGHg.css.gz +0 -0
  111. package/dist/client/assets/clipboardText-DoB9NjH8.js +1 -0
  112. package/dist/client/assets/clipboardText-DoB9NjH8.js.br +0 -0
  113. package/dist/client/assets/clipboardText-DoB9NjH8.js.gz +0 -0
  114. package/dist/client/assets/{cose-bilkent-JH36ORCC-0xPYMc2z.js → cose-bilkent-JH36ORCC-Bf6IObhf.js} +1 -1
  115. package/dist/client/assets/cose-bilkent-JH36ORCC-Bf6IObhf.js.br +0 -0
  116. package/dist/client/assets/cose-bilkent-JH36ORCC-Bf6IObhf.js.gz +0 -0
  117. package/dist/client/assets/{cynefin-OW5HDTMX-BQ7-lCHm.js → cynefin-OW5HDTMX-DAtjde93.js} +1 -1
  118. package/dist/client/assets/cynefin-OW5HDTMX-DAtjde93.js.br +0 -0
  119. package/dist/client/assets/cynefin-OW5HDTMX-DAtjde93.js.gz +0 -0
  120. package/dist/client/assets/{cynefinDiagram-5FMLGOSQ-CazHuSj1.js → cynefinDiagram-5FMLGOSQ-Bwoin99V.js} +1 -1
  121. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-Bwoin99V.js.br +0 -0
  122. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-Bwoin99V.js.gz +0 -0
  123. package/dist/client/assets/{dagre-GXQ25YYZ-CJNgsyHQ.js → dagre-GXQ25YYZ-dxPzSob9.js} +1 -1
  124. package/dist/client/assets/dagre-GXQ25YYZ-dxPzSob9.js.br +0 -0
  125. package/dist/client/assets/dagre-GXQ25YYZ-dxPzSob9.js.gz +0 -0
  126. package/dist/client/assets/{diagram-S7CK7UJ4-D4xXIj1P.js → diagram-S7CK7UJ4-BXdiLivz.js} +1 -1
  127. package/dist/client/assets/diagram-S7CK7UJ4-BXdiLivz.js.br +0 -0
  128. package/dist/client/assets/diagram-S7CK7UJ4-BXdiLivz.js.gz +0 -0
  129. package/dist/client/assets/{diagram-UQ7AKVKN-BWhpL-35.js → diagram-UQ7AKVKN-DXveP3fg.js} +1 -1
  130. package/dist/client/assets/diagram-UQ7AKVKN-DXveP3fg.js.br +0 -0
  131. package/dist/client/assets/diagram-UQ7AKVKN-DXveP3fg.js.gz +0 -0
  132. package/dist/client/assets/{diagram-VSXAHHWV-DG9A7EgJ.js → diagram-VSXAHHWV-BAZtoQue.js} +1 -1
  133. package/dist/client/assets/diagram-VSXAHHWV-BAZtoQue.js.br +0 -0
  134. package/dist/client/assets/diagram-VSXAHHWV-BAZtoQue.js.gz +0 -0
  135. package/dist/client/assets/{diagram-VX7I27RA-L5PSvynM.js → diagram-VX7I27RA-Bhc7cKpk.js} +1 -1
  136. package/dist/client/assets/diagram-VX7I27RA-Bhc7cKpk.js.br +0 -0
  137. package/dist/client/assets/diagram-VX7I27RA-Bhc7cKpk.js.gz +0 -0
  138. package/dist/client/assets/{diagram-Z3DM3KII-moBH7ruR.js → diagram-Z3DM3KII-DWIa_F-y.js} +1 -1
  139. package/dist/client/assets/diagram-Z3DM3KII-DWIa_F-y.js.br +0 -0
  140. package/dist/client/assets/diagram-Z3DM3KII-DWIa_F-y.js.gz +0 -0
  141. package/dist/client/assets/{ebnfDiagram-PWID7BFC-DEiGgcRP.js → ebnfDiagram-PWID7BFC-B3LDILSm.js} +1 -1
  142. package/dist/client/assets/ebnfDiagram-PWID7BFC-B3LDILSm.js.br +0 -0
  143. package/dist/client/assets/ebnfDiagram-PWID7BFC-B3LDILSm.js.gz +0 -0
  144. package/dist/client/assets/{erDiagram-RLTQ6QDP-BboIleYi.js → erDiagram-RLTQ6QDP-Cfu95bMX.js} +1 -1
  145. package/dist/client/assets/erDiagram-RLTQ6QDP-Cfu95bMX.js.br +0 -0
  146. package/dist/client/assets/erDiagram-RLTQ6QDP-Cfu95bMX.js.gz +0 -0
  147. package/dist/client/assets/{external-link-AZ3wjUg5.js → external-link-DodqgrCc.js} +1 -1
  148. package/dist/client/assets/{flowDiagram-HODETNUW-COxz7Rda.js → flowDiagram-HODETNUW-DVtO6aQE.js} +1 -1
  149. package/dist/client/assets/flowDiagram-HODETNUW-DVtO6aQE.js.br +0 -0
  150. package/dist/client/assets/flowDiagram-HODETNUW-DVtO6aQE.js.gz +0 -0
  151. package/dist/client/assets/{ganttDiagram-EL5Y4UJY-_XdRvgyZ.js → ganttDiagram-EL5Y4UJY-Bh1TvYzb.js} +1 -1
  152. package/dist/client/assets/ganttDiagram-EL5Y4UJY-Bh1TvYzb.js.br +0 -0
  153. package/dist/client/assets/ganttDiagram-EL5Y4UJY-Bh1TvYzb.js.gz +0 -0
  154. package/dist/client/assets/{git-compare-90v75Jal.js → git-compare-KkbucDhN.js} +1 -1
  155. package/dist/client/assets/{gitGraphDiagram-WWUBYQGX-CBb9xBNW.js → gitGraphDiagram-WWUBYQGX-BKbRxPsF.js} +1 -1
  156. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-BKbRxPsF.js.br +0 -0
  157. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-BKbRxPsF.js.gz +0 -0
  158. package/dist/client/assets/index-DEAMSl55.css +1 -0
  159. package/dist/client/assets/index-DEAMSl55.css.br +0 -0
  160. package/dist/client/assets/index-DEAMSl55.css.gz +0 -0
  161. package/dist/client/assets/{infoDiagram-27XIBGKW-DjLdeNZi.js → infoDiagram-27XIBGKW-CLhO8B16.js} +1 -1
  162. package/dist/client/assets/{ishikawaDiagram-5VMMS53U-Bcr-lhIE.js → ishikawaDiagram-5VMMS53U-BwchGTP9.js} +1 -1
  163. package/dist/client/assets/ishikawaDiagram-5VMMS53U-BwchGTP9.js.br +0 -0
  164. package/dist/client/assets/ishikawaDiagram-5VMMS53U-BwchGTP9.js.gz +0 -0
  165. package/dist/client/assets/{journeyDiagram-3NMN7TZE-3vK6s9Pq.js → journeyDiagram-3NMN7TZE-eWBpuyMm.js} +1 -1
  166. package/dist/client/assets/journeyDiagram-3NMN7TZE-eWBpuyMm.js.br +0 -0
  167. package/dist/client/assets/journeyDiagram-3NMN7TZE-eWBpuyMm.js.gz +0 -0
  168. package/dist/client/assets/{kanban-definition-UXKFOSKX-DqDYDca0.js → kanban-definition-UXKFOSKX-Sik-RHYc.js} +1 -1
  169. package/dist/client/assets/kanban-definition-UXKFOSKX-Sik-RHYc.js.br +0 -0
  170. package/dist/client/assets/kanban-definition-UXKFOSKX-Sik-RHYc.js.gz +0 -0
  171. package/dist/client/assets/{layout-C7_WwzCP.js → layout-BJX2CDWF.js} +1 -1
  172. package/dist/client/assets/layout-BJX2CDWF.js.br +0 -0
  173. package/dist/client/assets/layout-BJX2CDWF.js.gz +0 -0
  174. package/dist/client/assets/{linear-BQCRhl6P.js → linear-0FKHr918.js} +1 -1
  175. package/dist/client/assets/{linear-BQCRhl6P.js.br → linear-0FKHr918.js.br} +0 -0
  176. package/dist/client/assets/linear-0FKHr918.js.gz +0 -0
  177. package/dist/client/assets/{link-Cq14tNBm.js → link-DWUQqMDL.js} +3 -3
  178. package/dist/client/assets/link-DWUQqMDL.js.br +0 -0
  179. package/dist/client/assets/link-DWUQqMDL.js.gz +0 -0
  180. package/dist/client/assets/{list-tree-C281zrdg.js → list-tree-DxdLnXUB.js} +1 -1
  181. package/dist/client/assets/{maximize-2-CovPxWdw.js → maximize-2-Clx4ktqB.js} +1 -1
  182. package/dist/client/assets/{mermaid.core-DGsccxt-.js → mermaid.core-DWoaNsig.js} +5 -5
  183. package/dist/client/assets/mermaid.core-DWoaNsig.js.br +0 -0
  184. package/dist/client/assets/mermaid.core-DWoaNsig.js.gz +0 -0
  185. package/dist/client/assets/{mindmap-definition-YA3MSWOX-l0eF1PQE.js → mindmap-definition-YA3MSWOX-kFqW8-1C.js} +1 -1
  186. package/dist/client/assets/mindmap-definition-YA3MSWOX-kFqW8-1C.js.br +0 -0
  187. package/dist/client/assets/mindmap-definition-YA3MSWOX-kFqW8-1C.js.gz +0 -0
  188. package/dist/client/assets/{passwordBootstrap-B5VzheZz.js → passwordBootstrap-ZDVK8UPE.js} +1 -1
  189. package/dist/client/assets/passwordBootstrap-ZDVK8UPE.js.br +0 -0
  190. package/dist/client/assets/passwordBootstrap-ZDVK8UPE.js.gz +0 -0
  191. package/dist/client/assets/{pegDiagram-XKGWAZYB-fRrxGIDM.js → pegDiagram-XKGWAZYB-CndGmUtZ.js} +1 -1
  192. package/dist/client/assets/pegDiagram-XKGWAZYB-CndGmUtZ.js.br +0 -0
  193. package/dist/client/assets/pegDiagram-XKGWAZYB-CndGmUtZ.js.gz +0 -0
  194. package/dist/client/assets/{pieDiagram-E7YTZNPT-B-EBa3qN.js → pieDiagram-E7YTZNPT-Q550203T.js} +1 -1
  195. package/dist/client/assets/pieDiagram-E7YTZNPT-Q550203T.js.br +0 -0
  196. package/dist/client/assets/pieDiagram-E7YTZNPT-Q550203T.js.gz +0 -0
  197. package/dist/client/assets/{quadrantDiagram-AXDQQJYC-Dj4e6f4h.js → quadrantDiagram-AXDQQJYC-BrjlUGzZ.js} +1 -1
  198. package/dist/client/assets/quadrantDiagram-AXDQQJYC-BrjlUGzZ.js.br +0 -0
  199. package/dist/client/assets/quadrantDiagram-AXDQQJYC-BrjlUGzZ.js.gz +0 -0
  200. package/dist/client/assets/{quote-COQfrXhi.js → quote-B9G-yF_k.js} +1 -1
  201. package/dist/client/assets/{railroadDiagram-O6MQD6OU-CEMppxTC.js → railroadDiagram-O6MQD6OU-CSqOaX_w.js} +1 -1
  202. package/dist/client/assets/railroadDiagram-O6MQD6OU-CSqOaX_w.js.br +0 -0
  203. package/dist/client/assets/railroadDiagram-O6MQD6OU-CSqOaX_w.js.gz +0 -0
  204. package/dist/client/assets/rdpSession-DdqSmi-Z.js +1 -0
  205. package/dist/client/assets/rdpSession-DdqSmi-Z.js.br +0 -0
  206. package/dist/client/assets/rdpSession-DdqSmi-Z.js.gz +0 -0
  207. package/dist/client/assets/referenceSelection-0uCpJjt2.js +4 -0
  208. package/dist/client/assets/referenceSelection-0uCpJjt2.js.br +0 -0
  209. package/dist/client/assets/referenceSelection-0uCpJjt2.js.gz +0 -0
  210. package/dist/client/assets/{requirementDiagram-BXWQKSXE-Dri1k4_x.js → requirementDiagram-BXWQKSXE-NGPth3Pf.js} +1 -1
  211. package/dist/client/assets/requirementDiagram-BXWQKSXE-NGPth3Pf.js.br +0 -0
  212. package/dist/client/assets/requirementDiagram-BXWQKSXE-NGPth3Pf.js.gz +0 -0
  213. package/dist/client/assets/{sankeyDiagram-P5KCCOFB-CMsL_tYL.js → sankeyDiagram-P5KCCOFB-CbxpJ6iI.js} +1 -1
  214. package/dist/client/assets/sankeyDiagram-P5KCCOFB-CbxpJ6iI.js.br +0 -0
  215. package/dist/client/assets/sankeyDiagram-P5KCCOFB-CbxpJ6iI.js.gz +0 -0
  216. package/dist/client/assets/{search-Dg6HWygj.js → search-DAQ_AOVP.js} +1 -1
  217. package/dist/client/assets/{sequenceDiagram-WJ2MYXX4-4_4hZtOd.js → sequenceDiagram-WJ2MYXX4-D3gJOK25.js} +1 -1
  218. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-D3gJOK25.js.br +0 -0
  219. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-D3gJOK25.js.gz +0 -0
  220. package/dist/client/assets/{sizeCapture-INFHLROL-3QA6qj2j.js → sizeCapture-INFHLROL-D4D1KI0n.js} +1 -1
  221. package/dist/client/assets/sizeCapture-INFHLROL-D4D1KI0n.js.br +0 -0
  222. package/dist/client/assets/sizeCapture-INFHLROL-D4D1KI0n.js.gz +0 -0
  223. package/dist/client/assets/{stateDiagram-D77RDMKH-90IFPhD9.js → stateDiagram-D77RDMKH-BjtgjBg5.js} +1 -1
  224. package/dist/client/assets/stateDiagram-D77RDMKH-BjtgjBg5.js.br +0 -0
  225. package/dist/client/assets/stateDiagram-D77RDMKH-BjtgjBg5.js.gz +0 -0
  226. package/dist/client/assets/stateDiagram-v2-MP3YSRHH-BkFsvhZ0.js +1 -0
  227. package/dist/client/assets/{sun-BAMMjiA8.js → sun-DvwMJkda.js} +1 -1
  228. package/dist/client/assets/{swimlanes-42K2YHIH-BuHieVWC.js → swimlanes-42K2YHIH-C17jwdFo.js} +1 -1
  229. package/dist/client/assets/swimlanes-42K2YHIH-C17jwdFo.js.br +0 -0
  230. package/dist/client/assets/swimlanes-42K2YHIH-C17jwdFo.js.gz +0 -0
  231. package/dist/client/assets/swimlanesDiagram-VR7AAH4N-Bcw2hbFj.js +8 -0
  232. package/dist/client/assets/swiper-BaumVgFd.js +1 -0
  233. package/dist/client/assets/swiper-BaumVgFd.js.br +0 -0
  234. package/dist/client/assets/swiper-BaumVgFd.js.gz +0 -0
  235. package/dist/client/assets/{terminal-Dea8wJF3.js → terminal-DaiFCKy_.js} +7 -7
  236. package/dist/client/assets/terminal-DaiFCKy_.js.br +0 -0
  237. package/dist/client/assets/terminal-DaiFCKy_.js.gz +0 -0
  238. package/dist/client/assets/{timeline-definition-24CTP7MA-C7FpaNwf.js → timeline-definition-24CTP7MA-CtdHmPoC.js} +1 -1
  239. package/dist/client/assets/timeline-definition-24CTP7MA-CtdHmPoC.js.br +0 -0
  240. package/dist/client/assets/timeline-definition-24CTP7MA-CtdHmPoC.js.gz +0 -0
  241. package/dist/client/assets/triangle-alert-D-tt7pA2.js +1 -0
  242. package/dist/client/assets/{unplug-DN2SNXUL.js → unplug-BQxOculv.js} +1 -1
  243. package/dist/client/assets/use-gesture-react.esm-CM42s15B.js +1 -0
  244. package/dist/client/assets/use-gesture-react.esm-CM42s15B.js.br +0 -0
  245. package/dist/client/assets/use-gesture-react.esm-CM42s15B.js.gz +0 -0
  246. package/dist/client/assets/{vennDiagram-4TSXK5OY-CxoHHVcs.js → vennDiagram-4TSXK5OY-DhwCFaVe.js} +1 -1
  247. package/dist/client/assets/vennDiagram-4TSXK5OY-DhwCFaVe.js.br +0 -0
  248. package/dist/client/assets/vennDiagram-4TSXK5OY-DhwCFaVe.js.gz +0 -0
  249. package/dist/client/assets/{videoCompression-rr2lu3uy.js → videoCompression-BFhMaMl7.js} +1 -1
  250. package/dist/client/assets/videoCompression-BFhMaMl7.js.br +0 -0
  251. package/dist/client/assets/videoCompression-BFhMaMl7.js.gz +0 -0
  252. package/dist/client/assets/{wardleyDiagram-VM6X3IG4-B4Hsh-Ad.js → wardleyDiagram-VM6X3IG4-BP4Z-QQ4.js} +1 -1
  253. package/dist/client/assets/wardleyDiagram-VM6X3IG4-BP4Z-QQ4.js.br +0 -0
  254. package/dist/client/assets/wardleyDiagram-VM6X3IG4-BP4Z-QQ4.js.gz +0 -0
  255. package/dist/client/assets/{xychartDiagram-S5SC5T6Z-CghzsxQv.js → xychartDiagram-S5SC5T6Z-CEPWf1tk.js} +1 -1
  256. package/dist/client/assets/xychartDiagram-S5SC5T6Z-CEPWf1tk.js.br +0 -0
  257. package/dist/client/assets/xychartDiagram-S5SC5T6Z-CEPWf1tk.js.gz +0 -0
  258. package/dist/client/index.html +3 -3
  259. package/dist/client/index.html.br +0 -0
  260. package/dist/client/index.html.gz +0 -0
  261. package/dist/client/sw-encrypted-background.js +1 -1
  262. package/dist/client/sw-encrypted-background.js.br +0 -0
  263. package/dist/client/sw-encrypted-background.js.gz +0 -0
  264. package/dist/client/sw.js +1 -1
  265. package/dist/client/sw.js.br +0 -0
  266. package/dist/client/sw.js.gz +0 -0
  267. package/dist/server/agent/collaborationPeerTransport.js +14 -69
  268. package/dist/server/agent/collaborationStore.js +5 -0
  269. package/dist/server/agent/installers.js +89 -33
  270. package/dist/server/agent/integrationServer.js +31 -2
  271. package/dist/server/agent/pluginPackages.js +51 -22
  272. package/dist/server/agent/sessionChatRoutes.js +45 -7
  273. package/dist/server/agentHook.js +56 -12
  274. package/dist/server/android/adb.js +24 -31
  275. package/dist/server/cli.js +52 -110
  276. package/dist/server/entry.js +17 -23
  277. package/dist/server/federation/cli.js +13 -47
  278. package/dist/server/federation/connectionErrors.js +37 -0
  279. package/dist/server/federation/connectionModel.js +83 -0
  280. package/dist/server/federation/desktopTargets.js +35 -13
  281. package/dist/server/federation/directRoutes.js +28 -36
  282. package/dist/server/federation/directTargetRegistry.js +106 -0
  283. package/dist/server/federation/httpUploadLimit.js +8 -0
  284. package/dist/server/federation/relay.js +13 -6
  285. package/dist/server/federation/relayTransport.js +147 -0
  286. package/dist/server/federation/routeAccess.js +5 -3
  287. package/dist/server/federation/runtime.js +4 -2
  288. package/dist/server/federation/selfRelay.js +10 -59
  289. package/dist/server/federation/serviceTransport.js +123 -0
  290. package/dist/server/federation/streamLimits.js +3 -0
  291. package/dist/server/federation/trustedCa.js +61 -0
  292. package/dist/server/routes/android.js +5 -7
  293. package/dist/server/routes/terminal.js +149 -111
  294. package/dist/server/shared/androidDevices.js +64 -0
  295. package/dist/server/shared/programStatus.js +174 -0
  296. package/dist/server/shared/shareResources.js +3 -2
  297. package/dist/server/todos/routes.js +36 -0
  298. package/dist/server/todos/store.js +31 -1
  299. package/dist/server/utils/bootCheck.js +41 -271
  300. package/dist/server/utils/localHttpsSetup.js +257 -0
  301. package/dist/server/utils/oscBuffer.js +9 -0
  302. package/dist/server/utils/sessionDisplayName.js +11 -9
  303. package/dist/server/utils/settings.js +6 -3
  304. package/dist/server/utils/tmuxDisplayGeometry.js +54 -0
  305. package/dist/server/utils/tmuxObserverSize.js +26 -0
  306. package/docs/integrations.md +2 -1
  307. package/package.json +6 -1
  308. package/runtime-manifest.json +3 -3
  309. package/scripts/install-utils.cjs +81 -0
  310. package/scripts/postinstall.mjs +19 -106
  311. package/dist/client/assets/AndroidMirrorView-DW9oRr0w.js +0 -3
  312. package/dist/client/assets/AndroidMirrorView-DW9oRr0w.js.br +0 -0
  313. package/dist/client/assets/AndroidMirrorView-DW9oRr0w.js.gz +0 -0
  314. package/dist/client/assets/App-DEZ2i9ZZ.js +0 -178
  315. package/dist/client/assets/App-DEZ2i9ZZ.js.br +0 -0
  316. package/dist/client/assets/App-DEZ2i9ZZ.js.gz +0 -0
  317. package/dist/client/assets/ArchitecturePanel-Bf4b-6An.js +0 -9
  318. package/dist/client/assets/ArchitecturePanel-Bf4b-6An.js.br +0 -0
  319. package/dist/client/assets/ArchitecturePanel-Bf4b-6An.js.gz +0 -0
  320. package/dist/client/assets/ChangeWalkthroughPanel-DO_zJfZr.js.br +0 -0
  321. package/dist/client/assets/ChangeWalkthroughPanel-DO_zJfZr.js.gz +0 -0
  322. package/dist/client/assets/ChatRichContent-Cu1E1cJ8.js.br +0 -0
  323. package/dist/client/assets/ChatRichContent-Cu1E1cJ8.js.gz +0 -0
  324. package/dist/client/assets/CollaborationMainWorkspace-BhmpSEbf.js +0 -1
  325. package/dist/client/assets/CollaborationMainWorkspace-BhmpSEbf.js.br +0 -0
  326. package/dist/client/assets/CollaborationMainWorkspace-BhmpSEbf.js.gz +0 -0
  327. package/dist/client/assets/CollaborationTaskContent-CX0Aqdi2.js +0 -2
  328. package/dist/client/assets/ComputerControlView-DjQLzn10.js +0 -6
  329. package/dist/client/assets/ComputerControlView-DjQLzn10.js.br +0 -0
  330. package/dist/client/assets/ComputerControlView-DjQLzn10.js.gz +0 -0
  331. package/dist/client/assets/DagPlayground-CPYwfryM.js.br +0 -0
  332. package/dist/client/assets/DagPlayground-CPYwfryM.js.gz +0 -0
  333. package/dist/client/assets/DiffLab-ptw96Q_4.js.br +0 -0
  334. package/dist/client/assets/DiffLab-ptw96Q_4.js.gz +0 -0
  335. package/dist/client/assets/DiffReview-12E2zWyL.js +0 -1
  336. package/dist/client/assets/DiffReview-12E2zWyL.js.br +0 -0
  337. package/dist/client/assets/DiffReview-12E2zWyL.js.gz +0 -0
  338. package/dist/client/assets/DiffReviewLab-eEi3y-0G.js.br +0 -0
  339. package/dist/client/assets/DiffReviewLab-eEi3y-0G.js.gz +0 -0
  340. package/dist/client/assets/DiffViewer-DqcQxp4Q.js.br +0 -0
  341. package/dist/client/assets/DiffViewer-DqcQxp4Q.js.gz +0 -0
  342. package/dist/client/assets/GitLoadingSkeleton-DYrDIDF1.js.br +0 -0
  343. package/dist/client/assets/GitLoadingSkeleton-DYrDIDF1.js.gz +0 -0
  344. package/dist/client/assets/MarkdownPreview-CsJGsDRL.js +0 -19
  345. package/dist/client/assets/MarkdownPreview-CsJGsDRL.js.br +0 -0
  346. package/dist/client/assets/MarkdownPreview-CsJGsDRL.js.gz +0 -0
  347. package/dist/client/assets/ModelPreview-DjtHLlqP.js.br +0 -0
  348. package/dist/client/assets/ModelPreview-DjtHLlqP.js.gz +0 -0
  349. package/dist/client/assets/RecordingSaveDialog-DUtwgIME.js +0 -1
  350. package/dist/client/assets/RecordingSaveDialog-DUtwgIME.js.br +0 -0
  351. package/dist/client/assets/RecordingSaveDialog-DUtwgIME.js.gz +0 -0
  352. package/dist/client/assets/RightSidebar-BltjUFwI.js +0 -1662
  353. package/dist/client/assets/RightSidebar-BltjUFwI.js.br +0 -0
  354. package/dist/client/assets/RightSidebar-BltjUFwI.js.gz +0 -0
  355. package/dist/client/assets/SessionChatView-CdKfHRp8.js +0 -13
  356. package/dist/client/assets/SessionChatView-CdKfHRp8.js.br +0 -0
  357. package/dist/client/assets/SessionChatView-CdKfHRp8.js.gz +0 -0
  358. package/dist/client/assets/SessionChatView-D8GoESjb.css +0 -1
  359. package/dist/client/assets/SessionChatView-D8GoESjb.css.br +0 -0
  360. package/dist/client/assets/SessionChatView-D8GoESjb.css.gz +0 -0
  361. package/dist/client/assets/SessionResourceSidebar-DmQOydhf.js +0 -2
  362. package/dist/client/assets/SessionResourceSidebar-DmQOydhf.js.br +0 -0
  363. package/dist/client/assets/SessionResourceSidebar-DmQOydhf.js.gz +0 -0
  364. package/dist/client/assets/TodoWorkspace-Bh1C035B.js +0 -1
  365. package/dist/client/assets/TodoWorkspace-Bh1C035B.js.br +0 -0
  366. package/dist/client/assets/TodoWorkspace-Bh1C035B.js.gz +0 -0
  367. package/dist/client/assets/abnfDiagram-VCTEODGH-Cvf_KWZ0.js.br +0 -0
  368. package/dist/client/assets/abnfDiagram-VCTEODGH-Cvf_KWZ0.js.gz +0 -0
  369. package/dist/client/assets/app-DuUnqxq-.js +0 -37
  370. package/dist/client/assets/app-DuUnqxq-.js.br +0 -0
  371. package/dist/client/assets/app-DuUnqxq-.js.gz +0 -0
  372. package/dist/client/assets/arc-UvdowQOf.js.br +0 -0
  373. package/dist/client/assets/arc-UvdowQOf.js.gz +0 -0
  374. package/dist/client/assets/architectureDiagram-5GKGNRK7-DotsbCCA.js.br +0 -0
  375. package/dist/client/assets/arrow-up-DNkfesW0.js +0 -1
  376. package/dist/client/assets/blockDiagram-I7D4REHJ-CoOfSG4k.js.br +0 -0
  377. package/dist/client/assets/blockDiagram-I7D4REHJ-CoOfSG4k.js.gz +0 -0
  378. package/dist/client/assets/c4Diagram-7LVT6UL2-BAfjgs8B.js.br +0 -0
  379. package/dist/client/assets/c4Diagram-7LVT6UL2-BAfjgs8B.js.gz +0 -0
  380. package/dist/client/assets/channel-BzMU9Wks.js +0 -1
  381. package/dist/client/assets/chunk-F27PBJKO-BI3Di4Ve.js.br +0 -0
  382. package/dist/client/assets/chunk-F27PBJKO-BI3Di4Ve.js.gz +0 -0
  383. package/dist/client/assets/chunk-IMKFNOWR-Cvvs1wmn.js.br +0 -0
  384. package/dist/client/assets/chunk-IMKFNOWR-Cvvs1wmn.js.gz +0 -0
  385. package/dist/client/assets/chunk-SVP7TREG-BZfMhm64.js.br +0 -0
  386. package/dist/client/assets/chunk-SVP7TREG-BZfMhm64.js.gz +0 -0
  387. package/dist/client/assets/chunk-TICWLB2K-DmkEaRK3.js.br +0 -0
  388. package/dist/client/assets/chunk-TICWLB2K-DmkEaRK3.js.gz +0 -0
  389. package/dist/client/assets/classDiagram-ZZMXUADV-DtAtEoWU.js +0 -1
  390. package/dist/client/assets/classDiagram-v2-VYDZK3BY-DtAtEoWU.js +0 -1
  391. package/dist/client/assets/clipboardText-cZXParp1.js +0 -1
  392. package/dist/client/assets/clipboardText-cZXParp1.js.br +0 -0
  393. package/dist/client/assets/clipboardText-cZXParp1.js.gz +0 -0
  394. package/dist/client/assets/cose-bilkent-JH36ORCC-0xPYMc2z.js.br +0 -0
  395. package/dist/client/assets/cose-bilkent-JH36ORCC-0xPYMc2z.js.gz +0 -0
  396. package/dist/client/assets/cynefin-OW5HDTMX-BQ7-lCHm.js.br +0 -0
  397. package/dist/client/assets/cynefin-OW5HDTMX-BQ7-lCHm.js.gz +0 -0
  398. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-CazHuSj1.js.br +0 -0
  399. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-CazHuSj1.js.gz +0 -0
  400. package/dist/client/assets/dagre-GXQ25YYZ-CJNgsyHQ.js.br +0 -0
  401. package/dist/client/assets/dagre-GXQ25YYZ-CJNgsyHQ.js.gz +0 -0
  402. package/dist/client/assets/diagram-S7CK7UJ4-D4xXIj1P.js.br +0 -0
  403. package/dist/client/assets/diagram-S7CK7UJ4-D4xXIj1P.js.gz +0 -0
  404. package/dist/client/assets/diagram-UQ7AKVKN-BWhpL-35.js.br +0 -0
  405. package/dist/client/assets/diagram-UQ7AKVKN-BWhpL-35.js.gz +0 -0
  406. package/dist/client/assets/diagram-VSXAHHWV-DG9A7EgJ.js.br +0 -0
  407. package/dist/client/assets/diagram-VSXAHHWV-DG9A7EgJ.js.gz +0 -0
  408. package/dist/client/assets/diagram-VX7I27RA-L5PSvynM.js.br +0 -0
  409. package/dist/client/assets/diagram-VX7I27RA-L5PSvynM.js.gz +0 -0
  410. package/dist/client/assets/diagram-Z3DM3KII-moBH7ruR.js.br +0 -0
  411. package/dist/client/assets/diagram-Z3DM3KII-moBH7ruR.js.gz +0 -0
  412. package/dist/client/assets/ebnfDiagram-PWID7BFC-DEiGgcRP.js.br +0 -0
  413. package/dist/client/assets/ebnfDiagram-PWID7BFC-DEiGgcRP.js.gz +0 -0
  414. package/dist/client/assets/erDiagram-RLTQ6QDP-BboIleYi.js.br +0 -0
  415. package/dist/client/assets/erDiagram-RLTQ6QDP-BboIleYi.js.gz +0 -0
  416. package/dist/client/assets/flowDiagram-HODETNUW-COxz7Rda.js.br +0 -0
  417. package/dist/client/assets/flowDiagram-HODETNUW-COxz7Rda.js.gz +0 -0
  418. package/dist/client/assets/ganttDiagram-EL5Y4UJY-_XdRvgyZ.js.br +0 -0
  419. package/dist/client/assets/ganttDiagram-EL5Y4UJY-_XdRvgyZ.js.gz +0 -0
  420. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-CBb9xBNW.js.br +0 -0
  421. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-CBb9xBNW.js.gz +0 -0
  422. package/dist/client/assets/index-nIgxJ6I3.css +0 -1
  423. package/dist/client/assets/index-nIgxJ6I3.css.br +0 -0
  424. package/dist/client/assets/index-nIgxJ6I3.css.gz +0 -0
  425. package/dist/client/assets/ishikawaDiagram-5VMMS53U-Bcr-lhIE.js.br +0 -0
  426. package/dist/client/assets/ishikawaDiagram-5VMMS53U-Bcr-lhIE.js.gz +0 -0
  427. package/dist/client/assets/journeyDiagram-3NMN7TZE-3vK6s9Pq.js.br +0 -0
  428. package/dist/client/assets/journeyDiagram-3NMN7TZE-3vK6s9Pq.js.gz +0 -0
  429. package/dist/client/assets/kanban-definition-UXKFOSKX-DqDYDca0.js.br +0 -0
  430. package/dist/client/assets/kanban-definition-UXKFOSKX-DqDYDca0.js.gz +0 -0
  431. package/dist/client/assets/layout-C7_WwzCP.js.br +0 -0
  432. package/dist/client/assets/layout-C7_WwzCP.js.gz +0 -0
  433. package/dist/client/assets/linear-BQCRhl6P.js.gz +0 -0
  434. package/dist/client/assets/link-Cq14tNBm.js.br +0 -0
  435. package/dist/client/assets/link-Cq14tNBm.js.gz +0 -0
  436. package/dist/client/assets/loader-circle-Df0zpx5N.js +0 -1
  437. package/dist/client/assets/mermaid.core-DGsccxt-.js.br +0 -0
  438. package/dist/client/assets/mermaid.core-DGsccxt-.js.gz +0 -0
  439. package/dist/client/assets/mindmap-definition-YA3MSWOX-l0eF1PQE.js.br +0 -0
  440. package/dist/client/assets/mindmap-definition-YA3MSWOX-l0eF1PQE.js.gz +0 -0
  441. package/dist/client/assets/passwordBootstrap-B5VzheZz.js.br +0 -0
  442. package/dist/client/assets/passwordBootstrap-B5VzheZz.js.gz +0 -0
  443. package/dist/client/assets/pegDiagram-XKGWAZYB-fRrxGIDM.js.br +0 -0
  444. package/dist/client/assets/pegDiagram-XKGWAZYB-fRrxGIDM.js.gz +0 -0
  445. package/dist/client/assets/pieDiagram-E7YTZNPT-B-EBa3qN.js.br +0 -0
  446. package/dist/client/assets/pieDiagram-E7YTZNPT-B-EBa3qN.js.gz +0 -0
  447. package/dist/client/assets/quadrantDiagram-AXDQQJYC-Dj4e6f4h.js.br +0 -0
  448. package/dist/client/assets/quadrantDiagram-AXDQQJYC-Dj4e6f4h.js.gz +0 -0
  449. package/dist/client/assets/railroadDiagram-O6MQD6OU-CEMppxTC.js.br +0 -0
  450. package/dist/client/assets/railroadDiagram-O6MQD6OU-CEMppxTC.js.gz +0 -0
  451. package/dist/client/assets/rdpSession-C5rS-ImV.js +0 -1
  452. package/dist/client/assets/rdpSession-C5rS-ImV.js.br +0 -0
  453. package/dist/client/assets/rdpSession-C5rS-ImV.js.gz +0 -0
  454. package/dist/client/assets/requirementDiagram-BXWQKSXE-Dri1k4_x.js.br +0 -0
  455. package/dist/client/assets/requirementDiagram-BXWQKSXE-Dri1k4_x.js.gz +0 -0
  456. package/dist/client/assets/sankeyDiagram-P5KCCOFB-CMsL_tYL.js.br +0 -0
  457. package/dist/client/assets/sankeyDiagram-P5KCCOFB-CMsL_tYL.js.gz +0 -0
  458. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-4_4hZtOd.js.br +0 -0
  459. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-4_4hZtOd.js.gz +0 -0
  460. package/dist/client/assets/settings-2-iGqzPez0.js +0 -1
  461. package/dist/client/assets/sizeCapture-INFHLROL-3QA6qj2j.js.br +0 -0
  462. package/dist/client/assets/sizeCapture-INFHLROL-3QA6qj2j.js.gz +0 -0
  463. package/dist/client/assets/stateDiagram-D77RDMKH-90IFPhD9.js.br +0 -0
  464. package/dist/client/assets/stateDiagram-D77RDMKH-90IFPhD9.js.gz +0 -0
  465. package/dist/client/assets/stateDiagram-v2-MP3YSRHH-CH-yvmL4.js +0 -1
  466. package/dist/client/assets/swimlanes-42K2YHIH-BuHieVWC.js.br +0 -0
  467. package/dist/client/assets/swimlanes-42K2YHIH-BuHieVWC.js.gz +0 -0
  468. package/dist/client/assets/swimlanesDiagram-VR7AAH4N-P_rDqbtg.js +0 -8
  469. package/dist/client/assets/swiper-DJjq1TYT.js +0 -1
  470. package/dist/client/assets/swiper-DJjq1TYT.js.br +0 -0
  471. package/dist/client/assets/swiper-DJjq1TYT.js.gz +0 -0
  472. package/dist/client/assets/syntaxHighlight-Cz6TPDW9.js +0 -4
  473. package/dist/client/assets/syntaxHighlight-Cz6TPDW9.js.br +0 -0
  474. package/dist/client/assets/syntaxHighlight-Cz6TPDW9.js.gz +0 -0
  475. package/dist/client/assets/terminal-Dea8wJF3.js.br +0 -0
  476. package/dist/client/assets/terminal-Dea8wJF3.js.gz +0 -0
  477. package/dist/client/assets/timeline-definition-24CTP7MA-C7FpaNwf.js.br +0 -0
  478. package/dist/client/assets/timeline-definition-24CTP7MA-C7FpaNwf.js.gz +0 -0
  479. package/dist/client/assets/triangle-alert-Oj-OsZDw.js +0 -1
  480. package/dist/client/assets/use-gesture-react.esm-DYpdiE_k.js +0 -1
  481. package/dist/client/assets/use-gesture-react.esm-DYpdiE_k.js.br +0 -0
  482. package/dist/client/assets/use-gesture-react.esm-DYpdiE_k.js.gz +0 -0
  483. package/dist/client/assets/vennDiagram-4TSXK5OY-CxoHHVcs.js.br +0 -0
  484. package/dist/client/assets/vennDiagram-4TSXK5OY-CxoHHVcs.js.gz +0 -0
  485. package/dist/client/assets/videoCompression-rr2lu3uy.js.br +0 -0
  486. package/dist/client/assets/videoCompression-rr2lu3uy.js.gz +0 -0
  487. package/dist/client/assets/wardleyDiagram-VM6X3IG4-B4Hsh-Ad.js.br +0 -0
  488. package/dist/client/assets/wardleyDiagram-VM6X3IG4-B4Hsh-Ad.js.gz +0 -0
  489. package/dist/client/assets/xychartDiagram-S5SC5T6Z-CghzsxQv.js.br +0 -0
  490. package/dist/client/assets/xychartDiagram-S5SC5T6Z-CghzsxQv.js.gz +0 -0
@@ -0,0 +1,147 @@
1
+ import { RELAY_CLIENT_CONNECT_TIMEOUT_MS, RELAY_MAX_FRAME_BYTES, RELAY_MAX_BUFFERED_BYTES } from './streamLimits.js';
2
+ import { fromBase64, toBase64 } from './packets.js';
3
+ import { ConnectionAccessError } from './connectionErrors.js';
4
+ const MAX_FRAME_BYTES = RELAY_MAX_FRAME_BYTES;
5
+ const MAX_BUFFER_BYTES = RELAY_MAX_BUFFERED_BYTES;
6
+ /** A byte WebSocket facade over a single explicitly addressed relay stream. */
7
+ export class RelayTransport extends EventTarget {
8
+ url;
9
+ CONNECTING = 0;
10
+ OPEN = 1;
11
+ CLOSING = 2;
12
+ CLOSED = 3;
13
+ protocol = '';
14
+ extensions = '';
15
+ binaryType = 'arraybuffer';
16
+ readyState = 0;
17
+ transportFailure;
18
+ onopen = null;
19
+ onmessage = null;
20
+ onerror = null;
21
+ onclose = null;
22
+ connectionTimings = { entryOpenMs: null, routeOpenMs: null };
23
+ upstream;
24
+ streamId = crypto.randomUUID();
25
+ requested = false;
26
+ deadline;
27
+ get bufferedAmount() { return this.upstream.bufferedAmount; }
28
+ constructor(url, targetServiceId, socketFactory, context = {}) {
29
+ super();
30
+ this.url = url;
31
+ if (!/^[a-zA-Z0-9_.:-]{1,160}$/.test(targetServiceId))
32
+ throw new Error('Invalid target identity');
33
+ if (context.entryServiceId === targetServiceId)
34
+ throw new ConnectionAccessError('RELAY_SELF_TARGET', { ...context, targetServiceId });
35
+ const started = performance.now();
36
+ let entryReadyAt;
37
+ this.upstream = socketFactory(url);
38
+ this.upstream.addEventListener('open', () => {
39
+ this.connectionTimings.entryOpenMs = performance.now() - started;
40
+ });
41
+ this.deadline = setTimeout(() => this.fail('Relay connection timed out'), RELAY_CLIENT_CONNECT_TIMEOUT_MS);
42
+ this.upstream.addEventListener('message', event => {
43
+ if (this.readyState === 3)
44
+ return;
45
+ try {
46
+ if (typeof event.data !== 'string' || new TextEncoder().encode(event.data).length > MAX_FRAME_BYTES)
47
+ throw new Error('Invalid relay envelope');
48
+ const frame = JSON.parse(event.data);
49
+ if (frame.type === 'ready') {
50
+ if (this.requested || this.readyState !== 0)
51
+ throw new Error('Repeated relay handshake');
52
+ entryReadyAt = performance.now();
53
+ this.requested = true;
54
+ this.transmit({ type: 'open', streamId: this.streamId, serviceId: targetServiceId });
55
+ return;
56
+ }
57
+ if (frame.streamId !== this.streamId)
58
+ return;
59
+ if (frame.type === 'opened' && this.readyState === 0) {
60
+ this.connectionTimings.routeOpenMs = entryReadyAt === undefined ? null : performance.now() - entryReadyAt;
61
+ clearTimeout(this.deadline);
62
+ this.readyState = 1;
63
+ const e = new Event('open');
64
+ this.dispatchEvent(e);
65
+ this.onopen?.(e);
66
+ return;
67
+ }
68
+ if (frame.type === 'close') {
69
+ if (frame.code === 'RELAY_AUTHORIZATION_REQUIRED' || frame.reason === 'Authorization revoked') {
70
+ this.transportFailure = new ConnectionAccessError('RELAY_AUTHORIZATION_REQUIRED', { ...context, targetServiceId });
71
+ }
72
+ if (frame.code === 'RELAY_SELF_TARGET')
73
+ this.transportFailure = new ConnectionAccessError('RELAY_SELF_TARGET', { ...context, targetServiceId });
74
+ this.finish(1001, this.transportFailure?.message || 'Relay route closed');
75
+ this.upstream.close();
76
+ return;
77
+ }
78
+ if (frame.type !== 'data' || this.readyState !== 1 || frame.encoding !== 'base64' || typeof frame.payload !== 'string'
79
+ || !/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(frame.payload))
80
+ throw new Error('Invalid ciphertext relay frame');
81
+ const bytes = fromBase64(frame.payload);
82
+ const data = this.binaryType === 'blob' ? new Blob([bytes]) : bytes.buffer;
83
+ const e = new MessageEvent('message', { data });
84
+ this.dispatchEvent(e);
85
+ this.onmessage?.(e);
86
+ }
87
+ catch {
88
+ this.fail('Relay protocol rejected frame');
89
+ }
90
+ });
91
+ this.upstream.addEventListener('close', event => this.finish(event.code || 1006, 'Relay disconnected'));
92
+ this.upstream.addEventListener('error', () => this.fail('Relay transport unavailable'));
93
+ }
94
+ transmit(frame) {
95
+ const data = JSON.stringify(frame);
96
+ if (this.upstream.readyState !== 1 || this.upstream.bufferedAmount + data.length > MAX_BUFFER_BYTES || data.length > MAX_FRAME_BYTES)
97
+ throw new Error('Relay unavailable or congested');
98
+ this.upstream.send(data);
99
+ }
100
+ send(data) {
101
+ if (this.readyState !== 1)
102
+ throw new Error('Relay socket is not open');
103
+ let bytes;
104
+ if (ArrayBuffer.isView(data))
105
+ bytes = new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
106
+ else if (data instanceof ArrayBuffer)
107
+ bytes = new Uint8Array(data);
108
+ else
109
+ throw new Error('Relay secure transport requires binary bytes');
110
+ try {
111
+ this.transmit({ type: 'data', streamId: this.streamId, encoding: 'base64', payload: toBase64(bytes) });
112
+ }
113
+ catch (error) {
114
+ this.fail('Relay transport congested');
115
+ throw error;
116
+ }
117
+ }
118
+ close(code = 1000, reason = '') {
119
+ if (this.readyState === 3)
120
+ return;
121
+ try {
122
+ if (this.requested)
123
+ this.transmit({ type: 'close', streamId: this.streamId });
124
+ }
125
+ catch { /* connection already unavailable */ }
126
+ this.finish(code, reason);
127
+ this.upstream.close();
128
+ }
129
+ fail(reason) {
130
+ if (this.readyState === 3)
131
+ return;
132
+ const e = new Event('error');
133
+ this.dispatchEvent(e);
134
+ this.onerror?.(e);
135
+ this.finish(1006, reason);
136
+ this.upstream.close();
137
+ }
138
+ finish(code, reason) {
139
+ if (this.readyState === 3)
140
+ return;
141
+ clearTimeout(this.deadline);
142
+ this.readyState = 3;
143
+ const e = Object.assign(new Event('close'), { code, reason, wasClean: code === 1000 });
144
+ this.dispatchEvent(e);
145
+ this.onclose?.(e);
146
+ }
147
+ }
@@ -157,9 +157,11 @@ export class RouteAccess {
157
157
  renameSync(temporary, this.filePath);
158
158
  }
159
159
  configuredDirectTargets() {
160
- const targets = new Map(this.additionalTargets().map(target => [target.serviceId, target]));
161
- for (const target of this.registry().directTargets)
162
- targets.set(target.serviceId, target);
160
+ const explicit = this.registry().directTargets;
161
+ const overridden = new Set(explicit.map(target => target.serviceId));
162
+ const targets = new Map(this.additionalTargets().filter(target => !overridden.has(target.serviceId)).map(target => [JSON.stringify([target.serviceId, target.url]), target]));
163
+ for (const target of explicit)
164
+ targets.set(JSON.stringify([target.serviceId, target.url]), target);
163
165
  return [...targets.values()];
164
166
  }
165
167
  configuredTargets() {
@@ -1,3 +1,4 @@
1
+ import { androidRouteAccess } from '../shared/androidDevices.js';
1
2
  import { SessionSharingPresence } from './sessionSharing.js';
2
3
  import { collaborationSessionDisplayName } from '../utils/sessionDisplayName.js';
3
4
  import { mergeShareResources } from '../shared/shareResources.js';
@@ -15,6 +16,7 @@ import { createIdentity, importIdentity, exportIdentity, secureConnection } from
15
16
  import { InvitationStore, validateInvitation } from './invitations.js';
16
17
  import { AuthorizationStore } from './authorization.js';
17
18
  import { resolveAccessRequest, isBusinessApiPath, terminalMessageAction } from './accessPolicy.js';
19
+ import { httpUploadLimit } from './httpUploadLimit.js';
18
20
  import { AsyncQueue, PacketChannel, toBase64, fromBase64 } from './packets.js';
19
21
  import { socketDuplex } from './socketDuplex.js';
20
22
  import { markEncryptedRequest } from './requestContext.js';
@@ -171,7 +173,7 @@ export async function createFederationRuntime(app, directory, handlers, options
171
173
  return stable !== undefined && store.authorize({ subjectId, serviceId, action, sessionId: stable }).allowed;
172
174
  };
173
175
  const resources = (subjectId) => mergeShareResources(store.listEffective({ subjectId, serviceId }).map(g => g.resources));
174
- const androidAllowed = (subjectId, serial, control = false) => full(subjectId) || resources(subjectId).android?.some(d => d.serial === serial && (!control || d.access === 'control')) === true;
176
+ const androidAllowed = (subjectId, serial, control = false) => full(subjectId) || (control ? androidRouteAccess(resources(subjectId).android, serial) === 'control' : !!androidRouteAccess(resources(subjectId).android, serial));
175
177
  const computerAllowed = (subjectId, target) => full(subjectId) || !!computerResource(resources(subjectId), target.host, target.protocol, target.port);
176
178
  const full = (subjectId) => open() || store.hasFullServiceAccess({ subjectId, serviceId });
177
179
  let channel;
@@ -585,7 +587,7 @@ export async function createFederationRuntime(app, directory, handlers, options
585
587
  httpAllowed(operation.head);
586
588
  const bytes = operation.head.binaryChunks === true && packet.bytes instanceof Uint8Array ? packet.bytes : fromBase64(packet.data);
587
589
  operation.size += bytes.length;
588
- const limit = new URL(String(operation.head.path), 'http://inner').pathname === '/api/terminal/fs/upload' ? 110 * 1024 * 1024 : 5 * 1024 * 1024;
590
+ const limit = httpUploadLimit(new URL(String(operation.head.path), 'http://inner').pathname);
589
591
  if (['GET', 'HEAD'].includes(String(operation.head.method)) || bytes.length > TRANSFER_CHUNK_BYTES || operation.size > limit) {
590
592
  cancelHttp(operation);
591
593
  operations.delete(packet.id);
@@ -3,60 +3,14 @@ import { readFileSync } from 'node:fs';
3
3
  import { resolve } from 'node:path';
4
4
  import { desktopDirectTargets } from './desktopTargets.js';
5
5
  import { RelayClient } from './relay.js';
6
- import { readPinnedCertificateAuthority } from './trustedCa.js';
6
+ import { openServiceSocket } from './serviceTransport.js';
7
+ import { serviceEndpoint, normalizeServiceAddress } from './connectionModel.js';
7
8
  import { connectCollaborationRpc } from '../agent/collaborationPeerTransport.js';
8
9
  function relayEndpoint(origin, selfRelayToken) {
9
- const url = new URL('/api/federation/relay', origin);
10
- url.protocol = 'wss:';
10
+ const url = serviceEndpoint(origin, 'relay');
11
11
  url.searchParams.set('selfRelayToken', selfRelayToken);
12
12
  return url.href;
13
13
  }
14
- function secureEndpoint(origin) {
15
- const url = new URL('/api/federation/secure', origin);
16
- url.protocol = url.protocol === 'https:' ? 'wss:' : 'ws:';
17
- return url.href;
18
- }
19
- function openSocket(url, ca, maxPayload = 256 * 1024) {
20
- return new Promise((resolve, reject) => {
21
- const secure = new URL(url).protocol === 'wss:';
22
- const socket = new WebSocket(url, {
23
- ...(secure ? { ...(ca ? { ca } : {}), rejectUnauthorized: true } : {}),
24
- followRedirects: false,
25
- handshakeTimeout: 10_000,
26
- maxPayload,
27
- });
28
- const failed = () => { cleanup(); socket.terminate(); reject(new Error('SELF_RELAY_CONNECTION_FAILED')); };
29
- const opened = () => { cleanup(); socket.on('error', () => socket.terminate()); resolve(socket); };
30
- const cleanup = () => { socket.off('open', opened); socket.off('error', failed); socket.off('close', failed); };
31
- socket.once('open', opened);
32
- socket.once('error', failed);
33
- socket.once('close', failed);
34
- });
35
- }
36
- function waitForReady(socket) {
37
- return new Promise((resolve, reject) => {
38
- const timer = setTimeout(() => fail(), 10_000);
39
- timer.unref?.();
40
- const cleanup = () => { clearTimeout(timer); socket.off('message', ready); socket.off('close', fail); };
41
- const fail = () => { cleanup(); socket.terminate(); reject(new Error('SELF_RELAY_AUTHENTICATION_FAILED')); };
42
- const ready = (raw, binary) => {
43
- try {
44
- const frame = binary ? null : JSON.parse(raw.toString());
45
- if (frame?.type !== 'ready') {
46
- fail();
47
- return;
48
- }
49
- cleanup();
50
- resolve();
51
- }
52
- catch {
53
- fail();
54
- }
55
- };
56
- socket.once('message', ready);
57
- socket.once('close', fail);
58
- });
59
- }
60
14
  /**
61
15
  * A local Termdock service may publish only its own stable identity to other
62
16
  * administrator-configured peers or services pinned by the same Desktop
@@ -93,10 +47,10 @@ export class DesktopSelfRelay {
93
47
  return;
94
48
  const desired = new Map([...desktopDirectTargets(this.options.desktopFile, this.options.serviceId), ...(this.options.targets?.() || [])]
95
49
  .filter(target => target.serviceId !== this.options.serviceId)
96
- .map(target => [target.serviceId, { ...target, url: new URL(target.url.replace(/^wss:/, 'https:')).origin }]));
50
+ .map(target => [JSON.stringify([target.serviceId, normalizeServiceAddress(target.url)]), { ...target, url: normalizeServiceAddress(target.url) }]));
97
51
  for (const [serviceId, state] of this.states) {
98
52
  const target = desired.get(serviceId);
99
- const signature = target && JSON.stringify([target.url, target.caFingerprint256, target.caPath]);
53
+ const signature = target && JSON.stringify([target.url, target.caFingerprint256, target.caPath, target.certificateFingerprint256]);
100
54
  if (!target || signature !== state.signature) {
101
55
  this.stopState(state);
102
56
  this.states.delete(serviceId);
@@ -104,7 +58,7 @@ export class DesktopSelfRelay {
104
58
  }
105
59
  for (const [serviceId, target] of desired)
106
60
  if (!this.states.has(serviceId)) {
107
- const state = { signature: JSON.stringify([target.url, target.caFingerprint256, target.caPath]), stopped: false };
61
+ const state = { signature: JSON.stringify([target.url, target.caFingerprint256, target.caPath, target.certificateFingerprint256]), stopped: false, lifetime: new AbortController() };
108
62
  this.states.set(serviceId, state);
109
63
  void this.run(state, target);
110
64
  }
@@ -113,6 +67,7 @@ export class DesktopSelfRelay {
113
67
  if (state.stopped)
114
68
  return;
115
69
  state.stopped = true;
70
+ state.lifetime.abort();
116
71
  state.wake?.();
117
72
  state.wake = undefined;
118
73
  state.client?.close();
@@ -141,7 +96,7 @@ export class DesktopSelfRelay {
141
96
  async connect(state, target) {
142
97
  const peer = { serviceId: target.serviceId, origin: target.url, ...(target.caFingerprint256 ? { caFingerprint256: target.caFingerprint256 } : {}) };
143
98
  const configuredCa = target.caPath ? readFileSync(resolve(this.options.baseDir || process.cwd(), target.caPath)) : undefined;
144
- const rpc = await connectCollaborationRpc(this.options.identity, peer, undefined, undefined, configuredCa);
99
+ const rpc = await connectCollaborationRpc(this.options.identity, peer, undefined, undefined, configuredCa, target.certificateFingerprint256, state.lifetime.signal);
145
100
  let selfRelayToken;
146
101
  try {
147
102
  const result = await rpc.request({ type: 'self-relay-ticket' });
@@ -155,17 +110,13 @@ export class DesktopSelfRelay {
155
110
  }
156
111
  if (this.stopped || state.stopped)
157
112
  return;
158
- const ca = target.caFingerprint256 ? await readPinnedCertificateAuthority(target.url, target.caFingerprint256) : configuredCa;
159
- const upstream = await openSocket(relayEndpoint(target.url, selfRelayToken), ca);
113
+ const upstream = await openServiceSocket(relayEndpoint(target.url, selfRelayToken), target, { baseDir: this.options.baseDir, maxPayload: 256 * 1024, relayReady: true, signal: state.lifetime.signal });
160
114
  state.upstream = upstream;
161
115
  try {
162
- if (this.stopped || state.stopped)
163
- return;
164
- await waitForReady(upstream);
165
116
  if (this.stopped || state.stopped)
166
117
  return;
167
118
  const client = new RelayClient(upstream, { targets: new Map([[this.options.serviceId,
168
- () => openSocket(secureEndpoint(this.options.localOrigin), this.options.localCa, 1024 * 1024)]]) });
119
+ (signal) => openServiceSocket(serviceEndpoint(typeof this.options.localOrigin === 'function' ? this.options.localOrigin() : this.options.localOrigin).href, { ca: this.options.localCa }, { signal: AbortSignal.any([signal, state.lifetime.signal]) })]]) });
169
120
  state.client = client;
170
121
  await new Promise(resolve => {
171
122
  if (upstream.readyState !== WebSocket.OPEN)
@@ -0,0 +1,123 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { resolve } from 'node:path';
3
+ import * as tls from 'node:tls';
4
+ import WebSocket from 'ws';
5
+ import { normalizeServiceAddress } from './connectionModel.js';
6
+ import { pinnedServerTlsOptions, readPinnedCertificateAuthority } from './trustedCa.js';
7
+ import { RELAY_MAX_FRAME_BYTES } from './streamLimits.js';
8
+ /** One trust decision for probes, direct providers, reverse relays and peer RPC.
9
+ * A pinned leaf, a pinned CA and a CA file are distinct trust modes. */
10
+ export async function serviceTlsOptions(address, trust = {}, baseDir = process.cwd()) {
11
+ const origin = normalizeServiceAddress(address);
12
+ const modes = [trust.ca, trust.caPath, trust.caFingerprint256, trust.certificateFingerprint256].filter(value => value !== undefined);
13
+ if (modes.length > 1)
14
+ throw new Error('Conflicting service certificate trust');
15
+ if (trust.certificateFingerprint256 !== undefined)
16
+ return pinnedServerTlsOptions(origin, trust.certificateFingerprint256);
17
+ if (trust.caFingerprint256 !== undefined)
18
+ return { ca: await readPinnedCertificateAuthority(origin, trust.caFingerprint256) };
19
+ if (trust.caPath !== undefined && !trust.caPath)
20
+ throw new Error('Invalid service CA path');
21
+ if (!modes.length) {
22
+ // Match native clients' OS-approved trust without changing process-global
23
+ // TLS defaults. Explicit pins/CA files never inherit these additional roots.
24
+ const getCertificates = tls.getCACertificates;
25
+ if (getCertificates)
26
+ return { ca: [...new Set([...getCertificates('default'), ...getCertificates('system')])] };
27
+ }
28
+ return { ca: trust.caPath ? readFileSync(resolve(baseDir, trust.caPath)) : trust.ca };
29
+ }
30
+ /** Return a connecting socket, so relay listeners are installed before the
31
+ * entry's ready frame. No business bytes are sent during TLS pin inspection. */
32
+ export async function createServiceSocket(address, trust = {}, options = {}) {
33
+ const url = new URL(address);
34
+ const origin = normalizeServiceAddress(url.origin.replace(/^wss:/, 'https:').replace(/^ws:/, 'http:'));
35
+ if (!['wss:', 'ws:'].includes(url.protocol) || url.username || url.password || url.hash
36
+ || !['/api/federation/secure', '/api/federation/relay'].includes(url.pathname)
37
+ || [...url.searchParams.keys()].length > 1
38
+ || [...url.searchParams.keys()].some(key => url.pathname !== '/api/federation/relay' || !['routeToken', 'selfRelayToken'].includes(key))
39
+ || url.search && Object.keys(options.headers || {}).some(key => key.toLowerCase() === 'authorization'))
40
+ throw new Error('Invalid service transport endpoint');
41
+ const tls = await serviceTlsOptions(origin, trust, options.baseDir);
42
+ options.signal?.throwIfAborted();
43
+ const socket = new WebSocket(url, { ...tls, rejectUnauthorized: true, followRedirects: false, perMessageDeflate: false,
44
+ maxPayload: options.maxPayload ?? 1024 * 1024, handshakeTimeout: options.handshakeTimeout ?? 5000,
45
+ ...(options.headers ? { headers: options.headers } : {}) });
46
+ const abort = () => socket.terminate();
47
+ options.signal?.addEventListener('abort', abort, { once: true });
48
+ socket.once('close', () => options.signal?.removeEventListener('abort', abort));
49
+ socket.on('error', () => socket.terminate());
50
+ return socket;
51
+ }
52
+ export function waitForServiceSocket(socket, signal) {
53
+ return new Promise((resolve, reject) => {
54
+ const cleanup = () => {
55
+ socket.removeEventListener('open', opened);
56
+ socket.removeEventListener('error', failed);
57
+ socket.removeEventListener('close', failed);
58
+ signal?.removeEventListener('abort', aborted);
59
+ };
60
+ const opened = () => { cleanup(); resolve(); };
61
+ const failed = () => { cleanup(); reject(socket.transportFailure || new Error('Service transport unavailable')); };
62
+ const aborted = () => { cleanup(); reject(signal?.reason); };
63
+ if (signal?.aborted) {
64
+ aborted();
65
+ return;
66
+ }
67
+ if (socket.readyState === 1) {
68
+ opened();
69
+ return;
70
+ }
71
+ if (socket.readyState >= 2) {
72
+ failed();
73
+ return;
74
+ }
75
+ socket.addEventListener('open', opened);
76
+ socket.addEventListener('error', failed);
77
+ socket.addEventListener('close', failed);
78
+ signal?.addEventListener('abort', aborted, { once: true });
79
+ });
80
+ }
81
+ export async function openServiceSocket(address, trust = {}, options = {}) {
82
+ const socket = await createServiceSocket(address, trust, options);
83
+ // Subscribe before open: an upgrade response and ready frame can share a packet.
84
+ const ready = options.relayReady ? relayEntryReady(socket, options.signal) : undefined;
85
+ try {
86
+ await waitForServiceSocket(socket, options.signal);
87
+ if (ready)
88
+ await ready;
89
+ if (socket.readyState !== WebSocket.OPEN)
90
+ throw new Error('Service transport closed during handshake');
91
+ return socket;
92
+ }
93
+ catch (error) {
94
+ socket.terminate();
95
+ throw error;
96
+ }
97
+ }
98
+ function relayEntryReady(socket, signal) {
99
+ const ready = new Promise((resolve, reject) => {
100
+ const cleanup = () => { clearTimeout(timer); socket.off('message', message); socket.off('close', failed); signal?.removeEventListener('abort', aborted); };
101
+ const failed = () => { cleanup(); reject(new Error('Relay entry handshake failed')); };
102
+ const aborted = () => { cleanup(); reject(signal?.reason); };
103
+ const message = (raw, binary) => {
104
+ try {
105
+ if (binary || Buffer.byteLength(Array.isArray(raw) ? Buffer.concat(raw) : raw) > RELAY_MAX_FRAME_BYTES || JSON.parse(raw.toString())?.type !== 'ready')
106
+ throw new Error('Invalid entry handshake');
107
+ cleanup();
108
+ resolve();
109
+ }
110
+ catch {
111
+ failed();
112
+ }
113
+ };
114
+ const timer = setTimeout(failed, 10_000);
115
+ socket.once('message', message);
116
+ socket.once('close', failed);
117
+ signal?.addEventListener('abort', aborted, { once: true });
118
+ if (signal?.aborted)
119
+ aborted();
120
+ });
121
+ void ready.catch(() => { });
122
+ return ready;
123
+ }
@@ -8,3 +8,6 @@ export const MAX_OPEN_SECURE_SOCKETS = 128;
8
8
  export const RELAY_PROVIDER_CONNECT_TIMEOUT_MS = 10_000;
9
9
  export const RELAY_ROUTE_OPEN_TIMEOUT_MS = 15_000;
10
10
  export const RELAY_CLIENT_CONNECT_TIMEOUT_MS = 20_000;
11
+ export const RELAY_MAX_FRAME_BYTES = 256 * 1024;
12
+ export const RELAY_MAX_BUFFERED_BYTES = 1024 * 1024;
13
+ export const CONNECTION_ROUND_TIMEOUT_MS = 30_000;
@@ -1,6 +1,67 @@
1
1
  import { X509Certificate } from 'node:crypto';
2
2
  import { get } from 'node:https';
3
+ import { connect, checkServerIdentity } from 'node:tls';
3
4
  const cache = new Map();
5
+ const leafCache = new Map();
6
+ /** Inspect TLS only, without sending HTTP or business data. Preview approves
7
+ * the leaf itself, so a downloaded CA cannot substitute for that approval. */
8
+ export async function pinnedServerTlsOptions(origin, fingerprint) {
9
+ const url = new URL(origin);
10
+ if (url.protocol !== 'https:' || url.username || url.password || !/^[\da-f]{64}$/i.test(fingerprint))
11
+ throw new Error('Invalid pinned server certificate');
12
+ const pin = fingerprint.toUpperCase();
13
+ const key = `${url.origin}:${pin}`;
14
+ let cached = leafCache.get(key);
15
+ if (!cached || cached.expires <= Date.now()) {
16
+ const value = new Promise((resolve, reject) => {
17
+ const socket = connect({ host: url.hostname.replace(/^\[|\]$/g, ''), port: Number(url.port || 443),
18
+ ...(url.hostname.includes(':') || /^[\d.]+$/.test(url.hostname) ? {} : { servername: url.hostname }),
19
+ rejectUnauthorized: false });
20
+ const timer = setTimeout(() => socket.destroy(new Error('Pinned server certificate inspection timed out')), 5000);
21
+ socket.once('error', reject);
22
+ socket.once('close', () => { clearTimeout(timer); reject(new Error('Pinned server certificate inspection closed')); });
23
+ socket.once('secureConnect', () => {
24
+ try {
25
+ const raw = socket.getPeerCertificate().raw;
26
+ if (!raw)
27
+ throw new Error('Server did not present a certificate');
28
+ const cert = new X509Certificate(raw);
29
+ const hostError = checkServerIdentity(url.hostname.replace(/^\[|\]$/g, ''), socket.getPeerCertificate());
30
+ if (hostError)
31
+ throw hostError;
32
+ if (cert.fingerprint256.replaceAll(':', '') !== pin || Date.now() < Date.parse(cert.validFrom)
33
+ || Date.now() > Date.parse(cert.validTo))
34
+ throw new Error('Server certificate no longer matches Preview trust');
35
+ resolve(Buffer.from(cert.toString()));
36
+ }
37
+ catch (error) {
38
+ reject(error);
39
+ }
40
+ finally {
41
+ socket.destroy();
42
+ }
43
+ });
44
+ });
45
+ cached = { expires: Date.now() + 120_000, value };
46
+ if (leafCache.size >= 64)
47
+ leafCache.delete(leafCache.keys().next().value);
48
+ leafCache.set(key, cached);
49
+ void value.catch(() => { if (leafCache.get(key)?.value === value)
50
+ leafCache.delete(key); });
51
+ }
52
+ return {
53
+ ca: await cached.value,
54
+ // A CA-issued leaf can be the exact trust anchor without importing its CA.
55
+ allowPartialTrustChain: true,
56
+ checkServerIdentity(host, cert) {
57
+ const error = checkServerIdentity(host, cert);
58
+ if (error)
59
+ return error;
60
+ if (cert.fingerprint256?.replaceAll(':', '').toUpperCase() !== pin)
61
+ return new Error('Server certificate no longer matches Preview trust');
62
+ },
63
+ };
64
+ }
4
65
  /** Only the CA download is unauthenticated. Its exact SHA-256 fingerprint was
5
66
  * already approved locally for this origin; the subsequent WSS connection must
6
67
  * still pass normal TLS chain, hostname and expiry checks using this CA.
@@ -6,12 +6,10 @@ import { createScrcpySession, resolveScrcpyBinaries } from '../android/scrcpy.js
6
6
  import { androidRecordings } from '../android/recording.js';
7
7
  import { pathValidator } from '../utils/pathValidator.js';
8
8
  const router = Router();
9
- const SERIAL_PATTERN = /^(?:[0-9a-zA-Z_.:\-]+|\[[0-9a-fA-F:.]+\]:\d{1,5})$/;
10
- /** 逐帧/逐控件的诊断日志默认关闭,需要时 TERMDOCK_ANDROID_DEBUG=1 打开。 */
9
+ import { isValidAndroidSerial, androidRouteAccess } from '../shared/androidDevices.js';
10
+ export { isValidAndroidSerial };
11
+ /** Opt-in per-frame diagnostics. */
11
12
  const DEBUG_ANDROID = process.env.TERMDOCK_ANDROID_DEBUG === '1';
12
- export function isValidAndroidSerial(serial) {
13
- return serial.length <= 128 && SERIAL_PATTERN.test(serial);
14
- }
15
13
  router.get('/devices', async (req, res) => {
16
14
  try {
17
15
  const devices = await listDevices();
@@ -24,7 +22,7 @@ router.get('/devices', async (req, res) => {
24
22
  scrcpyVersion = null;
25
23
  }
26
24
  const shared = encryptedRequestResources(req);
27
- res.json({ adbAvailable, scrcpyVersion, devices: shared && !hasEncryptedServiceAccess(req) ? devices.filter(d => shared.android?.some(a => a.serial === d.serial)) : devices });
25
+ res.json({ adbAvailable, scrcpyVersion, devices: shared && !hasEncryptedServiceAccess(req) ? devices.filter(d => androidRouteAccess(shared.android, d.serial)) : devices });
28
26
  }
29
27
  catch (error) {
30
28
  res.status(503).json({ error: error instanceof Error ? error.message : 'ADB_UNAVAILABLE', code: 'ADB_UNAVAILABLE' });
@@ -66,7 +64,7 @@ router.use('/recordings', async (req, res, next) => {
66
64
  try {
67
65
  const id = /^\/([^/]+)(?:\/(?:stop|save))?$/.exec(req.path)?.[1];
68
66
  const serial = id ? (await androidRecordings.info(id, subject)).serial : req.method === 'GET' ? req.query.serial : req.body?.serial;
69
- if (typeof serial !== 'string' || !resources.android?.some(device => device.serial === serial))
67
+ if (typeof serial !== 'string' || !androidRouteAccess(resources.android, serial))
70
68
  throw new Error('PHONE_NOT_SHARED');
71
69
  if (req.body?.directory !== undefined && (typeof req.body.directory !== 'string' || !directoryResource(resources, req.body.directory, true)))
72
70
  throw new Error('DIRECTORY_NOT_SHARED');