termdock 1.4.168 → 1.4.170

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 (515) hide show
  1. package/.desktop-dist/main.js +155 -20
  2. package/dist/client/assets/ChangeWalkthroughPanel-u9y3e-pI.js +2 -0
  3. package/dist/client/assets/ChangeWalkthroughPanel-u9y3e-pI.js.br +0 -0
  4. package/dist/client/assets/ChangeWalkthroughPanel-u9y3e-pI.js.gz +0 -0
  5. package/dist/client/assets/DagPlayground-BLUwaOMM.js +1 -0
  6. package/dist/client/assets/DagPlayground-BLUwaOMM.js.br +0 -0
  7. package/dist/client/assets/DagPlayground-BLUwaOMM.js.gz +0 -0
  8. package/dist/client/assets/DiffLab-ThgXydJA.js +370 -0
  9. package/dist/client/assets/DiffLab-ThgXydJA.js.br +0 -0
  10. package/dist/client/assets/DiffLab-ThgXydJA.js.gz +0 -0
  11. package/dist/client/assets/DiffReview-DNkXOQ2y.js +1 -0
  12. package/dist/client/assets/DiffReview-DNkXOQ2y.js.br +0 -0
  13. package/dist/client/assets/DiffReview-DNkXOQ2y.js.gz +0 -0
  14. package/dist/client/assets/DiffReviewLab-CHyV1WMR.js +2 -0
  15. package/dist/client/assets/DiffReviewLab-CHyV1WMR.js.br +0 -0
  16. package/dist/client/assets/DiffReviewLab-CHyV1WMR.js.gz +0 -0
  17. package/dist/client/assets/DiffViewer-CxxOpsVz.js +35 -0
  18. package/dist/client/assets/DiffViewer-CxxOpsVz.js.br +0 -0
  19. package/dist/client/assets/DiffViewer-CxxOpsVz.js.gz +0 -0
  20. package/dist/client/assets/DiffViewer-T3uj2-aP.css +1 -0
  21. package/dist/client/assets/DiffViewer-T3uj2-aP.css.br +0 -0
  22. package/dist/client/assets/DiffViewer-T3uj2-aP.css.gz +0 -0
  23. package/dist/client/assets/ModelPreview-DZzx3Tzo.js +4112 -0
  24. package/dist/client/assets/ModelPreview-DZzx3Tzo.js.br +0 -0
  25. package/dist/client/assets/ModelPreview-DZzx3Tzo.js.gz +0 -0
  26. package/dist/client/assets/RightSidebar-Bv8Y6hqx.js +55 -0
  27. package/dist/client/assets/RightSidebar-Bv8Y6hqx.js.br +0 -0
  28. package/dist/client/assets/RightSidebar-Bv8Y6hqx.js.gz +0 -0
  29. package/dist/client/assets/RightSidebar-DW-JEgm2.css +1 -0
  30. package/dist/client/assets/{abnfDiagram-VRR7QNED-BPFn9m09.js → abnfDiagram-VCTEODGH-DKmZLRlf.js} +1 -1
  31. package/dist/client/assets/abnfDiagram-VCTEODGH-DKmZLRlf.js.br +0 -0
  32. package/dist/client/assets/abnfDiagram-VCTEODGH-DKmZLRlf.js.gz +0 -0
  33. package/dist/client/assets/app-tT08GaCs.js +175 -0
  34. package/dist/client/assets/app-tT08GaCs.js.br +0 -0
  35. package/dist/client/assets/app-tT08GaCs.js.gz +0 -0
  36. package/dist/client/assets/arc-CjmHoRed.js +1 -0
  37. package/dist/client/assets/arc-CjmHoRed.js.br +0 -0
  38. package/dist/client/assets/arc-CjmHoRed.js.gz +0 -0
  39. package/dist/client/assets/architectureDiagram-5GKGNRK7-B0EDOwYH.js +36 -0
  40. package/dist/client/assets/architectureDiagram-5GKGNRK7-B0EDOwYH.js.br +0 -0
  41. package/dist/client/assets/architectureDiagram-5GKGNRK7-B0EDOwYH.js.gz +0 -0
  42. package/dist/client/assets/blockDiagram-I7D4REHJ-CW-AaouZ.js +129 -0
  43. package/dist/client/assets/blockDiagram-I7D4REHJ-CW-AaouZ.js.br +0 -0
  44. package/dist/client/assets/blockDiagram-I7D4REHJ-CW-AaouZ.js.gz +0 -0
  45. package/dist/client/assets/c4Diagram-7LVT6UL2-aE7hFKfo.js +38 -0
  46. package/dist/client/assets/c4Diagram-7LVT6UL2-aE7hFKfo.js.br +0 -0
  47. package/dist/client/assets/c4Diagram-7LVT6UL2-aE7hFKfo.js.gz +0 -0
  48. package/dist/client/assets/channel-DhsPQnwY.js +1 -0
  49. package/dist/client/assets/{chunk-2Q5K7J3B-CXqAcWtO.js → chunk-2Q5K7J3B-FAEL5P17.js} +1 -1
  50. package/dist/client/assets/{chunk-5VM5RSS4-B2ewCivF.js → chunk-5VM5RSS4-BQJAvucM.js} +1 -1
  51. package/dist/client/assets/chunk-F27PBJKO-DEkt187T.js +1 -0
  52. package/dist/client/assets/chunk-F27PBJKO-DEkt187T.js.br +0 -0
  53. package/dist/client/assets/chunk-F27PBJKO-DEkt187T.js.gz +0 -0
  54. package/dist/client/assets/{chunk-EX3LRPZG-DcpNYccw.js → chunk-IMKFNOWR-BfOJ-x_l.js} +5 -5
  55. package/dist/client/assets/chunk-IMKFNOWR-BfOJ-x_l.js.br +0 -0
  56. package/dist/client/assets/chunk-IMKFNOWR-BfOJ-x_l.js.gz +0 -0
  57. package/dist/client/assets/{chunk-JWPE2WC7-DJGW22NC.js → chunk-JWPE2WC7-BN6q6jKH.js} +1 -1
  58. package/dist/client/assets/chunk-POPQ4Y6H-BrhQRNCn.js +1 -0
  59. package/dist/client/assets/{chunk-MOJQB5TN-CI12TXOM.js → chunk-SVP7TREG-CjZOC5Dj.js} +4 -4
  60. package/dist/client/assets/chunk-SVP7TREG-CjZOC5Dj.js.br +0 -0
  61. package/dist/client/assets/chunk-SVP7TREG-CjZOC5Dj.js.gz +0 -0
  62. package/dist/client/assets/{chunk-V7JOEXUC-D2J88tQk.js → chunk-TICWLB2K-Wshj9ws7.js} +3 -3
  63. package/dist/client/assets/chunk-TICWLB2K-Wshj9ws7.js.br +0 -0
  64. package/dist/client/assets/chunk-TICWLB2K-Wshj9ws7.js.gz +0 -0
  65. package/dist/client/assets/{chunk-XXDRQBXY-DFycwWDp.js → chunk-XXDRQBXY-BPPghuc3.js} +1 -1
  66. package/dist/client/assets/classDiagram-ZZMXUADV-2OomHNTG.js +1 -0
  67. package/dist/client/assets/classDiagram-v2-VYDZK3BY-2OomHNTG.js +1 -0
  68. package/dist/client/assets/{cose-bilkent-JH36ORCC-D8eG4PZe.js → cose-bilkent-JH36ORCC-BjxJYQH8.js} +1 -1
  69. package/dist/client/assets/cose-bilkent-JH36ORCC-BjxJYQH8.js.br +0 -0
  70. package/dist/client/assets/cose-bilkent-JH36ORCC-BjxJYQH8.js.gz +0 -0
  71. package/dist/client/assets/{cynefin-VYW2F7L2-B9Z9SAtQ.js → cynefin-OW5HDTMX-QmUTVmd_.js} +38 -38
  72. package/dist/client/assets/cynefin-OW5HDTMX-QmUTVmd_.js.br +0 -0
  73. package/dist/client/assets/cynefin-OW5HDTMX-QmUTVmd_.js.gz +0 -0
  74. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-CBJtWB9m.js +62 -0
  75. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-CBJtWB9m.js.br +0 -0
  76. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-CBJtWB9m.js.gz +0 -0
  77. package/dist/client/assets/cytoscape.esm-D3_iZ_3b.js.br +0 -0
  78. package/dist/client/assets/cytoscape.esm-D3_iZ_3b.js.gz +0 -0
  79. package/dist/client/assets/dagre-GXQ25YYZ-CJFctjtR.js +4 -0
  80. package/dist/client/assets/dagre-GXQ25YYZ-CJFctjtR.js.br +0 -0
  81. package/dist/client/assets/dagre-GXQ25YYZ-CJFctjtR.js.gz +0 -0
  82. package/dist/client/assets/defaultLocale-CrowFXzY.js.br +0 -0
  83. package/dist/client/assets/defaultLocale-CrowFXzY.js.gz +0 -0
  84. package/dist/client/assets/diagram-S7CK7UJ4-e7Jn-RGH.js +30 -0
  85. package/dist/client/assets/diagram-S7CK7UJ4-e7Jn-RGH.js.br +0 -0
  86. package/dist/client/assets/diagram-S7CK7UJ4-e7Jn-RGH.js.gz +0 -0
  87. package/dist/client/assets/diagram-UQ7AKVKN-B1G-uMf2.js +41 -0
  88. package/dist/client/assets/diagram-UQ7AKVKN-B1G-uMf2.js.br +0 -0
  89. package/dist/client/assets/diagram-UQ7AKVKN-B1G-uMf2.js.gz +0 -0
  90. package/dist/client/assets/{diagram-FQU43EPY-BSU4bMc7.js → diagram-VSXAHHWV-cp7u53yF.js} +3 -3
  91. package/dist/client/assets/diagram-VSXAHHWV-cp7u53yF.js.br +0 -0
  92. package/dist/client/assets/diagram-VSXAHHWV-cp7u53yF.js.gz +0 -0
  93. package/dist/client/assets/diagram-VX7I27RA-DJWrVfMd.js +24 -0
  94. package/dist/client/assets/diagram-VX7I27RA-DJWrVfMd.js.br +0 -0
  95. package/dist/client/assets/diagram-VX7I27RA-DJWrVfMd.js.gz +0 -0
  96. package/dist/client/assets/diagram-Z3DM3KII-B-IZbqzJ.js +24 -0
  97. package/dist/client/assets/diagram-Z3DM3KII-B-IZbqzJ.js.br +0 -0
  98. package/dist/client/assets/diagram-Z3DM3KII-B-IZbqzJ.js.gz +0 -0
  99. package/dist/client/assets/diffWorker-CAzvFFr7.js +27 -0
  100. package/dist/client/assets/diffWorker-CAzvFFr7.js.br +0 -0
  101. package/dist/client/assets/diffWorker-CAzvFFr7.js.gz +0 -0
  102. package/dist/client/assets/{ebnfDiagram-CCIWWBDH-N_k0E7sQ.js → ebnfDiagram-PWID7BFC-Bt4zDbpn.js} +1 -1
  103. package/dist/client/assets/ebnfDiagram-PWID7BFC-Bt4zDbpn.js.br +0 -0
  104. package/dist/client/assets/ebnfDiagram-PWID7BFC-Bt4zDbpn.js.gz +0 -0
  105. package/dist/client/assets/erDiagram-RLTQ6QDP-DUPOkndO.js +99 -0
  106. package/dist/client/assets/erDiagram-RLTQ6QDP-DUPOkndO.js.br +0 -0
  107. package/dist/client/assets/erDiagram-RLTQ6QDP-DUPOkndO.js.gz +0 -0
  108. package/dist/client/assets/flowDiagram-HODETNUW-CBSvTIxa.js +168 -0
  109. package/dist/client/assets/flowDiagram-HODETNUW-CBSvTIxa.js.br +0 -0
  110. package/dist/client/assets/flowDiagram-HODETNUW-CBSvTIxa.js.gz +0 -0
  111. package/dist/client/assets/ganttDiagram-EL5Y4UJY-C7BvkSc8.js +292 -0
  112. package/dist/client/assets/ganttDiagram-EL5Y4UJY-C7BvkSc8.js.br +0 -0
  113. package/dist/client/assets/ganttDiagram-EL5Y4UJY-C7BvkSc8.js.gz +0 -0
  114. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-C4v6Do2L.js +106 -0
  115. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-C4v6Do2L.js.br +0 -0
  116. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-C4v6Do2L.js.gz +0 -0
  117. package/dist/client/assets/index-BaBARzax.css +1 -0
  118. package/dist/client/assets/index-BaBARzax.css.br +0 -0
  119. package/dist/client/assets/index-BaBARzax.css.gz +0 -0
  120. package/dist/client/assets/{index-Ca-rq7yX.js → index-UqXCGE5m.js} +4 -4
  121. package/dist/client/assets/index-UqXCGE5m.js.br +0 -0
  122. package/dist/client/assets/index-UqXCGE5m.js.gz +0 -0
  123. package/dist/client/assets/infoDiagram-27XIBGKW-CVQtEdgb.js +2 -0
  124. package/dist/client/assets/{ishikawaDiagram-FXEZZL3T-Ew07ODU5.js → ishikawaDiagram-5VMMS53U-Cf7tUoyW.js} +5 -5
  125. package/dist/client/assets/ishikawaDiagram-5VMMS53U-Cf7tUoyW.js.br +0 -0
  126. package/dist/client/assets/ishikawaDiagram-5VMMS53U-Cf7tUoyW.js.gz +0 -0
  127. package/dist/client/assets/{journeyDiagram-5HDEW3XC-BUjwylu4.js → journeyDiagram-3NMN7TZE-B-9CWrlr.js} +5 -5
  128. package/dist/client/assets/journeyDiagram-3NMN7TZE-B-9CWrlr.js.br +0 -0
  129. package/dist/client/assets/journeyDiagram-3NMN7TZE-B-9CWrlr.js.gz +0 -0
  130. package/dist/client/assets/{kanban-definition-HUTT4EX6-Cjv8zokk.js → kanban-definition-UXKFOSKX-LDN2IZeo.js} +7 -7
  131. package/dist/client/assets/kanban-definition-UXKFOSKX-LDN2IZeo.js.br +0 -0
  132. package/dist/client/assets/kanban-definition-UXKFOSKX-LDN2IZeo.js.gz +0 -0
  133. package/dist/client/assets/katex-55ZPZeOF.css.br +0 -0
  134. package/dist/client/assets/katex-55ZPZeOF.css.gz +0 -0
  135. package/dist/client/assets/katex-DnlPpQZa.js.br +0 -0
  136. package/dist/client/assets/katex-DnlPpQZa.js.gz +0 -0
  137. package/dist/client/assets/katex-HP8lGamR.js.br +0 -0
  138. package/dist/client/assets/katex-HP8lGamR.js.gz +0 -0
  139. package/dist/client/assets/layout-DvqSuFgF.js +1 -0
  140. package/dist/client/assets/layout-DvqSuFgF.js.br +0 -0
  141. package/dist/client/assets/layout-DvqSuFgF.js.gz +0 -0
  142. package/dist/client/assets/{linear-C6Z8ZZfN.js → linear-D43LQnis.js} +1 -1
  143. package/dist/client/assets/linear-D43LQnis.js.br +0 -0
  144. package/dist/client/assets/linear-D43LQnis.js.gz +0 -0
  145. package/dist/client/assets/mermaid.core-DiblHLKe.js +308 -0
  146. package/dist/client/assets/mermaid.core-DiblHLKe.js.br +0 -0
  147. package/dist/client/assets/mermaid.core-DiblHLKe.js.gz +0 -0
  148. package/dist/client/assets/{mindmap-definition-LN4V7U3C-DACHJUhw.js → mindmap-definition-YA3MSWOX-k3f4uWuu.js} +3 -3
  149. package/dist/client/assets/mindmap-definition-YA3MSWOX-k3f4uWuu.js.br +0 -0
  150. package/dist/client/assets/mindmap-definition-YA3MSWOX-k3f4uWuu.js.gz +0 -0
  151. package/dist/client/assets/ordinal-Cboi1Yqb.js.br +0 -0
  152. package/dist/client/assets/ordinal-Cboi1Yqb.js.gz +0 -0
  153. package/dist/client/assets/{pegDiagram-2B236MQR-C6YRG4Sp.js → pegDiagram-XKGWAZYB-Dj32Fl3j.js} +1 -1
  154. package/dist/client/assets/pegDiagram-XKGWAZYB-Dj32Fl3j.js.br +0 -0
  155. package/dist/client/assets/pegDiagram-XKGWAZYB-Dj32Fl3j.js.gz +0 -0
  156. package/dist/client/assets/pieDiagram-E7YTZNPT-DWGSixfl.js +39 -0
  157. package/dist/client/assets/pieDiagram-E7YTZNPT-DWGSixfl.js.br +0 -0
  158. package/dist/client/assets/pieDiagram-E7YTZNPT-DWGSixfl.js.gz +0 -0
  159. package/dist/client/assets/purify.es-4eNOHKSq.js +3 -0
  160. package/dist/client/assets/purify.es-4eNOHKSq.js.br +0 -0
  161. package/dist/client/assets/purify.es-4eNOHKSq.js.gz +0 -0
  162. package/dist/client/assets/{quadrantDiagram-ABIIQ3AL-DugxSPrH.js → quadrantDiagram-AXDQQJYC-BPScfZWR.js} +1 -1
  163. package/dist/client/assets/quadrantDiagram-AXDQQJYC-BPScfZWR.js.br +0 -0
  164. package/dist/client/assets/quadrantDiagram-AXDQQJYC-BPScfZWR.js.gz +0 -0
  165. package/dist/client/assets/railroadDiagram-O6MQD6OU-CL00HIC2.js +1 -0
  166. package/dist/client/assets/railroadDiagram-O6MQD6OU-CL00HIC2.js.br +0 -0
  167. package/dist/client/assets/railroadDiagram-O6MQD6OU-CL00HIC2.js.gz +0 -0
  168. package/dist/client/assets/react-XDCjal2T.js.br +0 -0
  169. package/dist/client/assets/react-XDCjal2T.js.gz +0 -0
  170. package/dist/client/assets/{requirementDiagram-TGXJPOKE-BzaF87gc.js → requirementDiagram-BXWQKSXE-CosES4L6.js} +12 -12
  171. package/dist/client/assets/requirementDiagram-BXWQKSXE-CosES4L6.js.br +0 -0
  172. package/dist/client/assets/requirementDiagram-BXWQKSXE-CosES4L6.js.gz +0 -0
  173. package/dist/client/assets/sankeyDiagram-P5KCCOFB-CjM8CYFn.js +40 -0
  174. package/dist/client/assets/sankeyDiagram-P5KCCOFB-CjM8CYFn.js.br +0 -0
  175. package/dist/client/assets/sankeyDiagram-P5KCCOFB-CjM8CYFn.js.gz +0 -0
  176. package/dist/client/assets/{sequenceDiagram-DBY2YBRQ-B1gfbBUX.js → sequenceDiagram-WJ2MYXX4-3RKv_35o.js} +1 -1
  177. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-3RKv_35o.js.br +0 -0
  178. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-3RKv_35o.js.gz +0 -0
  179. package/dist/client/assets/{sizeCapture-X5ZJPWSS-Cx3c55P-.js → sizeCapture-INFHLROL-BrVkA4VD.js} +1 -1
  180. package/dist/client/assets/sizeCapture-INFHLROL-BrVkA4VD.js.br +0 -0
  181. package/dist/client/assets/sizeCapture-INFHLROL-BrVkA4VD.js.gz +0 -0
  182. package/dist/client/assets/sparkles-B3pwUd8-.js +1 -0
  183. package/dist/client/assets/stateDiagram-D77RDMKH-DeWhyAVC.js +1 -0
  184. package/dist/client/assets/stateDiagram-D77RDMKH-DeWhyAVC.js.br +0 -0
  185. package/dist/client/assets/stateDiagram-D77RDMKH-DeWhyAVC.js.gz +0 -0
  186. package/dist/client/assets/stateDiagram-v2-MP3YSRHH-DvdrGmTm.js +1 -0
  187. package/dist/client/assets/swimlanes-42K2YHIH-i2m0Wmhn.js +1 -0
  188. package/dist/client/assets/swimlanes-42K2YHIH-i2m0Wmhn.js.br +0 -0
  189. package/dist/client/assets/swimlanes-42K2YHIH-i2m0Wmhn.js.gz +0 -0
  190. package/dist/client/assets/swimlanesDiagram-VR7AAH4N-DIzij9pB.js +8 -0
  191. package/dist/client/assets/terminal-C7X98Amf.js.br +0 -0
  192. package/dist/client/assets/terminal-C7X98Amf.js.gz +0 -0
  193. package/dist/client/assets/{timeline-definition-FHXFAJF6-Dmjeiy4n.js → timeline-definition-24CTP7MA-BImN0AS_.js} +1 -1
  194. package/dist/client/assets/timeline-definition-24CTP7MA-BImN0AS_.js.br +0 -0
  195. package/dist/client/assets/timeline-definition-24CTP7MA-BImN0AS_.js.gz +0 -0
  196. package/dist/client/assets/vennDiagram-4TSXK5OY-DVUHKmvC.js +34 -0
  197. package/dist/client/assets/vennDiagram-4TSXK5OY-DVUHKmvC.js.br +0 -0
  198. package/dist/client/assets/vennDiagram-4TSXK5OY-DVUHKmvC.js.gz +0 -0
  199. package/dist/client/assets/{wardleyDiagram-EHGQE667-C0Qt8nhi.js → wardleyDiagram-VM6X3IG4-B9qi-hc7.js} +4 -4
  200. package/dist/client/assets/wardleyDiagram-VM6X3IG4-B9qi-hc7.js.br +0 -0
  201. package/dist/client/assets/wardleyDiagram-VM6X3IG4-B9qi-hc7.js.gz +0 -0
  202. package/dist/client/assets/xychartDiagram-S5SC5T6Z-3jgBcYVl.js +7 -0
  203. package/dist/client/assets/xychartDiagram-S5SC5T6Z-3jgBcYVl.js.br +0 -0
  204. package/dist/client/assets/xychartDiagram-S5SC5T6Z-3jgBcYVl.js.gz +0 -0
  205. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Bold-icons-38-022d7c89c800.woff2 +0 -0
  206. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Bold-icons-39-63f8fa5b3eba.woff2 +0 -0
  207. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Bold-icons-3a-2d8d46cc4dca.woff2 +0 -0
  208. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Bold-icons-3b-e75aed5d3969.woff2 +0 -0
  209. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Bold-icons-3c-ac2534aae681.woff2 +0 -0
  210. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Bold-icons-3c0-8c49a98e75c4.woff2 +0 -0
  211. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Bold-icons-3c1-971c5e7a86ce.woff2 +0 -0
  212. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Bold-icons-3c2-e5c4893acfb9.woff2 +0 -0
  213. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Bold-icons-3c3-156f2560c871.woff2 +0 -0
  214. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Bold-icons-3c4-49f0d18a7492.woff2 +0 -0
  215. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Bold-icons-3c5-33d81ad28c5c.woff2 +0 -0
  216. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Bold-icons-3c6-5c301879d053.woff2 +0 -0
  217. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Bold-icons-3d-52c90894de44.woff2 +0 -0
  218. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Bold-text-9e8d9df2dd02.woff2 +0 -0
  219. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-BoldItalic-icons-38-7942d3c93afb.woff2 +0 -0
  220. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-BoldItalic-icons-39-19989a2be535.woff2 +0 -0
  221. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-BoldItalic-icons-3a-7786ff4a4dd9.woff2 +0 -0
  222. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-BoldItalic-icons-3b-a759fd623d7e.woff2 +0 -0
  223. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-BoldItalic-icons-3c-2a1178076740.woff2 +0 -0
  224. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-BoldItalic-icons-3c0-6f2c7518f354.woff2 +0 -0
  225. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-BoldItalic-icons-3c1-4bf64cae9dd2.woff2 +0 -0
  226. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-BoldItalic-icons-3c2-7f26d4c7240b.woff2 +0 -0
  227. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-BoldItalic-icons-3c3-fc8e5a85d620.woff2 +0 -0
  228. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-BoldItalic-icons-3c4-91819b7977d3.woff2 +0 -0
  229. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-BoldItalic-icons-3c5-26933eec54e2.woff2 +0 -0
  230. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-BoldItalic-icons-3c6-af186404c8af.woff2 +0 -0
  231. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-BoldItalic-icons-3d-b004d85f5642.woff2 +0 -0
  232. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-BoldItalic-text-da002b4e56d3.woff2 +0 -0
  233. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Italic-icons-38-b3e69191d92f.woff2 +0 -0
  234. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Italic-icons-39-c4d8d66882cb.woff2 +0 -0
  235. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Italic-icons-3a-27609324e8a3.woff2 +0 -0
  236. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Italic-icons-3b-5e73d85d7506.woff2 +0 -0
  237. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Italic-icons-3c-7e535d65bbdb.woff2 +0 -0
  238. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Italic-icons-3c0-6465060a06a1.woff2 +0 -0
  239. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Italic-icons-3c1-9fd72ccd9350.woff2 +0 -0
  240. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Italic-icons-3c2-ea7dd77de270.woff2 +0 -0
  241. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Italic-icons-3c3-12808f88907a.woff2 +0 -0
  242. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Italic-icons-3c4-14b598e5e739.woff2 +0 -0
  243. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Italic-icons-3c5-3d40530ce6c2.woff2 +0 -0
  244. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Italic-icons-3c6-7020aec0d9e1.woff2 +0 -0
  245. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Italic-icons-3d-19831897003a.woff2 +0 -0
  246. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Italic-text-b7a9c776b048.woff2 +0 -0
  247. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Regular-icons-38-a637901140d8.woff2 +0 -0
  248. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Regular-icons-39-838726e8eeca.woff2 +0 -0
  249. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Regular-icons-3a-ec149087d0b9.woff2 +0 -0
  250. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Regular-icons-3b-db8e5a24d580.woff2 +0 -0
  251. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Regular-icons-3c-2290d2ad4621.woff2 +0 -0
  252. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Regular-icons-3c0-3b9edaf85d65.woff2 +0 -0
  253. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Regular-icons-3c1-5e7fb0696bbc.woff2 +0 -0
  254. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Regular-icons-3c2-cfad2884adf5.woff2 +0 -0
  255. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Regular-icons-3c3-d641de88278b.woff2 +0 -0
  256. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Regular-icons-3c4-3b0227356b3b.woff2 +0 -0
  257. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Regular-icons-3c5-9dc67c4d20b4.woff2 +0 -0
  258. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Regular-icons-3c6-c5b444110c62.woff2 +0 -0
  259. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Regular-icons-3d-2b19b65bb43a.woff2 +0 -0
  260. package/dist/client/fonts/terminal/JetBrainsMonoNLNerdFontMono-Regular-text-d7b9316fdf4f.woff2 +0 -0
  261. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-4e-46bdca5c323f.woff2 +0 -0
  262. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-4f-17200dc0dd0d.woff2 +0 -0
  263. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-50-370e36250c30.woff2 +0 -0
  264. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-51-66352f738581.woff2 +0 -0
  265. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-52-191f4025d2b5.woff2 +0 -0
  266. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-53-fb0a637c39bf.woff2 +0 -0
  267. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-54-66f2e72c9ca0.woff2 +0 -0
  268. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-55-54b538fd4fd8.woff2 +0 -0
  269. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-56-88f45aeb2030.woff2 +0 -0
  270. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-57-154d4324f0ce.woff2 +0 -0
  271. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-58-1660c86b8a05.woff2 +0 -0
  272. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-59-31a4c5afa3aa.woff2 +0 -0
  273. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-5a-fa1d1941710e.woff2 +0 -0
  274. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-5b-031a2b2ebeb7.woff2 +0 -0
  275. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-5c-065b634c07b3.woff2 +0 -0
  276. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-5d-71f6cd3ed180.woff2 +0 -0
  277. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-5e-f59de7a6e5c5.woff2 +0 -0
  278. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-5f-8cbe737b6011.woff2 +0 -0
  279. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-60-22913526da09.woff2 +0 -0
  280. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-61-c810c1d1a3a3.woff2 +0 -0
  281. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-62-9464d5d87d65.woff2 +0 -0
  282. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-63-79564d99f5da.woff2 +0 -0
  283. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-64-4b7cff1dae6f.woff2 +0 -0
  284. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-65-8dd48db5e297.woff2 +0 -0
  285. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-66-a808e22a3d14.woff2 +0 -0
  286. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-67-ae5f61af3f79.woff2 +0 -0
  287. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-68-a46bf47bd9ba.woff2 +0 -0
  288. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-69-28210414eafb.woff2 +0 -0
  289. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-6a-6bfb1f5e4fb7.woff2 +0 -0
  290. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-6b-39be890e04e4.woff2 +0 -0
  291. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-6c-79a4ff740d98.woff2 +0 -0
  292. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-6d-2de5a763980e.woff2 +0 -0
  293. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-6e-8e55b339244d.woff2 +0 -0
  294. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-6f-a56caf9fc7fc.woff2 +0 -0
  295. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-70-d70c6ee8e03c.woff2 +0 -0
  296. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-71-ac6f5f86dfef.woff2 +0 -0
  297. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-72-db3d346ecc61.woff2 +0 -0
  298. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-73-e7371bd71f0b.woff2 +0 -0
  299. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-74-43946d9b2f0b.woff2 +0 -0
  300. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-75-ea7cf53e31fa.woff2 +0 -0
  301. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-76-04c7fa4e0ebf.woff2 +0 -0
  302. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-77-24d70898f6b8.woff2 +0 -0
  303. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-78-c6a5d7135296.woff2 +0 -0
  304. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-79-7812cb6432aa.woff2 +0 -0
  305. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-7a-6e123be5cd36.woff2 +0 -0
  306. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-7b-a183ddc6890f.woff2 +0 -0
  307. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-7c-0895291ece9c.woff2 +0 -0
  308. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-7d-1d44252384cf.woff2 +0 -0
  309. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-7e-7be4dc6f056e.woff2 +0 -0
  310. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-7f-0d8e987db151.woff2 +0 -0
  311. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-80-c0c154bb8be0.woff2 +0 -0
  312. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-81-5343baca5ce7.woff2 +0 -0
  313. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-82-6d89af9614ce.woff2 +0 -0
  314. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-83-fa17ef529c5b.woff2 +0 -0
  315. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-84-287ecb493fad.woff2 +0 -0
  316. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-85-fea695c48165.woff2 +0 -0
  317. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-86-8bb35373cb82.woff2 +0 -0
  318. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-87-f83e9f70a6cc.woff2 +0 -0
  319. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-88-894cd19292c1.woff2 +0 -0
  320. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-89-2903a6eaf546.woff2 +0 -0
  321. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-8a-3ce275bfcf96.woff2 +0 -0
  322. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-8b-3aaeb26309a6.woff2 +0 -0
  323. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-8c-719b6608b746.woff2 +0 -0
  324. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-8d-a7f1ccd0dfb7.woff2 +0 -0
  325. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-8e-d503ad5c4958.woff2 +0 -0
  326. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-8f-18c6d04746c8.woff2 +0 -0
  327. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-90-e9d94d915dfe.woff2 +0 -0
  328. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-91-c258b07ec626.woff2 +0 -0
  329. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-92-e4833a556b60.woff2 +0 -0
  330. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-94-0889f5b84499.woff2 +0 -0
  331. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-95-7ef116efe7ee.woff2 +0 -0
  332. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-96-afbc0d2cacda.woff2 +0 -0
  333. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-97-df3903d86f65.woff2 +0 -0
  334. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-98-0f21094931ee.woff2 +0 -0
  335. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-99-eb95f4bead58.woff2 +0 -0
  336. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-9a-764e8b8723ec.woff2 +0 -0
  337. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-9b-33a540b9196a.woff2 +0 -0
  338. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-9c-60d6040aa049.woff2 +0 -0
  339. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-9e-4a64c65bf44d.woff2 +0 -0
  340. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-cjk-9f-4d84fba11345.woff2 +0 -0
  341. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Bold-Subset-punctuation-f1b7708e797a.woff2 +0 -0
  342. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-4e-bb1ec5541ecc.woff2 +0 -0
  343. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-4f-d6e8daa67360.woff2 +0 -0
  344. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-50-63c2ae7f85e8.woff2 +0 -0
  345. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-51-41b6e0624888.woff2 +0 -0
  346. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-52-57de15003b8d.woff2 +0 -0
  347. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-53-94382657e2bc.woff2 +0 -0
  348. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-54-177141086f32.woff2 +0 -0
  349. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-55-5ec6fae9813a.woff2 +0 -0
  350. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-56-720aa493b429.woff2 +0 -0
  351. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-57-a8884711a286.woff2 +0 -0
  352. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-58-42a3e7e1fe9a.woff2 +0 -0
  353. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-59-887ee4253daa.woff2 +0 -0
  354. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-5a-c45806889e3c.woff2 +0 -0
  355. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-5b-da142b99dca9.woff2 +0 -0
  356. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-5c-2bb495e5b511.woff2 +0 -0
  357. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-5d-9da87d6061f2.woff2 +0 -0
  358. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-5e-e4010764e593.woff2 +0 -0
  359. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-5f-a9c9021f6e01.woff2 +0 -0
  360. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-60-306f229a68e0.woff2 +0 -0
  361. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-61-6e4546c5f52a.woff2 +0 -0
  362. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-62-a73e47933059.woff2 +0 -0
  363. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-63-e8f49f472799.woff2 +0 -0
  364. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-64-37b54957eadc.woff2 +0 -0
  365. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-65-2742b20127ad.woff2 +0 -0
  366. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-66-239656e7fe56.woff2 +0 -0
  367. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-67-5dfa72b26c3f.woff2 +0 -0
  368. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-68-fe3d1fc05aae.woff2 +0 -0
  369. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-69-22535dbbd090.woff2 +0 -0
  370. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-6a-c4117cd520aa.woff2 +0 -0
  371. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-6b-895d3349f7de.woff2 +0 -0
  372. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-6c-56a0c71eb1b4.woff2 +0 -0
  373. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-6d-9ec807661604.woff2 +0 -0
  374. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-6e-3b633363cd57.woff2 +0 -0
  375. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-6f-91a1f1c31b75.woff2 +0 -0
  376. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-70-3a904a2a2371.woff2 +0 -0
  377. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-71-e8efb60879b0.woff2 +0 -0
  378. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-72-591318b99498.woff2 +0 -0
  379. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-73-d8f444050aa7.woff2 +0 -0
  380. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-74-55a832a12d7e.woff2 +0 -0
  381. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-75-660977996a4c.woff2 +0 -0
  382. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-76-441a04df9fb5.woff2 +0 -0
  383. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-77-5915143c4398.woff2 +0 -0
  384. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-78-242fbc33c745.woff2 +0 -0
  385. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-79-24d13953150a.woff2 +0 -0
  386. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-7a-41973af74017.woff2 +0 -0
  387. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-7b-f9661fdaf003.woff2 +0 -0
  388. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-7c-ef5167770bf7.woff2 +0 -0
  389. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-7d-d84ad5d95f37.woff2 +0 -0
  390. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-7e-66841a1c6381.woff2 +0 -0
  391. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-7f-5090e017351a.woff2 +0 -0
  392. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-80-9ad74a67c2b9.woff2 +0 -0
  393. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-81-423a60a6dcf1.woff2 +0 -0
  394. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-82-aad812217807.woff2 +0 -0
  395. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-83-3dc74dbac89c.woff2 +0 -0
  396. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-84-68db7802ffe8.woff2 +0 -0
  397. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-85-fa235a7160e4.woff2 +0 -0
  398. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-86-75a6a33d0db2.woff2 +0 -0
  399. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-87-7d98ea8ce063.woff2 +0 -0
  400. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-88-363fa8f178aa.woff2 +0 -0
  401. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-89-f2d185e8721f.woff2 +0 -0
  402. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-8a-e372253a07f5.woff2 +0 -0
  403. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-8b-0af53db9bdc1.woff2 +0 -0
  404. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-8c-6a43d3643480.woff2 +0 -0
  405. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-8d-09c4b5345b99.woff2 +0 -0
  406. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-8e-122a752954a6.woff2 +0 -0
  407. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-8f-c651bbfffeb3.woff2 +0 -0
  408. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-90-ab0a5fef3083.woff2 +0 -0
  409. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-91-e07b5cbe4792.woff2 +0 -0
  410. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-92-cba0a8ee6758.woff2 +0 -0
  411. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-94-e7a6bd14e248.woff2 +0 -0
  412. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-95-420f721d52ba.woff2 +0 -0
  413. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-96-90fd476b83f2.woff2 +0 -0
  414. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-97-34036fc287f7.woff2 +0 -0
  415. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-98-5c3cdd76911e.woff2 +0 -0
  416. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-99-73e6090fd7c8.woff2 +0 -0
  417. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-9a-673ebaebe683.woff2 +0 -0
  418. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-9b-90a5a3ee22d6.woff2 +0 -0
  419. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-9c-116d201c978b.woff2 +0 -0
  420. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-9e-78db36865caa.woff2 +0 -0
  421. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-cjk-9f-27e8d16243d5.woff2 +0 -0
  422. package/dist/client/fonts/terminal/NotoSansMonoCJKsc-Subset-punctuation-a4288065ed29.woff2 +0 -0
  423. package/dist/client/fonts/terminal/manifest.json +1349 -0
  424. package/dist/client/fonts/terminal/manifest.json.br +0 -0
  425. package/dist/client/fonts/terminal/manifest.json.gz +0 -0
  426. package/dist/client/icons/agents/claude.svg.br +0 -0
  427. package/dist/client/icons/agents/claude.svg.gz +0 -0
  428. package/dist/client/icons/agents/codex.svg.br +0 -0
  429. package/dist/client/icons/agents/codex.svg.gz +0 -0
  430. package/dist/client/icons/agents/copilot.svg.br +0 -0
  431. package/dist/client/icons/agents/copilot.svg.gz +0 -0
  432. package/dist/client/icons/agents/droid.svg.br +0 -0
  433. package/dist/client/icons/agents/droid.svg.gz +0 -0
  434. package/dist/client/icons/agents/gemini.svg.br +0 -0
  435. package/dist/client/icons/agents/gemini.svg.gz +0 -0
  436. package/dist/client/icons/agents/goose.svg.br +0 -0
  437. package/dist/client/icons/agents/goose.svg.gz +0 -0
  438. package/dist/client/index.html +7 -52
  439. package/dist/client/index.html.br +0 -0
  440. package/dist/client/index.html.gz +0 -0
  441. package/dist/client/sw-notifications.js.br +0 -0
  442. package/dist/client/sw-notifications.js.gz +0 -0
  443. package/dist/client/sw.js +1 -1
  444. package/dist/client/sw.js.br +0 -0
  445. package/dist/client/sw.js.gz +0 -0
  446. package/dist/client/workbox-9845bf53.js.br +0 -0
  447. package/dist/client/workbox-9845bf53.js.gz +0 -0
  448. package/dist/server/agent/installers.js +47 -27
  449. package/dist/server/cli.js +4 -4
  450. package/dist/server/entry.js +57 -145
  451. package/dist/server/routes/auth.js +9 -3
  452. package/dist/server/routes/filesystem.js +39 -9
  453. package/dist/server/routes/local.js +3 -2
  454. package/dist/server/routes/terminal.js +337 -225
  455. package/dist/server/utils/apiAccess.js +27 -0
  456. package/dist/server/utils/apiCachePolicy.js +10 -0
  457. package/dist/server/utils/authProtection.js +140 -38
  458. package/dist/server/utils/cookieSecurity.js +3 -2
  459. package/dist/server/utils/csrfProtection.js +2 -6
  460. package/dist/server/utils/previewValidation.js +16 -0
  461. package/dist/server/utils/publicSecurity.js +44 -0
  462. package/dist/server/utils/requestDeadline.js +2 -0
  463. package/dist/server/utils/requestSecurity.js +23 -28
  464. package/dist/server/utils/staticAssets.js +97 -0
  465. package/dist/server/utils/terminalClientAttachment.js +61 -0
  466. package/dist/server/utils/terminalHandshakeDimensions.js +9 -0
  467. package/dist/server/utils/terminalOutputDelivery.js +90 -0
  468. package/dist/server/utils/tmuxClientRedraw.js +16 -0
  469. package/dist/server/utils/tmuxInitialScreen.js +50 -0
  470. package/dist/server/utils/tmuxResizeReady.js +56 -0
  471. package/dist/server/utils/webSocketSecurity.js +28 -0
  472. package/package.json +7 -4
  473. package/runtime-manifest.json +4 -4
  474. package/scripts/generate-font-subsets.py +88 -0
  475. package/scripts/precompress-client.mjs +28 -0
  476. package/dist/client/assets/ModelPreview-BVdIA5hh.js +0 -4108
  477. package/dist/client/assets/app-uayLhfKS.js +0 -632
  478. package/dist/client/assets/arc-BrdWVufU.js +0 -1
  479. package/dist/client/assets/architectureDiagram-ZJ3FMSHR-M74Mohos.js +0 -36
  480. package/dist/client/assets/blockDiagram-677ZJIJ3-D6OG5gyC.js +0 -132
  481. package/dist/client/assets/c4Diagram-LMCZKHZV-C2w-_Jc4.js +0 -10
  482. package/dist/client/assets/channel-B3PaW8my.js +0 -1
  483. package/dist/client/assets/chunk-32BRIVSS-CEtSQTtD.js +0 -1
  484. package/dist/client/assets/chunk-RYQCIY6F-DS5ufo5c.js +0 -1
  485. package/dist/client/assets/chunk-VR4S4FIN-0lqTHFzc.js +0 -1
  486. package/dist/client/assets/classDiagram-OUVF2IWQ-CLK6o5ur.js +0 -1
  487. package/dist/client/assets/classDiagram-v2-EOCWNBFH-CLK6o5ur.js +0 -1
  488. package/dist/client/assets/cynefinDiagram-TSTJHNR4-DLfD0XDP.js +0 -62
  489. package/dist/client/assets/dagre-VKFMJZFB-BVcVxS_K.js +0 -4
  490. package/dist/client/assets/diagram-G47NLZAW-U4SDLU5l.js +0 -24
  491. package/dist/client/assets/diagram-NH7WQ7WH-DzUUOLaX.js +0 -24
  492. package/dist/client/assets/diagram-OA4YK3LP-CkCRYrYh.js +0 -30
  493. package/dist/client/assets/diagram-WEI45ONY-D5_8zUCk.js +0 -41
  494. package/dist/client/assets/diffWorker-Bg2YXCD-.js +0 -27
  495. package/dist/client/assets/erDiagram-Q63AITRT-CaBjWdJp.js +0 -85
  496. package/dist/client/assets/flowDiagram-23GEKE2U-CVOqw7CA.js +0 -156
  497. package/dist/client/assets/ganttDiagram-NO4QXBWP-DI8IFeJE.js +0 -292
  498. package/dist/client/assets/gitGraphDiagram-IHSO6WYX-CnpSm3yq.js +0 -106
  499. package/dist/client/assets/graph-D2o_JWn5.js +0 -1
  500. package/dist/client/assets/index-C13NrW5y.css +0 -1
  501. package/dist/client/assets/infoDiagram-FWYZ7A6U-C-dKF4KW.js +0 -2
  502. package/dist/client/assets/layout-1eBIAoSl.js +0 -1
  503. package/dist/client/assets/map-BdqsVdb3.js +0 -1
  504. package/dist/client/assets/mermaid.core-B13cUj_d.js +0 -306
  505. package/dist/client/assets/pieDiagram-ENE6RG2P-7cfuhoAx.js +0 -39
  506. package/dist/client/assets/purify.es-CC4Brkr_.js +0 -3
  507. package/dist/client/assets/railroadDiagram-RFXS5EU6-BhRp2Kow.js +0 -1
  508. package/dist/client/assets/sankeyDiagram-HTMAVEWB-4yvODBzh.js +0 -40
  509. package/dist/client/assets/stateDiagram-2N3HPSRC-CyZ_X_VK.js +0 -1
  510. package/dist/client/assets/stateDiagram-v2-6OUMAXLB-9hsqTyV0.js +0 -1
  511. package/dist/client/assets/swimlanes-5IMT3BWC-BZPAGrt1.js +0 -2
  512. package/dist/client/assets/swimlanesDiagram-G3AALYLV-DYvi0MbZ.js +0 -8
  513. package/dist/client/assets/vennDiagram-L72KCM5P-BC2FrHDP.js +0 -34
  514. package/dist/client/assets/xychartDiagram-FW5EYKEG-cQNpjzG4.js +0 -7
  515. package/dist/client/registerSW.js +0 -1
@@ -0,0 +1,27 @@
1
+ import crypto from 'crypto';
2
+ import { requireAuth } from './authProtection.js';
3
+ export function isTrustedLocalRequest(req, token) {
4
+ const supplied = req.header('X-Termdock-Local-Token');
5
+ if (!token || !supplied || req.headers.origin || req.headers['sec-fetch-site'])
6
+ return false;
7
+ const address = req.socket.remoteAddress ?? '';
8
+ if (!['127.0.0.1', '::1', '::ffff:127.0.0.1'].includes(address))
9
+ return false;
10
+ const a = Buffer.from(token);
11
+ const b = Buffer.from(supplied);
12
+ return a.length === b.length && crypto.timingSafeEqual(a, b);
13
+ }
14
+ /** Mounted at /api BEFORE body parsing. New endpoints are private by default. */
15
+ export function apiAccessGate(localToken) {
16
+ return requireAuth({ bypass: (req) => {
17
+ const path = req.path.toLowerCase().replace(/\/$/, '');
18
+ if (['GET', 'HEAD'].includes(req.method) && ['/auth/status', '/meta'].includes(path))
19
+ return true;
20
+ if (req.method === 'POST' && ['/auth/login', '/auth/logout'].includes(path))
21
+ return true;
22
+ // Preview capabilities perform scoped, session-bound authentication themselves.
23
+ if (['GET', 'HEAD'].includes(req.method) && /^\/terminal\/fs\/preview\//.test(path))
24
+ return true;
25
+ return isTrustedLocalRequest(req, localToken) && (/^\/(?:terminal|local)(?:\/|$)/.test(path) || path === '/diagnostics/runtime');
26
+ } });
27
+ }
@@ -0,0 +1,10 @@
1
+ const VALIDATED_PREVIEWS = new Set(['/terminal/fs/read', '/terminal/fs/blob', '/terminal/fs/eda-preview']);
2
+ /** Ordinary JSON callers require bodies. Preview callers explicitly handle 304. */
3
+ export const apiCachePolicy = (req, res, next) => {
4
+ if (!VALIDATED_PREVIEWS.has(req.path)) {
5
+ delete req.headers['if-none-match'];
6
+ delete req.headers['if-modified-since'];
7
+ res.setHeader('Cache-Control', 'no-store');
8
+ }
9
+ next();
10
+ };
@@ -1,11 +1,12 @@
1
1
  import crypto from 'crypto';
2
+ import { EventEmitter } from 'events';
2
3
  import fs from 'fs';
3
4
  import os from 'os';
4
5
  import path from 'path';
5
6
  import { getCookieSecurityOptions } from './cookieSecurity.js';
6
7
  // Auth state lives under ~/.termdock/. We keep two separate files:
7
8
  // - auth.json: password hash (mode 0600). Presence enables auth.
8
- // - auth-sessions.json: active session tokens (mode 0600). Persisted so
9
+ // - auth-sessions.json: active session token hashes (mode 0600). Persisted so
9
10
  // clients survive a server restart without re-login.
10
11
  const AUTH_DIR = path.join(os.homedir(), '.termdock');
11
12
  const AUTH_FILE = path.join(AUTH_DIR, 'auth.json');
@@ -13,7 +14,7 @@ const SESSIONS_FILE = path.join(AUTH_DIR, 'auth-sessions.json');
13
14
  // Cookie holding the opaque session token. httpOnly + sameSite=lax. The token
14
15
  // itself is 32 random bytes hex; never derived from the password.
15
16
  export const AUTH_COOKIE = 'termdock-auth';
16
- const SESSION_TTL_MS = 30 * 24 * 60 * 60 * 1000; // 30 days
17
+ const SESSION_TTL_MS = 30 * 24 * 60 * 60 * 1000;
17
18
  // scrypt parameters. N=2^15 keeps interactive login latency acceptable on
18
19
  // laptops/phones while still being painful for offline brute force on a
19
20
  // single secret.
@@ -22,7 +23,9 @@ const SCRYPT_R = 8;
22
23
  const SCRYPT_P = 1;
23
24
  const SCRYPT_KEY_LEN = 64;
24
25
  const SCRYPT_SALT_LEN = 16;
25
- // In-memory cache of active sessions, keyed by token. Mirrors SESSIONS_FILE.
26
+ // In-memory cache of active sessions, keyed by SHA-256 token hash.
27
+ export const authEvents = new EventEmitter();
28
+ authEvents.setMaxListeners(0);
26
29
  const sessions = new Map();
27
30
  let sessionsLoaded = false;
28
31
  const loginAttempts = new Map();
@@ -33,7 +36,14 @@ function ensureAuthDir() {
33
36
  }
34
37
  function writeFileSecure(filePath, content) {
35
38
  ensureAuthDir();
36
- fs.writeFileSync(filePath, content, { encoding: 'utf-8', mode: 0o600 });
39
+ const temporary = `${filePath}.${crypto.randomBytes(8).toString('hex')}.tmp`;
40
+ try {
41
+ fs.writeFileSync(temporary, content, { encoding: 'utf-8', mode: 0o600, flag: 'wx' });
42
+ fs.renameSync(temporary, filePath);
43
+ }
44
+ finally {
45
+ fs.rmSync(temporary, { force: true });
46
+ }
37
47
  // Best-effort chmod in case the file already existed with looser perms.
38
48
  try {
39
49
  fs.chmodSync(filePath, 0o600);
@@ -105,6 +115,11 @@ function getEnvPasswordHash() {
105
115
  }
106
116
  return cachedEnvHash.hash;
107
117
  }
118
+ function credentialFingerprint() {
119
+ const password = getEnvPassword();
120
+ const source = password ? `env:${getEnvPasswordHash()}` : `file:${readAuthFile()?.passwordHash ?? 'disabled'}`;
121
+ return crypto.createHash('sha256').update(source).digest('hex');
122
+ }
108
123
  export function isEnvPasswordSet() {
109
124
  return getEnvPassword() !== null;
110
125
  }
@@ -112,10 +127,13 @@ export function isAuthEnabled() {
112
127
  if (getEnvPassword())
113
128
  return true;
114
129
  try {
115
- return fs.existsSync(AUTH_FILE);
130
+ fs.statSync(AUTH_FILE);
131
+ return true;
116
132
  }
117
- catch {
118
- return false;
133
+ catch (error) {
134
+ // Only a missing file disables auth. I/O and permission failures must not
135
+ // turn an authenticated terminal into an anonymous one.
136
+ return error.code !== 'ENOENT';
119
137
  }
120
138
  }
121
139
  export function readAuthFile() {
@@ -124,11 +142,13 @@ export function readAuthFile() {
124
142
  return null;
125
143
  const raw = fs.readFileSync(AUTH_FILE, 'utf-8');
126
144
  const parsed = JSON.parse(raw);
127
- if (parsed.version !== 1 || typeof parsed.passwordHash !== 'string')
145
+ if (parsed.version !== 1 || typeof parsed.passwordHash !== 'string' ||
146
+ !/^scrypt\$[0-9a-f]{32}\$[0-9a-f]{128}$/.test(parsed.passwordHash))
128
147
  return null;
129
148
  return {
130
149
  version: 1,
131
150
  passwordHash: parsed.passwordHash,
151
+ passwordLength: typeof parsed.passwordLength === 'number' ? parsed.passwordLength : undefined,
132
152
  createdAt: typeof parsed.createdAt === 'number' ? parsed.createdAt : Date.now(),
133
153
  };
134
154
  }
@@ -136,8 +156,8 @@ export function readAuthFile() {
136
156
  return null;
137
157
  }
138
158
  }
139
- export function writeAuthFile(passwordHash) {
140
- const payload = { version: 1, passwordHash, createdAt: Date.now() };
159
+ export function writeAuthFile(passwordHash, passwordLength) {
160
+ const payload = { version: 1, passwordHash, createdAt: Date.now(), passwordLength };
141
161
  writeFileSecure(AUTH_FILE, JSON.stringify(payload, null, 2));
142
162
  }
143
163
  export function clearAuthFile() {
@@ -147,8 +167,10 @@ export function clearAuthFile() {
147
167
  }
148
168
  catch { /* ignore */ }
149
169
  // Clearing the password also invalidates all existing sessions.
170
+ sessionsLoaded = true;
150
171
  sessions.clear();
151
172
  persistSessions();
173
+ authEvents.emit('revoked');
152
174
  }
153
175
  function loadSessionsIfNeeded() {
154
176
  if (sessionsLoaded)
@@ -159,14 +181,17 @@ function loadSessionsIfNeeded() {
159
181
  return;
160
182
  const raw = fs.readFileSync(SESSIONS_FILE, 'utf-8');
161
183
  const parsed = JSON.parse(raw);
162
- if (parsed.version !== 1 || !Array.isArray(parsed.sessions))
184
+ if (parsed.version !== 2 || !Array.isArray(parsed.sessions))
163
185
  return;
164
186
  const now = Date.now();
165
187
  for (const record of parsed.sessions) {
166
188
  if (record &&
167
189
  typeof record.token === 'string' &&
190
+ /^[0-9a-f]{64}$/.test(record.token) &&
191
+ record.credential === credentialFingerprint() &&
168
192
  typeof record.expiresAt === 'number' &&
169
193
  typeof record.createdAt === 'number' &&
194
+ typeof record.lastUsedAt === 'number' &&
170
195
  record.expiresAt > now) {
171
196
  sessions.set(record.token, record);
172
197
  }
@@ -174,20 +199,11 @@ function loadSessionsIfNeeded() {
174
199
  }
175
200
  catch { /* ignore */ }
176
201
  }
177
- let persistTimer = null;
178
202
  function persistSessions() {
179
- if (persistTimer)
180
- clearTimeout(persistTimer);
181
- persistTimer = setTimeout(() => {
182
- try {
183
- const payload = {
184
- version: 1,
185
- sessions: Array.from(sessions.values()),
186
- };
187
- writeFileSecure(SESSIONS_FILE, JSON.stringify(payload, null, 2));
188
- }
189
- catch { /* ignore */ }
190
- }, 200);
203
+ // Revocations must reach disk before logout succeeds; a debounce could
204
+ // resurrect the session if the server restarts immediately after logout.
205
+ const payload = { version: 2, sessions: Array.from(sessions.values()) };
206
+ writeFileSecure(SESSIONS_FILE, JSON.stringify(payload, null, 2));
191
207
  }
192
208
  function pruneExpiredSessions() {
193
209
  loadSessionsIfNeeded();
@@ -203,42 +219,65 @@ function pruneExpiredSessions() {
203
219
  persistSessions();
204
220
  }
205
221
  export function createSession() {
206
- loadSessionsIfNeeded();
222
+ pruneExpiredSessions();
223
+ if (sessions.size >= 100) {
224
+ sessions.delete(sessions.keys().next().value);
225
+ authEvents.emit('revoked');
226
+ }
207
227
  const token = crypto.randomBytes(32).toString('hex');
208
228
  const now = Date.now();
209
229
  const record = {
210
230
  token,
211
231
  createdAt: now,
212
232
  expiresAt: now + SESSION_TTL_MS,
233
+ lastUsedAt: now,
234
+ credential: credentialFingerprint(),
213
235
  };
214
- sessions.set(token, record);
236
+ const tokenHash = crypto.createHash('sha256').update(token).digest('hex');
237
+ sessions.set(tokenHash, { ...record, token: tokenHash });
215
238
  persistSessions();
216
239
  return record;
217
240
  }
218
- export function isSessionValid(token) {
241
+ export function isSessionValid(token, touch = false) {
219
242
  if (!token || typeof token !== 'string')
220
243
  return false;
221
244
  loadSessionsIfNeeded();
222
- const record = sessions.get(token);
245
+ const tokenHash = crypto.createHash('sha256').update(token).digest('hex');
246
+ const record = sessions.get(tokenHash);
223
247
  if (!record)
224
248
  return false;
225
- if (record.expiresAt <= Date.now()) {
226
- sessions.delete(token);
249
+ if (record.expiresAt <= Date.now() ||
250
+ record.credential !== credentialFingerprint()) {
251
+ sessions.delete(tokenHash);
227
252
  persistSessions();
228
253
  return false;
229
254
  }
255
+ if (touch) {
256
+ const now = Date.now();
257
+ // Coalesce subsecond HTTP/input bursts, while persisting every new visit
258
+ // before replying. Also immediately upgrade still-valid shorter sessions.
259
+ if (now - record.lastUsedAt >= 1000 || record.expiresAt - record.lastUsedAt < SESSION_TTL_MS) {
260
+ record.lastUsedAt = now;
261
+ record.expiresAt = now + SESSION_TTL_MS;
262
+ persistSessions();
263
+ }
264
+ }
230
265
  return true;
231
266
  }
232
267
  export function destroySession(token) {
233
268
  if (!token)
234
269
  return;
235
270
  loadSessionsIfNeeded();
236
- if (sessions.delete(token))
271
+ if (sessions.delete(crypto.createHash('sha256').update(token).digest('hex'))) {
237
272
  persistSessions();
273
+ authEvents.emit('revoked');
274
+ }
238
275
  }
239
276
  export function destroyAllSessions() {
277
+ sessionsLoaded = true;
240
278
  sessions.clear();
241
279
  persistSessions();
280
+ authEvents.emit('revoked');
242
281
  }
243
282
  // ── Login rate limiting ──
244
283
  // Exponential backoff per source IP: 0, 0, 0, 1s, 4s, 16s, 64s, 256s, capped.
@@ -248,6 +287,10 @@ const BACKOFF_BASE_MS = 1000;
248
287
  const BACKOFF_CAP_MS = 15 * 60 * 1000; // 15 min hard cap per attempt window
249
288
  export function getLoginBlockMs(ip) {
250
289
  const record = loginAttempts.get(ip);
290
+ if (record && Date.now() - record.updatedAt > BACKOFF_CAP_MS * 2) {
291
+ loginAttempts.delete(ip);
292
+ return 0;
293
+ }
251
294
  if (!record)
252
295
  return 0;
253
296
  const remaining = record.blockedUntil - Date.now();
@@ -255,8 +298,12 @@ export function getLoginBlockMs(ip) {
255
298
  }
256
299
  export function recordLoginFailure(ip) {
257
300
  const now = Date.now();
258
- const record = loginAttempts.get(ip) ?? { failures: 0, blockedUntil: 0 };
301
+ const record = loginAttempts.get(ip) ?? { failures: 0, blockedUntil: 0, updatedAt: now };
302
+ record.updatedAt = now;
259
303
  record.failures += 1;
304
+ if (loginAttempts.size >= 4096 && !loginAttempts.has(ip)) {
305
+ loginAttempts.delete(loginAttempts.keys().next().value);
306
+ }
260
307
  if (record.failures > BACKOFF_GRACE_FAILURES) {
261
308
  const exponent = record.failures - BACKOFF_GRACE_FAILURES - 1;
262
309
  const delay = Math.min(BACKOFF_CAP_MS, BACKOFF_BASE_MS * Math.pow(4, exponent));
@@ -274,6 +321,18 @@ export function isRequestAuthenticated(req) {
274
321
  const token = req.cookies?.[AUTH_COOKIE];
275
322
  return isSessionValid(typeof token === 'string' ? token : undefined);
276
323
  }
324
+ // Refresh both sides of the login on HTTP visits. Socket validation alone
325
+ // cannot update a browser cookie, so the UI also checks status on foregrounding.
326
+ export function renewSessionMiddleware(req, res, next) {
327
+ const token = req.cookies?.[AUTH_COOKIE];
328
+ const authMutation = /^\/(?:api\/)?auth\/(?:login|logout)\/?$/i.test(req.path);
329
+ if (!authMutation && isAuthEnabled() && typeof token === 'string' && isSessionValid(token, true)) {
330
+ const key = crypto.createHash('sha256').update(token).digest('hex');
331
+ const record = sessions.get(key);
332
+ setSessionCookie(res, token, record.expiresAt);
333
+ }
334
+ next();
335
+ }
277
336
  // Middleware factory: blocks the request with 401 unless either auth is
278
337
  // disabled (no auth.json) or the request carries a valid session cookie.
279
338
  // Bypass paths are public (login/status/health/static).
@@ -290,7 +349,7 @@ export function requireAuth(options) {
290
349
  }
291
350
  // Verify the cookie attached to a WebSocket upgrade request. Reads the raw
292
351
  // Cookie header and matches AUTH_COOKIE without depending on Express middleware.
293
- export function isUpgradeRequestAuthenticated(cookieHeader) {
352
+ export function isUpgradeRequestAuthenticated(cookieHeader, touch = false) {
294
353
  if (!isAuthEnabled())
295
354
  return true;
296
355
  if (!cookieHeader)
@@ -303,9 +362,13 @@ export function isUpgradeRequestAuthenticated(cookieHeader) {
303
362
  const name = pair.slice(0, idx).trim();
304
363
  if (name !== AUTH_COOKIE)
305
364
  continue;
306
- const value = decodeURIComponent(pair.slice(idx + 1).trim());
307
- if (isSessionValid(value))
308
- return true;
365
+ try {
366
+ const value = decodeURIComponent(pair.slice(idx + 1).trim());
367
+ return isSessionValid(value, touch);
368
+ }
369
+ catch {
370
+ return false;
371
+ }
309
372
  }
310
373
  return false;
311
374
  }
@@ -315,11 +378,11 @@ export function getClientIp(req) {
315
378
  // sees the proxy IP — that's an acceptable trade-off here.
316
379
  return req.socket.remoteAddress ?? 'unknown';
317
380
  }
318
- export function setSessionCookie(res, token) {
381
+ export function setSessionCookie(res, token, expiresAt = Date.now() + SESSION_TTL_MS) {
319
382
  res.cookie(AUTH_COOKIE, token, {
320
383
  httpOnly: true,
321
384
  ...getCookieSecurityOptions(),
322
- maxAge: SESSION_TTL_MS,
385
+ maxAge: Math.max(0, expiresAt - Date.now()),
323
386
  path: '/',
324
387
  });
325
388
  }
@@ -338,3 +401,42 @@ export function verifyPassword(password) {
338
401
  return false;
339
402
  return verifyPasswordAgainstHash(password, auth.passwordHash);
340
403
  }
404
+ // A bounded asynchronous KDF prevents login traffic from blocking terminal I/O
405
+ // or filling the libuv worker queue. The shared budget also covers rotating IPs.
406
+ let activeVerifications = 0;
407
+ let verificationWindow = 0;
408
+ let verificationCount = 0;
409
+ export async function verifyPasswordAsync(password) {
410
+ const now = Date.now();
411
+ if (now - verificationWindow >= 60_000) {
412
+ verificationWindow = now;
413
+ verificationCount = 0;
414
+ }
415
+ if (activeVerifications >= 2 || verificationCount >= 30)
416
+ return null;
417
+ if (!password || Buffer.byteLength(password) > 1024)
418
+ return false;
419
+ verificationCount++;
420
+ const stored = getEnvPasswordHash() ?? readAuthFile()?.passwordHash;
421
+ if (!stored)
422
+ return false;
423
+ const [algorithm, salt, hash] = stored.split('$');
424
+ if (algorithm !== 'scrypt' || !/^[0-9a-f]{32}$/.test(salt ?? '') || !/^[0-9a-f]{128}$/.test(hash ?? ''))
425
+ return false;
426
+ const credential = credentialFingerprint();
427
+ activeVerifications++;
428
+ try {
429
+ const derived = await new Promise((resolve, reject) => {
430
+ crypto.scrypt(password, Buffer.from(salt, 'hex'), SCRYPT_KEY_LEN, {
431
+ N: SCRYPT_N, r: SCRYPT_R, p: SCRYPT_P, maxmem: 128 * SCRYPT_N * SCRYPT_R * 2,
432
+ }, (error, key) => error ? reject(error) : resolve(key));
433
+ });
434
+ return credential === credentialFingerprint() && crypto.timingSafeEqual(derived, Buffer.from(hash, 'hex'));
435
+ }
436
+ catch {
437
+ return false;
438
+ }
439
+ finally {
440
+ activeVerifications--;
441
+ }
442
+ }
@@ -1,13 +1,14 @@
1
+ import { getPublicOrigin } from './publicSecurity.js';
1
2
  let secureCookies = false;
2
3
  export function setSecureCookieMode(enabled) {
3
4
  secureCookies = enabled;
4
5
  }
5
6
  export function shouldUseSecureCookies() {
6
- return secureCookies;
7
+ return secureCookies || Boolean(getPublicOrigin());
7
8
  }
8
9
  export function getCookieSecurityOptions() {
9
10
  return {
10
- secure: secureCookies,
11
+ secure: shouldUseSecureCookies(),
11
12
  sameSite: 'lax',
12
13
  };
13
14
  }
@@ -29,7 +29,8 @@ export class CsrfProtection {
29
29
  * 验证CSRF令牌
30
30
  */
31
31
  verifyToken(cookieToken, headerToken) {
32
- if (typeof cookieToken !== 'string' || typeof headerToken !== 'string') {
32
+ if (typeof cookieToken !== 'string' || typeof headerToken !== 'string' ||
33
+ !new RegExp(`^[0-9a-f]{${this.config.tokenLength * 2}}$`).test(cookieToken) || cookieToken.length !== headerToken.length) {
33
34
  return false;
34
35
  }
35
36
  const cookieBuffer = Buffer.from(cookieToken);
@@ -72,11 +73,6 @@ export class CsrfProtection {
72
73
  if (safeMethods.includes(req.method)) {
73
74
  return next();
74
75
  }
75
- // 跳过某些端点(如果需要)
76
- const skipPaths = ['/api/csrf-token'];
77
- if (skipPaths.some(path => req.path.startsWith(path))) {
78
- return next();
79
- }
80
76
  // 获取令牌
81
77
  const cookieToken = req.cookies?.[this.config.cookieName];
82
78
  const headerToken = req.headers[this.config.headerName.toLowerCase()];
@@ -0,0 +1,16 @@
1
+ import crypto from 'node:crypto';
2
+ import { requestAcceptsEtag } from './edaPreviewCache.js';
3
+ /** Call only after authentication, path validation and file-type/size checks. */
4
+ export function validatePreview(req, res, file, stat, representation) {
5
+ const revision = crypto.createHash('sha256')
6
+ .update(JSON.stringify([file, stat.size, stat.mtimeMs, stat.ctimeMs, representation]))
7
+ .digest('base64url').slice(0, 24);
8
+ const etag = `W/"preview-${revision}"`;
9
+ res.setHeader('ETag', etag);
10
+ res.setHeader('Last-Modified', stat.mtime.toUTCString());
11
+ res.setHeader('Cache-Control', 'private, no-cache');
12
+ if (!requestAcceptsEtag(req.headers['if-none-match'], etag))
13
+ return false;
14
+ res.status(304).end();
15
+ return true;
16
+ }
@@ -0,0 +1,44 @@
1
+ import { isAuthEnabled, readAuthFile } from './authProtection.js';
2
+ /** Explicit external origin; never infer TLS or trust from forwarded headers. */
3
+ export function getPublicOrigin() {
4
+ const raw = process.env.TERMDOCK_PUBLIC_ORIGIN;
5
+ if (!raw)
6
+ return null;
7
+ const url = new URL(raw);
8
+ if (url.protocol !== 'https:' || url.username || url.password || url.pathname !== '/' || url.search || url.hash) {
9
+ throw new Error('TERMDOCK_PUBLIC_ORIGIN must be an HTTPS origin, e.g. https://term.example.com');
10
+ }
11
+ return url.origin;
12
+ }
13
+ export function assertPublicSecurity() {
14
+ if (!getPublicOrigin())
15
+ return;
16
+ if (!isAuthEnabled() || (!process.env.TERMDOCK_PASSWORD && !readAuthFile())) {
17
+ throw new Error('Public access requires authentication. Run td --set-password before starting.');
18
+ }
19
+ if (!process.env.TERMDOCK_PASSWORD && (readAuthFile()?.passwordLength ?? 0) < 16) {
20
+ throw new Error('Public access requires a verified 16-character password. Run td --set-password again.');
21
+ }
22
+ if (process.env.TERMDOCK_PASSWORD && process.env.TERMDOCK_PASSWORD.length < 16) {
23
+ throw new Error('Public access requires TERMDOCK_PASSWORD to contain at least 16 characters.');
24
+ }
25
+ }
26
+ export const securityHeaders = (req, res, next) => {
27
+ res.setHeader('X-Content-Type-Options', 'nosniff');
28
+ res.setHeader('Referrer-Policy', 'no-referrer');
29
+ res.setHeader('X-Frame-Options', 'SAMEORIGIN');
30
+ // Enforce sandbox even for top-level navigation to user-controlled HTML/SVG.
31
+ // allow-same-origin must NEVER be added: that would expose the terminal API.
32
+ const preview = /^\/api\/terminal\/fs(?:\/|$)/i.test(req.path);
33
+ res.setHeader('Content-Security-Policy', preview
34
+ ? "sandbox allow-scripts; frame-ancestors 'self'; object-src 'none'; base-uri 'self'"
35
+ : "script-src 'self' 'wasm-unsafe-eval'; script-src-attr 'none'; worker-src 'self' blob:; frame-ancestors 'self'; object-src 'none'; base-uri 'self'");
36
+ if (getPublicOrigin()) {
37
+ res.setHeader('Strict-Transport-Security', 'max-age=31536000');
38
+ if (!isAuthEnabled()) {
39
+ res.status(503).json({ error: 'Public access requires authentication', code: 'PUBLIC_AUTH_REQUIRED' });
40
+ return;
41
+ }
42
+ }
43
+ next();
44
+ };
@@ -20,6 +20,8 @@ const DEADLINE_RULES = [
20
20
  // 有限但可能很久:大目录搜索(有 done 事件的进度流)、大文件下载。
21
21
  { method: 'GET', pattern: /^\/api\/terminal\/fs\/search$/, deadlineMs: 120_000 },
22
22
  { method: 'GET', pattern: /^\/api\/terminal\/fs\/download$/, deadlineMs: 300_000 },
23
+ // KiCad GLB responses can take longer than rendering to transfer to a phone.
24
+ { method: 'GET', pattern: /^\/api\/terminal\/fs\/eda-preview$/, deadlineMs: 120_000 },
23
25
  // 上传最多 100MB×50 文件,弱网下接收请求体可能要几分钟。注意 Node 内置
24
26
  // requestTimeout(默认 300s,本项目未改)管「请求体接收」阶段并在超时后
25
27
  // 回 408,所以这里必须低于 300s——让我们的 503+日志先出手,而不是被
@@ -1,3 +1,5 @@
1
+ import { shouldUseSecureCookies } from './cookieSecurity.js';
2
+ import { getPublicOrigin } from './publicSecurity.js';
1
3
  import { getLanIPv4Addresses, localAccessManager } from './localAccess.js';
2
4
  const LOOPBACK_HOSTS = new Set(['localhost', '127.0.0.1', '::1']);
3
5
  function stripPort(hostHeader) {
@@ -39,6 +41,9 @@ export function getAllowedHosts() {
39
41
  for (const host of getEnvExtraHosts()) {
40
42
  hosts.add(host);
41
43
  }
44
+ const publicOrigin = getPublicOrigin();
45
+ if (publicOrigin)
46
+ hosts.add(new URL(publicOrigin).hostname);
42
47
  return hosts;
43
48
  }
44
49
  export function isAllowedHost(hostHeader) {
@@ -55,20 +60,25 @@ export function validateHostMiddleware(req, res, next) {
55
60
  next();
56
61
  }
57
62
  export function isAllowedOrigin(originHeader, _hostHeader) {
58
- // 与下方 isUpgradeOriginAllowed 同理:dev 模式下 Vite proxy (9833 → 9835) 用
59
- // changeOrigin: true Host 改写成 `localhost:9835`,而浏览器 Origin 仍是
60
- // `http://192.168.x.x:9833`,强制 Origin === Host 会让 LAN 访问的所有 POST
61
- // (包括登录)全部 403。Origin 头由浏览器控制、无法被网页攻击者伪造,所以只
62
- // 要求 origin host 落在 allowedHosts 白名单内即可,防 CSRF 的强度不变。
63
- // 注意:反向代理场景下 Host 头可能是内部地址,不用它来 gate Origin 检查,
64
- // 否则 TERMDOCK_ALLOWED_HOSTS 只包含公网域名时会误杀正常登录请求。
63
+ // Non-browser API clients may omit Origin; cookie-authenticated mutations
64
+ // additionally require CSRF tokens. Browsers cannot forge this header.
65
65
  if (!originHeader)
66
66
  return true;
67
67
  try {
68
- const originHost = stripPort(new URL(originHeader).host);
69
- if (!originHost)
68
+ const origin = new URL(originHeader);
69
+ if (!['http:', 'https:'].includes(origin.protocol) || origin.origin !== originHeader)
70
70
  return false;
71
- return getAllowedHosts().has(originHost);
71
+ const publicOrigin = getPublicOrigin();
72
+ if (publicOrigin)
73
+ return origin.origin === publicOrigin;
74
+ if (!getAllowedHosts().has(stripPort(origin.host)))
75
+ return false;
76
+ // Only the development proxy intentionally changes Host/port. On normal
77
+ // listeners, another service on the same LAN host is a different origin.
78
+ if (process.env.NODE_ENV === 'development')
79
+ return true;
80
+ return origin.host.toLowerCase() === (_hostHeader ?? '').toLowerCase() &&
81
+ origin.protocol === (shouldUseSecureCookies() ? 'https:' : 'http:');
72
82
  }
73
83
  catch {
74
84
  return false;
@@ -81,23 +91,8 @@ export function validateOriginMiddleware(req, res, next) {
81
91
  }
82
92
  next();
83
93
  }
84
- export function isUpgradeOriginAllowed(originHeader, _hostHeader) {
85
- // WS 升级请求:Origin 头是浏览器实际发出的(不可伪造),而 Host 头可能被前置代理改写。
86
- // 在 dev 模式下 Vite proxy (9833 → 9835) 用 changeOrigin: true 会把 Host 改写成
87
- // `localhost:9835`,但 Origin 仍是 `http://192.168.x.x:9833`。这种 mismatch
88
- // 会让正常 LAN 访问全部 403、WS 退化为持续 reconnecting。
89
- // 这里只要求 origin host 落在 allowedHosts 里(loopback + LAN IPv4 + mDNS 域名),
90
- // 不强制等于 request.headers.host。Origin 校验保持原强度(必须能解析出 host、
91
- // 且 host 在白名单内),所以攻击者把 Origin 改成任意地址仍然过不了。
92
- if (!originHeader)
93
- return true;
94
- try {
95
- const originHost = stripPort(new URL(originHeader).host);
96
- if (!originHost)
97
- return false;
98
- return getAllowedHosts().has(originHost);
99
- }
100
- catch {
94
+ export function isUpgradeOriginAllowed(originHeader, hostHeader) {
95
+ if (getPublicOrigin() && !originHeader)
101
96
  return false;
102
- }
97
+ return isAllowedOrigin(originHeader, hostHeader);
103
98
  }