@prismshadow/penguin-server 0.2.11 → 0.2.15

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 (470) hide show
  1. package/README.md +1 -1
  2. package/dist/api/types.d.ts +3650 -85
  3. package/dist/api/types.js +9 -0
  4. package/dist/auth-token.d.ts +22 -1
  5. package/dist/auth-token.js +7 -5
  6. package/dist/auth-token.js.map +1 -1
  7. package/dist/benchmark-package.d.ts +39 -0
  8. package/dist/benchmark-package.js +97 -0
  9. package/dist/benchmark-package.js.map +1 -0
  10. package/dist/chunk-54E64LWB.js +63 -0
  11. package/dist/chunk-54E64LWB.js.map +1 -0
  12. package/dist/{chunk-Q65VPAQS.js → chunk-5Z4UCHDB.js} +172 -108
  13. package/dist/chunk-5Z4UCHDB.js.map +1 -0
  14. package/dist/chunk-B5IP37ZQ.js +56 -0
  15. package/dist/chunk-HX3WBUYX.js +18 -0
  16. package/dist/chunk-HX3WBUYX.js.map +1 -0
  17. package/dist/chunk-JKJXQTHH.js +19 -0
  18. package/dist/chunk-JKJXQTHH.js.map +1 -0
  19. package/dist/chunk-LPPVGHYD.js +83 -0
  20. package/dist/chunk-LPPVGHYD.js.map +1 -0
  21. package/dist/chunk-NVWAYYRX.js +981 -0
  22. package/dist/chunk-NVWAYYRX.js.map +1 -0
  23. package/dist/chunk-Q4ON2L6E.js +52 -0
  24. package/dist/chunk-Q4ON2L6E.js.map +1 -0
  25. package/dist/chunk-QFV3ERQO.js +20 -0
  26. package/dist/chunk-QFV3ERQO.js.map +1 -0
  27. package/dist/{chunk-HOS3W3UP.js → chunk-TOOTEEM4.js} +50 -8
  28. package/dist/chunk-TOOTEEM4.js.map +1 -0
  29. package/dist/hmr/manifest.d.ts +1 -77
  30. package/dist/hmr/manifest.js +6 -1
  31. package/dist/index.js +86336 -22980
  32. package/dist/index.js.map +1 -1
  33. package/dist/initial-password.js +1 -0
  34. package/dist/install.ps1 +16 -6
  35. package/dist/install.sh +24 -10
  36. package/dist/lock.js +1 -0
  37. package/dist/machine-status.js +2 -1
  38. package/dist/machine-status.js.map +1 -1
  39. package/dist/plugin/index.d.ts +3384 -0
  40. package/dist/plugin/index.js.map +1 -0
  41. package/dist/reset-admin-password.js +8 -5
  42. package/dist/reset-admin-password.js.map +1 -1
  43. package/dist/secret-file.js +4 -13
  44. package/dist/secret-file.js.map +1 -1
  45. package/dist/version-report.d.ts +3 -0
  46. package/dist/version-report.js +3 -2
  47. package/package.json +19 -11
  48. package/web-dist/assets/KaTeX_Size3-Regular-gV2CO0n9.woff2 +0 -0
  49. package/web-dist/assets/abnfDiagram-VCTEODGH-CKWh4hoA.js +1 -0
  50. package/web-dist/assets/{addon-clipboard-1cARCaK9.js → addon-clipboard-DxLqat7q.js} +1 -1
  51. package/web-dist/assets/{addon-fit-BWdzl8Er.js → addon-fit-B8oPGPkW.js} +1 -1
  52. package/web-dist/assets/{addon-web-links-DjXuvn4Z.js → addon-web-links-C0W5TcK0.js} +1 -1
  53. package/web-dist/assets/arc-Dp9EkaAH.js +1 -0
  54. package/web-dist/assets/architectureDiagram-5GKGNRK7-BQ3LUcle.js +36 -0
  55. package/web-dist/assets/blockDiagram-I7D4REHJ-CZzyU0Jj.js +129 -0
  56. package/web-dist/assets/c-BG-tZi7o.js +1 -0
  57. package/web-dist/assets/c4Diagram-7LVT6UL2-Qps3jeAu.js +38 -0
  58. package/web-dist/assets/channel--PblgLlC.js +1 -0
  59. package/web-dist/assets/chunk-2Q5K7J3B-CQMntzuX.js +1 -0
  60. package/web-dist/assets/chunk-5VM5RSS4-2H2ZJAte.js +15 -0
  61. package/web-dist/assets/chunk-F27PBJKO-B30xCNBv.js +1 -0
  62. package/web-dist/assets/chunk-IMKFNOWR-Cyfx4zDs.js +231 -0
  63. package/web-dist/assets/chunk-JWPE2WC7-DADUytTh.js +1 -0
  64. package/web-dist/assets/chunk-POPQ4Y6H-9bjsAxLS.js +1 -0
  65. package/web-dist/assets/chunk-SVP7TREG-B9xO1VpN.js +88 -0
  66. package/web-dist/assets/chunk-TICWLB2K-B6oDkrep.js +206 -0
  67. package/web-dist/assets/chunk-XXDRQBXY-BbU8DR4B.js +1 -0
  68. package/web-dist/assets/classDiagram-ZZMXUADV-mn8tbuqa.js +1 -0
  69. package/web-dist/assets/classDiagram-v2-VYDZK3BY-mn8tbuqa.js +1 -0
  70. package/web-dist/assets/cose-bilkent-JH36ORCC-pkbuyec-.js +1 -0
  71. package/web-dist/assets/cpp-CaeG3uDQ.js +1 -0
  72. package/web-dist/assets/css-Br67jR8j.js +1 -0
  73. package/web-dist/assets/cynefin-OW5HDTMX-DU9YQQnc.js +166 -0
  74. package/web-dist/assets/cynefinDiagram-5FMLGOSQ-3a3XuhQq.js +62 -0
  75. package/web-dist/assets/cytoscape.esm-BB4DxJjf.js +321 -0
  76. package/web-dist/assets/dagre-GXQ25YYZ-BfZ9C5CZ.js +4 -0
  77. package/web-dist/assets/defaultLocale-DX6XiGOO.js +1 -0
  78. package/web-dist/assets/diagram-S7CK7UJ4-BoGhVBMn.js +30 -0
  79. package/web-dist/assets/diagram-UQ7AKVKN-zE67quty.js +41 -0
  80. package/web-dist/assets/diagram-VSXAHHWV-NihoXeXm.js +3 -0
  81. package/web-dist/assets/diagram-VX7I27RA-1627np0S.js +24 -0
  82. package/web-dist/assets/diagram-Z3DM3KII-Ddg_bUan.js +24 -0
  83. package/web-dist/assets/diff-jW5kmiru.js +1 -0
  84. package/web-dist/assets/ebnfDiagram-PWID7BFC-CmPUOM4j.js +1 -0
  85. package/web-dist/assets/erDiagram-RLTQ6QDP-DiTnEK72.js +99 -0
  86. package/web-dist/assets/flowDiagram-HODETNUW-mGQ38tRM.js +168 -0
  87. package/web-dist/assets/ganttDiagram-EL5Y4UJY-DU7MlzpW.js +292 -0
  88. package/web-dist/assets/gitGraphDiagram-WWUBYQGX-CRE_3vjl.js +106 -0
  89. package/web-dist/assets/github-dark-BQV5ugrc.js +1 -0
  90. package/web-dist/assets/github-light-Rcb2q3L5.js +1 -0
  91. package/web-dist/assets/go-B7VTfpnm.js +1 -0
  92. package/web-dist/assets/highlighter-CzfXQ6yd.js +2 -0
  93. package/web-dist/assets/{highlighter-Cu43iYr8.js → highlighter-core-B5CvXcEK.js} +7 -7
  94. package/web-dist/assets/highlighter.worker-D6D9fPma.js +152 -0
  95. package/web-dist/assets/html-BW_6VhB7.js +1 -0
  96. package/web-dist/assets/ibm-plex-sans-condensed-latin-600-normal-CRd5VyFf.woff2 +0 -0
  97. package/web-dist/assets/ibm-plex-sans-condensed-latin-ext-600-normal-CBdNZ9Ci.woff2 +0 -0
  98. package/web-dist/assets/ibm-plex-sans-latin-ext-wght-normal-CIII54If.woff2 +0 -0
  99. package/web-dist/assets/ibm-plex-sans-latin-wght-normal-IvpUvPa2.woff2 +0 -0
  100. package/web-dist/assets/index-BdG4qRyI.js +1275 -0
  101. package/web-dist/assets/index-W-xYFoIm.css +1 -0
  102. package/web-dist/assets/infoDiagram-27XIBGKW-Cdo6Ar-a.js +2 -0
  103. package/web-dist/assets/ini-Dix3pTmg.js +1 -0
  104. package/web-dist/assets/init-Gi6I4Gst.js +1 -0
  105. package/web-dist/assets/ishikawaDiagram-5VMMS53U-C27pgect.js +70 -0
  106. package/web-dist/assets/java-BTDmaRNO.js +1 -0
  107. package/web-dist/assets/javascript-WyGyM1wV.js +1 -0
  108. package/web-dist/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
  109. package/web-dist/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
  110. package/web-dist/assets/journeyDiagram-3NMN7TZE-CVxtKpLG.js +139 -0
  111. package/web-dist/assets/json-B8JryHcM.js +1 -0
  112. package/web-dist/assets/jsx-8cLv2Six.js +1 -0
  113. package/web-dist/assets/kanban-definition-UXKFOSKX-DWA31Da7.js +89 -0
  114. package/web-dist/assets/layout-DWKCU9PO.js +1 -0
  115. package/web-dist/assets/linear-BwCthj_k.js +1 -0
  116. package/web-dist/assets/log-CcaF_xNv.js +1 -0
  117. package/web-dist/assets/markdown-DX-TNHnc.js +1 -0
  118. package/web-dist/assets/mermaid.core-BcTrmPOv.js +310 -0
  119. package/web-dist/assets/mindmap-definition-YA3MSWOX-BLEDhbn1.js +96 -0
  120. package/web-dist/assets/misans-400-100-DHkMCix2.woff2 +0 -0
  121. package/web-dist/assets/misans-400-101-CwgSLsmc.woff2 +0 -0
  122. package/web-dist/assets/misans-400-102-BQgefHPQ.woff2 +0 -0
  123. package/web-dist/assets/misans-400-103-CP58Mc_T.woff2 +0 -0
  124. package/web-dist/assets/misans-400-104-Ta_Xu1gd.woff2 +0 -0
  125. package/web-dist/assets/misans-400-105-CDop11AR.woff2 +0 -0
  126. package/web-dist/assets/misans-400-106-Dv8y0ubk.woff2 +0 -0
  127. package/web-dist/assets/misans-400-107-CjnHtp9E.woff2 +0 -0
  128. package/web-dist/assets/misans-400-108-BA8nQUBw.woff2 +0 -0
  129. package/web-dist/assets/misans-400-109-B6uEN0pG.woff2 +0 -0
  130. package/web-dist/assets/misans-400-110-BQqnShrY.woff2 +0 -0
  131. package/web-dist/assets/misans-400-111-CHB-Jj5X.woff2 +0 -0
  132. package/web-dist/assets/misans-400-112-D1dh4Cjx.woff2 +0 -0
  133. package/web-dist/assets/misans-400-113-Bw_wNCFp.woff2 +0 -0
  134. package/web-dist/assets/misans-400-114-CUb-5IzE.woff2 +0 -0
  135. package/web-dist/assets/misans-400-115-BICOatsO.woff2 +0 -0
  136. package/web-dist/assets/misans-400-116-B3_gmYW6.woff2 +0 -0
  137. package/web-dist/assets/misans-400-117-B8k_y3cv.woff2 +0 -0
  138. package/web-dist/assets/misans-400-118-C-2Cf5C6.woff2 +0 -0
  139. package/web-dist/assets/misans-400-119-CmLP7xnX.woff2 +0 -0
  140. package/web-dist/assets/misans-400-21-DsSSD_Zj.woff2 +0 -0
  141. package/web-dist/assets/misans-400-22-rtkxWOv4.woff2 +0 -0
  142. package/web-dist/assets/misans-400-23-CDDB4M1H.woff2 +0 -0
  143. package/web-dist/assets/misans-400-24-Dqf_XeOL.woff2 +0 -0
  144. package/web-dist/assets/misans-400-25-C4U1tJ5J.woff2 +0 -0
  145. package/web-dist/assets/misans-400-26-CEXOK-nT.woff2 +0 -0
  146. package/web-dist/assets/misans-400-27-BrNOAScF.woff2 +0 -0
  147. package/web-dist/assets/misans-400-28-CPpEnCkG.woff2 +0 -0
  148. package/web-dist/assets/misans-400-29-C9JMVw8g.woff2 +0 -0
  149. package/web-dist/assets/misans-400-30-CD-QimXa.woff2 +0 -0
  150. package/web-dist/assets/misans-400-31-S4k06NbS.woff2 +0 -0
  151. package/web-dist/assets/misans-400-32-zRMBDkz6.woff2 +0 -0
  152. package/web-dist/assets/misans-400-33-sQ_tNZSM.woff2 +0 -0
  153. package/web-dist/assets/misans-400-34-8LEGljja.woff2 +0 -0
  154. package/web-dist/assets/misans-400-35-CxSPyuiU.woff2 +0 -0
  155. package/web-dist/assets/misans-400-36-BY1i4WtO.woff2 +0 -0
  156. package/web-dist/assets/misans-400-37-C0oF42pu.woff2 +0 -0
  157. package/web-dist/assets/misans-400-38-y7xcB90w.woff2 +0 -0
  158. package/web-dist/assets/misans-400-39-C307YgZx.woff2 +0 -0
  159. package/web-dist/assets/misans-400-40-ByZr736f.woff2 +0 -0
  160. package/web-dist/assets/misans-400-41-ChKEw5zV.woff2 +0 -0
  161. package/web-dist/assets/misans-400-42-CD__zJu5.woff2 +0 -0
  162. package/web-dist/assets/misans-400-43-CqNV6_TG.woff2 +0 -0
  163. package/web-dist/assets/misans-400-44-zE-akmW8.woff2 +0 -0
  164. package/web-dist/assets/misans-400-45-Du98otwc.woff2 +0 -0
  165. package/web-dist/assets/misans-400-46-B6JXbEy2.woff2 +0 -0
  166. package/web-dist/assets/misans-400-47-DpqW0kSq.woff2 +0 -0
  167. package/web-dist/assets/misans-400-48-BprON5Q_.woff2 +0 -0
  168. package/web-dist/assets/misans-400-49-N-ct3sN6.woff2 +0 -0
  169. package/web-dist/assets/misans-400-5-ton_4jCN.woff2 +0 -0
  170. package/web-dist/assets/misans-400-50-JgU49P0U.woff2 +0 -0
  171. package/web-dist/assets/misans-400-51-DSS3Moge.woff2 +0 -0
  172. package/web-dist/assets/misans-400-52-BMoXFmwE.woff2 +0 -0
  173. package/web-dist/assets/misans-400-53-BaLMGl4z.woff2 +0 -0
  174. package/web-dist/assets/misans-400-54-CaeSn3OR.woff2 +0 -0
  175. package/web-dist/assets/misans-400-55-BBqrtLxN.woff2 +0 -0
  176. package/web-dist/assets/misans-400-56-DAZ5BnbO.woff2 +0 -0
  177. package/web-dist/assets/misans-400-57-F-n3b0gI.woff2 +0 -0
  178. package/web-dist/assets/misans-400-58-DEUuPQAq.woff2 +0 -0
  179. package/web-dist/assets/misans-400-59-DXP5rhCL.woff2 +0 -0
  180. package/web-dist/assets/misans-400-6-DWCCUO_c.woff2 +0 -0
  181. package/web-dist/assets/misans-400-60-BE6IO6zJ.woff2 +0 -0
  182. package/web-dist/assets/misans-400-61-5Qb1gaxK.woff2 +0 -0
  183. package/web-dist/assets/misans-400-62-D_tJKNAj.woff2 +0 -0
  184. package/web-dist/assets/misans-400-63-hwmne8yB.woff2 +0 -0
  185. package/web-dist/assets/misans-400-64-BGedxReM.woff2 +0 -0
  186. package/web-dist/assets/misans-400-65-BaKPsugb.woff2 +0 -0
  187. package/web-dist/assets/misans-400-66-IdaOMzCz.woff2 +0 -0
  188. package/web-dist/assets/misans-400-67-BdWyS83H.woff2 +0 -0
  189. package/web-dist/assets/misans-400-68-DrZ_1swq.woff2 +0 -0
  190. package/web-dist/assets/misans-400-69-B3jsSD92.woff2 +0 -0
  191. package/web-dist/assets/misans-400-70-D6UZI2Ua.woff2 +0 -0
  192. package/web-dist/assets/misans-400-71-HFxyMCYg.woff2 +0 -0
  193. package/web-dist/assets/misans-400-72-CP5A-yQP.woff2 +0 -0
  194. package/web-dist/assets/misans-400-73-BoD_bu6s.woff2 +0 -0
  195. package/web-dist/assets/misans-400-74-CbJlhZlZ.woff2 +0 -0
  196. package/web-dist/assets/misans-400-75-BsbWuELX.woff2 +0 -0
  197. package/web-dist/assets/misans-400-76-DkwiQhof.woff2 +0 -0
  198. package/web-dist/assets/misans-400-77-6pVHXHnF.woff2 +0 -0
  199. package/web-dist/assets/misans-400-78-CfUF6pih.woff2 +0 -0
  200. package/web-dist/assets/misans-400-79-BCS3Dx4e.woff2 +0 -0
  201. package/web-dist/assets/misans-400-80-BEYSdQ_N.woff2 +0 -0
  202. package/web-dist/assets/misans-400-81-BzL-Gncx.woff2 +0 -0
  203. package/web-dist/assets/misans-400-82-CaENmdUU.woff2 +0 -0
  204. package/web-dist/assets/misans-400-83-Bvq1eBcA.woff2 +0 -0
  205. package/web-dist/assets/misans-400-84-Ctd90hiP.woff2 +0 -0
  206. package/web-dist/assets/misans-400-85-DWuOxfL1.woff2 +0 -0
  207. package/web-dist/assets/misans-400-86-D5niZS5c.woff2 +0 -0
  208. package/web-dist/assets/misans-400-87-DkOIADQJ.woff2 +0 -0
  209. package/web-dist/assets/misans-400-88-CGY4WTcC.woff2 +0 -0
  210. package/web-dist/assets/misans-400-89-CA3eoMTt.woff2 +0 -0
  211. package/web-dist/assets/misans-400-90-CzxR9MYb.woff2 +0 -0
  212. package/web-dist/assets/misans-400-91-Dyr85txc.woff2 +0 -0
  213. package/web-dist/assets/misans-400-97-qEZrCUNe.woff2 +0 -0
  214. package/web-dist/assets/misans-400-cyrillic--hFcG0Xp.woff2 +0 -0
  215. package/web-dist/assets/misans-400-extra-ZRI9n2Hu.woff2 +0 -0
  216. package/web-dist/assets/misans-400-latin-BRDR1WaL.woff2 +0 -0
  217. package/web-dist/assets/misans-400-latin-ext-6xS-MvHW.woff2 +0 -0
  218. package/web-dist/assets/misans-400-vietnamese-D7xD7kBB.woff2 +0 -0
  219. package/web-dist/assets/misans-500-100-BHuGA96E.woff2 +0 -0
  220. package/web-dist/assets/misans-500-101-CDMYUz0c.woff2 +0 -0
  221. package/web-dist/assets/misans-500-102-CWcqYYCV.woff2 +0 -0
  222. package/web-dist/assets/misans-500-103-BE1QSEzY.woff2 +0 -0
  223. package/web-dist/assets/misans-500-104-CDp743BV.woff2 +0 -0
  224. package/web-dist/assets/misans-500-105-y7dY6Foi.woff2 +0 -0
  225. package/web-dist/assets/misans-500-106-CP-kGZ6j.woff2 +0 -0
  226. package/web-dist/assets/misans-500-107-CUc8Hvle.woff2 +0 -0
  227. package/web-dist/assets/misans-500-108-ItN_x8jX.woff2 +0 -0
  228. package/web-dist/assets/misans-500-109-CEtf3R4D.woff2 +0 -0
  229. package/web-dist/assets/misans-500-110-BSZSHYRL.woff2 +0 -0
  230. package/web-dist/assets/misans-500-111-DfdArrjn.woff2 +0 -0
  231. package/web-dist/assets/misans-500-112-DRtNyrQw.woff2 +0 -0
  232. package/web-dist/assets/misans-500-113-CDT7tKuB.woff2 +0 -0
  233. package/web-dist/assets/misans-500-114-CCh4jwL8.woff2 +0 -0
  234. package/web-dist/assets/misans-500-115-DplUgPp0.woff2 +0 -0
  235. package/web-dist/assets/misans-500-116-C7eCklyK.woff2 +0 -0
  236. package/web-dist/assets/misans-500-117-BA0KabyT.woff2 +0 -0
  237. package/web-dist/assets/misans-500-118-V_M0eu2q.woff2 +0 -0
  238. package/web-dist/assets/misans-500-119-Cgf3Hszt.woff2 +0 -0
  239. package/web-dist/assets/misans-500-21-Di6DyR6O.woff2 +0 -0
  240. package/web-dist/assets/misans-500-22-CSnXvtL-.woff2 +0 -0
  241. package/web-dist/assets/misans-500-23-A06Hm9a6.woff2 +0 -0
  242. package/web-dist/assets/misans-500-24-Df97RCik.woff2 +0 -0
  243. package/web-dist/assets/misans-500-25-bOSJ6YXH.woff2 +0 -0
  244. package/web-dist/assets/misans-500-26-C65icgBb.woff2 +0 -0
  245. package/web-dist/assets/misans-500-27-C_GRm0va.woff2 +0 -0
  246. package/web-dist/assets/misans-500-28-CzZkqO0l.woff2 +0 -0
  247. package/web-dist/assets/misans-500-29-BReyeRyX.woff2 +0 -0
  248. package/web-dist/assets/misans-500-30-DzfjlROz.woff2 +0 -0
  249. package/web-dist/assets/misans-500-31-B2nLpgdU.woff2 +0 -0
  250. package/web-dist/assets/misans-500-32-Bz3rHm8X.woff2 +0 -0
  251. package/web-dist/assets/misans-500-33-AU3lZ1vY.woff2 +0 -0
  252. package/web-dist/assets/misans-500-34-CBAWkH-I.woff2 +0 -0
  253. package/web-dist/assets/misans-500-35-VgnGd14P.woff2 +0 -0
  254. package/web-dist/assets/misans-500-36-B2kfXv6A.woff2 +0 -0
  255. package/web-dist/assets/misans-500-37-DhKo8ykb.woff2 +0 -0
  256. package/web-dist/assets/misans-500-38-D8tTxFuc.woff2 +0 -0
  257. package/web-dist/assets/misans-500-39-DTm3aqJQ.woff2 +0 -0
  258. package/web-dist/assets/misans-500-40-C_akwj8_.woff2 +0 -0
  259. package/web-dist/assets/misans-500-41-RVM1JHQW.woff2 +0 -0
  260. package/web-dist/assets/misans-500-42-MVWIN_il.woff2 +0 -0
  261. package/web-dist/assets/misans-500-43-BtLZYNyD.woff2 +0 -0
  262. package/web-dist/assets/misans-500-44-D0QHMl6G.woff2 +0 -0
  263. package/web-dist/assets/misans-500-45-DRlclX7-.woff2 +0 -0
  264. package/web-dist/assets/misans-500-46-BEWswL4N.woff2 +0 -0
  265. package/web-dist/assets/misans-500-47-COSoxWaW.woff2 +0 -0
  266. package/web-dist/assets/misans-500-48-DZAISq3n.woff2 +0 -0
  267. package/web-dist/assets/misans-500-49-KSfi7MW0.woff2 +0 -0
  268. package/web-dist/assets/misans-500-5-h1SBcwuW.woff2 +0 -0
  269. package/web-dist/assets/misans-500-50-CIVMfG11.woff2 +0 -0
  270. package/web-dist/assets/misans-500-51-BdeNBhBL.woff2 +0 -0
  271. package/web-dist/assets/misans-500-52-CEW4e7ex.woff2 +0 -0
  272. package/web-dist/assets/misans-500-53-lmPCsEnt.woff2 +0 -0
  273. package/web-dist/assets/misans-500-54-B_7AqKQW.woff2 +0 -0
  274. package/web-dist/assets/misans-500-55-B-3RtUnH.woff2 +0 -0
  275. package/web-dist/assets/misans-500-56-g6D0e0cW.woff2 +0 -0
  276. package/web-dist/assets/misans-500-57-D5hp5Yqr.woff2 +0 -0
  277. package/web-dist/assets/misans-500-58-ilnDgEKt.woff2 +0 -0
  278. package/web-dist/assets/misans-500-59-DJYXz8tr.woff2 +0 -0
  279. package/web-dist/assets/misans-500-6-uCdpdDQy.woff2 +0 -0
  280. package/web-dist/assets/misans-500-60-B3Iaqx0p.woff2 +0 -0
  281. package/web-dist/assets/misans-500-61-CMxqg5hc.woff2 +0 -0
  282. package/web-dist/assets/misans-500-62-7FY8O2NQ.woff2 +0 -0
  283. package/web-dist/assets/misans-500-63-JP6vEuJf.woff2 +0 -0
  284. package/web-dist/assets/misans-500-64-Cdub62jh.woff2 +0 -0
  285. package/web-dist/assets/misans-500-65-DVHk_mlC.woff2 +0 -0
  286. package/web-dist/assets/misans-500-66-BX39wRtF.woff2 +0 -0
  287. package/web-dist/assets/misans-500-67-BcsepI3X.woff2 +0 -0
  288. package/web-dist/assets/misans-500-68-etUIUjrh.woff2 +0 -0
  289. package/web-dist/assets/misans-500-69-DfhVmnuA.woff2 +0 -0
  290. package/web-dist/assets/misans-500-70-D6dgy6-B.woff2 +0 -0
  291. package/web-dist/assets/misans-500-71-PkeKjcVn.woff2 +0 -0
  292. package/web-dist/assets/misans-500-72-D66Fnb30.woff2 +0 -0
  293. package/web-dist/assets/misans-500-73-jr9z9870.woff2 +0 -0
  294. package/web-dist/assets/misans-500-74-DsCkPKwe.woff2 +0 -0
  295. package/web-dist/assets/misans-500-75-Dkooq6KM.woff2 +0 -0
  296. package/web-dist/assets/misans-500-76-B0sfieHl.woff2 +0 -0
  297. package/web-dist/assets/misans-500-77-8tflq1ji.woff2 +0 -0
  298. package/web-dist/assets/misans-500-78-COKdMbdp.woff2 +0 -0
  299. package/web-dist/assets/misans-500-79-Bm0rBjSF.woff2 +0 -0
  300. package/web-dist/assets/misans-500-80-B9OoAnyy.woff2 +0 -0
  301. package/web-dist/assets/misans-500-81-DsQ9tpfX.woff2 +0 -0
  302. package/web-dist/assets/misans-500-82-VKsL2Tk2.woff2 +0 -0
  303. package/web-dist/assets/misans-500-83-Ce6mfHYD.woff2 +0 -0
  304. package/web-dist/assets/misans-500-84-D7kPSZLm.woff2 +0 -0
  305. package/web-dist/assets/misans-500-85-W5L0cEfd.woff2 +0 -0
  306. package/web-dist/assets/misans-500-86-DukGOEET.woff2 +0 -0
  307. package/web-dist/assets/misans-500-87-BJ_Lok6j.woff2 +0 -0
  308. package/web-dist/assets/misans-500-88-DbJ11zcA.woff2 +0 -0
  309. package/web-dist/assets/misans-500-89-LNKcEq6M.woff2 +0 -0
  310. package/web-dist/assets/misans-500-90-DNDDgSCd.woff2 +0 -0
  311. package/web-dist/assets/misans-500-91-rT8Q0evu.woff2 +0 -0
  312. package/web-dist/assets/misans-500-97-c8zW_WRq.woff2 +0 -0
  313. package/web-dist/assets/misans-500-cyrillic-CLHOGwgx.woff2 +0 -0
  314. package/web-dist/assets/misans-500-extra-CTAMEQ59.woff2 +0 -0
  315. package/web-dist/assets/misans-500-latin-Be606ott.woff2 +0 -0
  316. package/web-dist/assets/misans-500-latin-ext-BzDyL4sU.woff2 +0 -0
  317. package/web-dist/assets/misans-500-vietnamese-DBOLOqZH.woff2 +0 -0
  318. package/web-dist/assets/mona-sans-latin-ext-wght-normal-BqSk0Z3x.woff2 +0 -0
  319. package/web-dist/assets/mona-sans-latin-wght-normal-Pz49MTQZ.woff2 +0 -0
  320. package/web-dist/assets/noto-sans-sc-100-wght-normal-DrqXJETY.woff2 +0 -0
  321. package/web-dist/assets/noto-sans-sc-101-wght-normal-c94LAl5p.woff2 +0 -0
  322. package/web-dist/assets/noto-sans-sc-102-wght-normal-C1RtbCZr.woff2 +0 -0
  323. package/web-dist/assets/noto-sans-sc-103-wght-normal-DGHo20nu.woff2 +0 -0
  324. package/web-dist/assets/noto-sans-sc-104-wght-normal-CJT2ioDJ.woff2 +0 -0
  325. package/web-dist/assets/noto-sans-sc-105-wght-normal-BFoiJwz2.woff2 +0 -0
  326. package/web-dist/assets/noto-sans-sc-106-wght-normal-D6uUHw3w.woff2 +0 -0
  327. package/web-dist/assets/noto-sans-sc-107-wght-normal-kFQzJDLH.woff2 +0 -0
  328. package/web-dist/assets/noto-sans-sc-108-wght-normal-7aXvqIa2.woff2 +0 -0
  329. package/web-dist/assets/noto-sans-sc-109-wght-normal-CnjNbNmw.woff2 +0 -0
  330. package/web-dist/assets/noto-sans-sc-110-wght-normal-D2JBr045.woff2 +0 -0
  331. package/web-dist/assets/noto-sans-sc-111-wght-normal-ClFr5QXM.woff2 +0 -0
  332. package/web-dist/assets/noto-sans-sc-112-wght-normal-CiZxJMyY.woff2 +0 -0
  333. package/web-dist/assets/noto-sans-sc-113-wght-normal-OgQXOX6x.woff2 +0 -0
  334. package/web-dist/assets/noto-sans-sc-114-wght-normal-CRH9SDZu.woff2 +0 -0
  335. package/web-dist/assets/noto-sans-sc-115-wght-normal-BN__2iBG.woff2 +0 -0
  336. package/web-dist/assets/noto-sans-sc-116-wght-normal-vdFVzbO2.woff2 +0 -0
  337. package/web-dist/assets/noto-sans-sc-117-wght-normal-Dsz3vkzU.woff2 +0 -0
  338. package/web-dist/assets/noto-sans-sc-118-wght-normal-BPEb0gM9.woff2 +0 -0
  339. package/web-dist/assets/noto-sans-sc-119-wght-normal-BfzSEbFz.woff2 +0 -0
  340. package/web-dist/assets/noto-sans-sc-21-wght-normal-DIu_1ZBI.woff2 +0 -0
  341. package/web-dist/assets/noto-sans-sc-22-wght-normal-VXjdYcT-.woff2 +0 -0
  342. package/web-dist/assets/noto-sans-sc-23-wght-normal-4HrHKhpL.woff2 +0 -0
  343. package/web-dist/assets/noto-sans-sc-24-wght-normal-B58DWgHS.woff2 +0 -0
  344. package/web-dist/assets/noto-sans-sc-25-wght-normal-C3Jm6l7O.woff2 +0 -0
  345. package/web-dist/assets/noto-sans-sc-26-wght-normal-YNOygvr_.woff2 +0 -0
  346. package/web-dist/assets/noto-sans-sc-27-wght-normal-BP2pEGQH.woff2 +0 -0
  347. package/web-dist/assets/noto-sans-sc-28-wght-normal-BWPKDbtH.woff2 +0 -0
  348. package/web-dist/assets/noto-sans-sc-29-wght-normal-45aVmHn_.woff2 +0 -0
  349. package/web-dist/assets/noto-sans-sc-30-wght-normal-B8_s30jZ.woff2 +0 -0
  350. package/web-dist/assets/noto-sans-sc-31-wght-normal-DW0t445S.woff2 +0 -0
  351. package/web-dist/assets/noto-sans-sc-32-wght-normal-ShbWPcei.woff2 +0 -0
  352. package/web-dist/assets/noto-sans-sc-33-wght-normal-BOTZYTjM.woff2 +0 -0
  353. package/web-dist/assets/noto-sans-sc-34-wght-normal-BF1rqDSt.woff2 +0 -0
  354. package/web-dist/assets/noto-sans-sc-35-wght-normal-Bosspiyr.woff2 +0 -0
  355. package/web-dist/assets/noto-sans-sc-36-wght-normal-CtU9CyKw.woff2 +0 -0
  356. package/web-dist/assets/noto-sans-sc-37-wght-normal-ghDiyiuv.woff2 +0 -0
  357. package/web-dist/assets/noto-sans-sc-38-wght-normal-4Nz8k_dt.woff2 +0 -0
  358. package/web-dist/assets/noto-sans-sc-39-wght-normal-Ddtm1XVC.woff2 +0 -0
  359. package/web-dist/assets/noto-sans-sc-4-wght-normal-BRbPMj-C.woff2 +0 -0
  360. package/web-dist/assets/noto-sans-sc-40-wght-normal-BVn4-kgX.woff2 +0 -0
  361. package/web-dist/assets/noto-sans-sc-41-wght-normal-CZqajZnl.woff2 +0 -0
  362. package/web-dist/assets/noto-sans-sc-42-wght-normal-CQ4lY28u.woff2 +0 -0
  363. package/web-dist/assets/noto-sans-sc-43-wght-normal-psppu0d8.woff2 +0 -0
  364. package/web-dist/assets/noto-sans-sc-44-wght-normal-cbKJlTUe.woff2 +0 -0
  365. package/web-dist/assets/noto-sans-sc-45-wght-normal-MKIEVRIC.woff2 +0 -0
  366. package/web-dist/assets/noto-sans-sc-46-wght-normal-CErGc6Mt.woff2 +0 -0
  367. package/web-dist/assets/noto-sans-sc-47-wght-normal-C5Kgg1_m.woff2 +0 -0
  368. package/web-dist/assets/noto-sans-sc-48-wght-normal-DFMjDDY6.woff2 +0 -0
  369. package/web-dist/assets/noto-sans-sc-49-wght-normal-B7l_3BZr.woff2 +0 -0
  370. package/web-dist/assets/noto-sans-sc-5-wght-normal-DI846rD9.woff2 +0 -0
  371. package/web-dist/assets/noto-sans-sc-50-wght-normal-C5KfAmFp.woff2 +0 -0
  372. package/web-dist/assets/noto-sans-sc-51-wght-normal-C2bq6hC8.woff2 +0 -0
  373. package/web-dist/assets/noto-sans-sc-52-wght-normal-P18e_Y0j.woff2 +0 -0
  374. package/web-dist/assets/noto-sans-sc-53-wght-normal-Bgkuo2tF.woff2 +0 -0
  375. package/web-dist/assets/noto-sans-sc-54-wght-normal-DL5lmlUd.woff2 +0 -0
  376. package/web-dist/assets/noto-sans-sc-55-wght-normal-BV_Oy6IF.woff2 +0 -0
  377. package/web-dist/assets/noto-sans-sc-56-wght-normal-B4L7Hj8f.woff2 +0 -0
  378. package/web-dist/assets/noto-sans-sc-57-wght-normal-DU8YBsDj.woff2 +0 -0
  379. package/web-dist/assets/noto-sans-sc-58-wght-normal-CE0BKS9u.woff2 +0 -0
  380. package/web-dist/assets/noto-sans-sc-59-wght-normal-Azv2Ku9_.woff2 +0 -0
  381. package/web-dist/assets/noto-sans-sc-6-wght-normal-ozUCEY9O.woff2 +0 -0
  382. package/web-dist/assets/noto-sans-sc-60-wght-normal-C1lngC61.woff2 +0 -0
  383. package/web-dist/assets/noto-sans-sc-61-wght-normal-BxWkGF5M.woff2 +0 -0
  384. package/web-dist/assets/noto-sans-sc-62-wght-normal-CXXMAq-5.woff2 +0 -0
  385. package/web-dist/assets/noto-sans-sc-63-wght-normal-4La5uKvS.woff2 +0 -0
  386. package/web-dist/assets/noto-sans-sc-64-wght-normal-CbIuD2Eg.woff2 +0 -0
  387. package/web-dist/assets/noto-sans-sc-65-wght-normal-BGqvKda2.woff2 +0 -0
  388. package/web-dist/assets/noto-sans-sc-66-wght-normal-BvNozWOY.woff2 +0 -0
  389. package/web-dist/assets/noto-sans-sc-67-wght-normal-CC-WRBV-.woff2 +0 -0
  390. package/web-dist/assets/noto-sans-sc-68-wght-normal-c0FjfUaj.woff2 +0 -0
  391. package/web-dist/assets/noto-sans-sc-69-wght-normal-D596Jjl2.woff2 +0 -0
  392. package/web-dist/assets/noto-sans-sc-70-wght-normal-ColEcmtJ.woff2 +0 -0
  393. package/web-dist/assets/noto-sans-sc-71-wght-normal-ChZfXpdg.woff2 +0 -0
  394. package/web-dist/assets/noto-sans-sc-72-wght-normal-D1VyfEG3.woff2 +0 -0
  395. package/web-dist/assets/noto-sans-sc-73-wght-normal-DwSJRYPJ.woff2 +0 -0
  396. package/web-dist/assets/noto-sans-sc-74-wght-normal-Cte7o1QG.woff2 +0 -0
  397. package/web-dist/assets/noto-sans-sc-75-wght-normal-B0qL41rF.woff2 +0 -0
  398. package/web-dist/assets/noto-sans-sc-76-wght-normal-BPLMO_2x.woff2 +0 -0
  399. package/web-dist/assets/noto-sans-sc-77-wght-normal-Dkbi3pye.woff2 +0 -0
  400. package/web-dist/assets/noto-sans-sc-78-wght-normal-BFUXeSw6.woff2 +0 -0
  401. package/web-dist/assets/noto-sans-sc-79-wght-normal-DoJG4UTB.woff2 +0 -0
  402. package/web-dist/assets/noto-sans-sc-80-wght-normal-BEFypWOO.woff2 +0 -0
  403. package/web-dist/assets/noto-sans-sc-81-wght-normal-ed_TZlfo.woff2 +0 -0
  404. package/web-dist/assets/noto-sans-sc-82-wght-normal-DcxfR5OJ.woff2 +0 -0
  405. package/web-dist/assets/noto-sans-sc-83-wght-normal-C9UjAcMM.woff2 +0 -0
  406. package/web-dist/assets/noto-sans-sc-84-wght-normal-C7NxT478.woff2 +0 -0
  407. package/web-dist/assets/noto-sans-sc-85-wght-normal-DBcDBu1n.woff2 +0 -0
  408. package/web-dist/assets/noto-sans-sc-86-wght-normal-CLJIoPpl.woff2 +0 -0
  409. package/web-dist/assets/noto-sans-sc-87-wght-normal-DYfJ-vGE.woff2 +0 -0
  410. package/web-dist/assets/noto-sans-sc-88-wght-normal-ClNDOCGW.woff2 +0 -0
  411. package/web-dist/assets/noto-sans-sc-89-wght-normal-IQU_KQA8.woff2 +0 -0
  412. package/web-dist/assets/noto-sans-sc-90-wght-normal-BWcrRNoG.woff2 +0 -0
  413. package/web-dist/assets/noto-sans-sc-91-wght-normal-CGekvDdH.woff2 +0 -0
  414. package/web-dist/assets/noto-sans-sc-97-wght-normal-BsBHkXi3.woff2 +0 -0
  415. package/web-dist/assets/noto-sans-sc-98-wght-normal-BZqSA1r_.woff2 +0 -0
  416. package/web-dist/assets/noto-sans-sc-99-wght-normal-Q_IptJM5.woff2 +0 -0
  417. package/web-dist/assets/noto-sans-sc-cyrillic-wght-normal-CRA5_Pf1.woff2 +0 -0
  418. package/web-dist/assets/noto-sans-sc-latin-ext-wght-normal-CqPqLCfe.woff2 +0 -0
  419. package/web-dist/assets/noto-sans-sc-latin-wght-normal-DYAKOyvl.woff2 +0 -0
  420. package/web-dist/assets/noto-sans-sc-vietnamese-wght-normal-y5SU35Rl.woff2 +0 -0
  421. package/web-dist/assets/ordinal-Cboi1Yqb.js +1 -0
  422. package/web-dist/assets/pegDiagram-XKGWAZYB-CLEM1SDU.js +1 -0
  423. package/web-dist/assets/php-CNeTOyEV.js +1 -0
  424. package/web-dist/assets/pieDiagram-E7YTZNPT-B__g6eF0.js +39 -0
  425. package/web-dist/assets/python-B6Ihcp-E.js +1 -0
  426. package/web-dist/assets/quadrantDiagram-AXDQQJYC-C7VQ2LMY.js +7 -0
  427. package/web-dist/assets/railroadDiagram-O6MQD6OU-eWNnzjwS.js +1 -0
  428. package/web-dist/assets/requirementDiagram-BXWQKSXE-Bi5qeD4b.js +84 -0
  429. package/web-dist/assets/ruby-CYiNE6ps.js +1 -0
  430. package/web-dist/assets/rust-CxuBE0J8.js +1 -0
  431. package/web-dist/assets/sankeyDiagram-P5KCCOFB-DG1VOpXX.js +40 -0
  432. package/web-dist/assets/sequenceDiagram-WJ2MYXX4-Fhkw73Th.js +162 -0
  433. package/web-dist/assets/shellscript-DgJyDXW6.js +1 -0
  434. package/web-dist/assets/sizeCapture-INFHLROL-D9E_17SF.js +1 -0
  435. package/web-dist/assets/sql-Dq2MiB0T.js +1 -0
  436. package/web-dist/assets/stateDiagram-D77RDMKH-Cs5Y0xhW.js +1 -0
  437. package/web-dist/assets/stateDiagram-v2-MP3YSRHH-CEM51fAf.js +1 -0
  438. package/web-dist/assets/swimlanes-42K2YHIH-t-EocvKZ.js +1 -0
  439. package/web-dist/assets/swimlanesDiagram-VR7AAH4N-BrR66vrK.js +8 -0
  440. package/web-dist/assets/timeline-definition-24CTP7MA-CozGCxuA.js +120 -0
  441. package/web-dist/assets/toml-Ms459DBw.js +1 -0
  442. package/web-dist/assets/tsx-D6116Ycy.js +1 -0
  443. package/web-dist/assets/typescript-BqvgUolh.js +1 -0
  444. package/web-dist/assets/vennDiagram-4TSXK5OY-ewU8ycSa.js +34 -0
  445. package/web-dist/assets/wardleyDiagram-VM6X3IG4-DuAhDu-0.js +78 -0
  446. package/web-dist/assets/xml-BkAJuBCc.js +1 -0
  447. package/web-dist/assets/{xterm-DKcY6q-I.js → xterm-v5e56GC9.js} +1 -1
  448. package/web-dist/assets/xychartDiagram-S5SC5T6Z-BxGuZO23.js +7 -0
  449. package/web-dist/assets/yaml-Bopit2L3.js +1 -0
  450. package/web-dist/fonts-licenses/ibm-plex-sans-condensed.txt +93 -0
  451. package/web-dist/fonts-licenses/ibm-plex-sans.txt +93 -0
  452. package/web-dist/fonts-licenses/jetbrains-mono.txt +93 -0
  453. package/web-dist/fonts-licenses/misans.txt +119 -0
  454. package/web-dist/fonts-licenses/mona-sans.txt +93 -0
  455. package/web-dist/fonts-licenses/noto-sans-sc.txt +93 -0
  456. package/web-dist/index.html +18 -4
  457. package/web-dist/workflow-ui.css +261 -0
  458. package/dist/chunk-4SXGU7RO.js +0 -50
  459. package/dist/chunk-4SXGU7RO.js.map +0 -1
  460. package/dist/chunk-ADZJYDNC.js +0 -421
  461. package/dist/chunk-ADZJYDNC.js.map +0 -1
  462. package/dist/chunk-HOS3W3UP.js.map +0 -1
  463. package/dist/chunk-Q65VPAQS.js.map +0 -1
  464. package/dist/chunk-TTGGJDNA.js +0 -14
  465. package/dist/chunk-TTGGJDNA.js.map +0 -1
  466. package/dist/extension/index.d.ts +0 -212
  467. package/web-dist/assets/index-Bm9n7ZV-.js +0 -457
  468. package/web-dist/assets/index-DR4PrRzS.css +0 -1
  469. /package/dist/{extension/index.js.map → chunk-B5IP37ZQ.js.map} +0 -0
  470. /package/dist/{extension → plugin}/index.js +0 -0
@@ -1,8 +1,18 @@
1
+ import {
2
+ HttpError
3
+ } from "./chunk-Q4ON2L6E.js";
1
4
  import {
2
5
  sessionTokenHash
3
- } from "./chunk-HOS3W3UP.js";
6
+ } from "./chunk-TOOTEEM4.js";
7
+ import {
8
+ __decorateElement,
9
+ __decoratorStart,
10
+ __publicField,
11
+ __runInitializers
12
+ } from "./chunk-B5IP37ZQ.js";
4
13
 
5
14
  // src/auth/password.ts
15
+ import { Component, Interface } from "@prismshadow/penguin-core/kernel";
6
16
  import { randomBytes, scrypt, timingSafeEqual } from "crypto";
7
17
  var SCRYPT_COST = 16384;
8
18
  var SCRYPT_R = 8;
@@ -29,30 +39,50 @@ async function hashPassword(password, cost = SCRYPT_COST) {
29
39
  key.toString("base64")
30
40
  ].join("$");
31
41
  }
32
- async function verifyPassword(password, stored) {
42
+ async function checkPassword(password, stored) {
33
43
  const parts = stored.split("$");
34
- if (parts.length !== 6 || parts[0] !== "scrypt") return false;
44
+ if (parts.length !== 6 || parts[0] !== "scrypt") return "unverifiable";
35
45
  const n = Number(parts[1]);
36
46
  const r = Number(parts[2]);
37
47
  const p = Number(parts[3]);
38
- if (!Number.isInteger(n) || !Number.isInteger(r) || !Number.isInteger(p)) return false;
39
- let salt;
40
- let expected;
41
- try {
42
- salt = Buffer.from(parts[4], "base64");
43
- expected = Buffer.from(parts[5], "base64");
44
- } catch {
45
- return false;
46
- }
47
- if (salt.length === 0 || expected.length === 0) return false;
48
+ if (!Number.isInteger(n) || !Number.isInteger(r) || !Number.isInteger(p)) return "unverifiable";
49
+ const salt = Buffer.from(parts[4], "base64");
50
+ const expected = Buffer.from(parts[5], "base64");
51
+ if (salt.length === 0 || expected.length === 0) return "unverifiable";
48
52
  let actual;
49
53
  try {
50
54
  actual = await scryptAsync(password, salt, expected.length, n, r, p);
51
55
  } catch {
52
- return false;
56
+ return "unverifiable";
53
57
  }
54
- return actual.length === expected.length && timingSafeEqual(actual, expected);
58
+ return timingSafeEqual(actual, expected) ? "match" : "mismatch";
59
+ }
60
+ async function verifyPassword(password, stored) {
61
+ return await checkPassword(password, stored) === "match";
62
+ }
63
+ async function verifyAccountPassword(password, stored, dummyHash, check = checkPassword) {
64
+ const outcome = stored === null ? "unverifiable" : await check(password, stored);
65
+ if (outcome !== "unverifiable") return outcome === "match";
66
+ await check(password, await dummyHash());
67
+ return false;
55
68
  }
69
+ var _PasswordHasher_decorators, _init;
70
+ _PasswordHasher_decorators = [Interface()];
71
+ var PasswordHasher = class {
72
+ };
73
+ _init = __decoratorStart(null);
74
+ PasswordHasher = __decorateElement(_init, 0, "PasswordHasher", _PasswordHasher_decorators, PasswordHasher);
75
+ __runInitializers(_init, 1, PasswordHasher);
76
+ var _ScryptHasher_decorators, _init2;
77
+ _ScryptHasher_decorators = [Component()];
78
+ var ScryptHasher = class {
79
+ hash(password) {
80
+ return hashPassword(password, SCRYPT_COST);
81
+ }
82
+ };
83
+ _init2 = __decoratorStart(null);
84
+ ScryptHasher = __decorateElement(_init2, 0, "ScryptHasher", _ScryptHasher_decorators, ScryptHasher);
85
+ __runInitializers(_init2, 1, ScryptHasher);
56
86
 
57
87
  // src/auth/service.ts
58
88
  import { randomBytes as randomBytes3 } from "crypto";
@@ -83,40 +113,8 @@ function tokensEqual(a, b) {
83
113
  return timingSafeEqual2(digest(a), digest(b));
84
114
  }
85
115
 
86
- // src/http/errors.ts
87
- var HttpError = class extends Error {
88
- constructor(status, code, message) {
89
- super(message);
90
- this.status = status;
91
- this.code = code;
92
- this.name = "HttpError";
93
- }
94
- status;
95
- code;
96
- };
97
- function errorBody(code, message) {
98
- return { error: { code, message } };
99
- }
100
- function isMissingCredential(err) {
101
- const message = err instanceof Error ? err.message : String(err);
102
- return /missing credentials|api[_ ]?key/i.test(message);
103
- }
104
- function modelCredentialMissing(modelId) {
105
- return new HttpError(
106
- 400,
107
- "model_credential_missing",
108
- `Model ${modelId} has no API key yet. Configure it on the Models page first.`
109
- );
110
- }
111
- function handleError(err, c) {
112
- if (err instanceof HttpError) {
113
- return c.json(errorBody(err.code, err.message), err.status);
114
- }
115
- console.error(`[server] Unhandled exception: ${err.stack ?? err.message}`);
116
- return c.json(errorBody("internal", "Internal server error."), 500);
117
- }
118
-
119
116
  // src/auth/service.ts
117
+ import { Component as Component2, Use, Interface as Interface2 } from "@prismshadow/penguin-core/kernel";
120
118
  var MIN_PASSWORD_LENGTH = 8;
121
119
  var ADMIN_USER_ID = "admin";
122
120
  var LOGIN_FREE_ATTEMPTS = 5;
@@ -132,22 +130,40 @@ function toUserInfo(row) {
132
130
  userId: row.userId,
133
131
  isAdmin: row.isAdmin,
134
132
  passwordIsInitial: row.passwordIsInitial,
133
+ ...row.displayName !== null ? { displayName: row.displayName } : {},
134
+ ...row.avatar !== null ? { avatar: row.avatar } : {},
135
135
  createdAt: row.createdAt
136
136
  };
137
137
  }
138
+ var _hasher_dec, _clock_dec, _config_dec, _provisioner_dec, _state_dec, _authSessions_dec, _users_dec, _AuthService_decorators, _init3;
139
+ _AuthService_decorators = [Component2()], _users_dec = [Use()], _authSessions_dec = [Use()], _state_dec = [Use()], _provisioner_dec = [Use()], _config_dec = [Use()], _clock_dec = [Use()], _hasher_dec = [Use()];
138
140
  var AuthService = class {
139
- constructor(deps) {
140
- this.deps = deps;
141
- this.now = deps.now ?? (() => /* @__PURE__ */ new Date());
142
- this.hashCost = deps.passwordHashCost ?? SCRYPT_COST;
143
- this.deps.authSessions.deleteExpired(this.now().toISOString());
141
+ constructor() {
142
+ __publicField(this, "users", __runInitializers(_init3, 8, this)), __runInitializers(_init3, 11, this);
143
+ __publicField(this, "authSessions", __runInitializers(_init3, 12, this)), __runInitializers(_init3, 15, this);
144
+ __publicField(this, "state", __runInitializers(_init3, 16, this)), __runInitializers(_init3, 19, this);
145
+ __publicField(this, "provisioner", __runInitializers(_init3, 20, this)), __runInitializers(_init3, 23, this);
146
+ __publicField(this, "config", __runInitializers(_init3, 24, this)), __runInitializers(_init3, 27, this);
147
+ __publicField(this, "clock", __runInitializers(_init3, 28, this)), __runInitializers(_init3, 31, this);
148
+ __publicField(this, "hasher", __runInitializers(_init3, 32, this)), __runInitializers(_init3, 35, this);
149
+ /** Consecutive login failures per userId (see the throttling comment on the constants). */
150
+ __publicField(this, "loginFailures", /* @__PURE__ */ new Map());
151
+ /** Cache for loginDummyHash. */
152
+ __publicField(this, "dummyHash", null);
144
153
  }
145
- deps;
146
- now;
147
- hashCost;
148
154
  /** Session lifetime, for the cookie that must expire WITH the session, not before it. */
149
155
  get sessionTtlMs() {
150
- return this.deps.sessionTtlMs;
156
+ return this.config.authSessionTtlMs;
157
+ }
158
+ get sessionRenewMs() {
159
+ return this.config.authSessionRenewMs;
160
+ }
161
+ /** Fixed initial password for the seeded admin; null generates a random one at seed time. */
162
+ get seedAdminPassword() {
163
+ return this.config.seedAdminPassword;
164
+ }
165
+ setup() {
166
+ this.authSessions.deleteExpired(this.clock.now().toISOString());
151
167
  }
152
168
  /**
153
169
  * Null once the server is claimed, so the only setup session that exists is a printed one.
@@ -156,11 +172,11 @@ var AuthService = class {
156
172
  */
157
173
  mintFirstLogin() {
158
174
  if (!this.adminPasswordIsInitial()) return null;
159
- if (this.deps.state.firstLoginToken !== null && this.authenticateWithMeta(this.deps.state.firstLoginToken) === null) {
160
- this.deps.state.firstLoginToken = null;
175
+ if (this.state.firstLoginToken !== null && this.authenticateWithMeta(this.state.firstLoginToken) === null) {
176
+ this.state.firstLoginToken = null;
161
177
  }
162
- this.deps.state.firstLoginToken ??= this.issueSession(ADMIN_USER_ID, "setup");
163
- return this.deps.state.firstLoginToken;
178
+ this.state.firstLoginToken ??= this.issueSession(ADMIN_USER_ID, "setup");
179
+ return this.state.firstLoginToken;
164
180
  }
165
181
  /**
166
182
  * For the startup notice's pinned-seed gate (index.ts): a pin usually means the operator
@@ -168,7 +184,7 @@ var AuthService = class {
168
184
  * that or the rescue link stays suppressed.
169
185
  */
170
186
  async adminPasswordIs(password) {
171
- const row = this.deps.users.findById(ADMIN_USER_ID);
187
+ const row = this.users.findById(ADMIN_USER_ID);
172
188
  return row !== null && await verifyPassword(password, row.passwordHash);
173
189
  }
174
190
  /**
@@ -177,8 +193,8 @@ var AuthService = class {
177
193
  * the server retries on next startup.
178
194
  */
179
195
  async seedAdmin() {
180
- if (this.deps.users.count() > 0) return;
181
- const password = this.deps.seedAdminPassword ?? generateInitialAdminPassword();
196
+ if (this.users.count() > 0) return;
197
+ const password = this.seedAdminPassword ?? generateInitialAdminPassword();
182
198
  if (password.length < MIN_PASSWORD_LENGTH) {
183
199
  throw new Error(
184
200
  `PENGUIN_SEED_ADMIN_PASSWORD must be at least ${MIN_PASSWORD_LENGTH} characters.`
@@ -186,16 +202,18 @@ var AuthService = class {
186
202
  }
187
203
  const user = {
188
204
  userId: ADMIN_USER_ID,
189
- passwordHash: await hashPassword(password, this.hashCost),
205
+ passwordHash: await this.hasher.hash(password),
190
206
  isAdmin: true,
191
207
  passwordIsInitial: true,
192
- createdAt: this.now().toISOString()
208
+ displayName: null,
209
+ avatar: null,
210
+ createdAt: this.clock.now().toISOString()
193
211
  };
194
- this.deps.users.insert(user);
212
+ this.users.insert(user);
195
213
  try {
196
- await this.deps.provisionInitialProject(user, true);
214
+ await this.provisioner.provisionInitialProject(user, true);
197
215
  } catch (err) {
198
- this.deps.users.delete(user.userId);
216
+ this.users.delete(user.userId);
199
217
  throw err;
200
218
  }
201
219
  }
@@ -205,16 +223,24 @@ var AuthService = class {
205
223
  * because a prefetching browser would burn it before its reader clicked.
206
224
  */
207
225
  redeemFirstLogin(given) {
208
- const expected = this.deps.state.firstLoginToken;
226
+ const expected = this.state.firstLoginToken;
209
227
  if (expected === null || given === "" || !tokensEqual(given, expected)) return null;
210
228
  return this.authenticateWithMeta(expected) === null ? null : expected;
211
229
  }
212
230
  /** Whether the built-in admin still runs on its initial password (gates the first-login link). */
213
231
  adminPasswordIsInitial() {
214
- return this.deps.users.findById(ADMIN_USER_ID)?.passwordIsInitial === true;
232
+ return this.users.findById(ADMIN_USER_ID)?.passwordIsInitial === true;
233
+ }
234
+ /**
235
+ * The hash a sign-in with no account to check is verified against (verifyAccountPassword), so
236
+ * it costs what a wrong password costs. Made by this server's own hasher, hence at the cost its
237
+ * real hashes carry, from a random password nobody holds; computed on the first such sign-in
238
+ * and kept.
239
+ */
240
+ async loginDummyHash() {
241
+ this.dummyHash ??= await this.hasher.hash(randomBytes3(18).toString("base64url"));
242
+ return this.dummyHash;
215
243
  }
216
- /** Consecutive login failures per userId (see the throttling comment on the constants). */
217
- loginFailures = /* @__PURE__ */ new Map();
218
244
  /** The wait imposed after `failures` consecutive failures (0 while within the free attempts). */
219
245
  loginDelayMs(failures) {
220
246
  const excess = failures - LOGIN_FREE_ATTEMPTS;
@@ -222,7 +248,7 @@ var AuthService = class {
222
248
  return Math.min(LOGIN_BACKOFF_START_MS * 2 ** (excess - 1), LOGIN_BACKOFF_CAP_MS);
223
249
  }
224
250
  async login(userId, password) {
225
- const nowMs = this.now().getTime();
251
+ const nowMs = this.clock.now().getTime();
226
252
  for (const [key, entry] of this.loginFailures) {
227
253
  if (nowMs - entry.lastFailureAt > LOGIN_FAILURE_IDLE_MS) this.loginFailures.delete(key);
228
254
  }
@@ -237,26 +263,40 @@ var AuthService = class {
237
263
  );
238
264
  }
239
265
  }
240
- const row = this.deps.users.findById(userId);
241
- const ok = row !== null && await verifyPassword(password, row.passwordHash);
266
+ const row = this.users.findById(userId);
267
+ const ok = await verifyAccountPassword(
268
+ password,
269
+ row?.passwordHash ?? null,
270
+ () => this.loginDummyHash()
271
+ );
242
272
  if (!row || !ok) {
243
273
  this.loginFailures.set(userId, {
244
274
  failures: (failed?.failures ?? 0) + 1,
245
- lastFailureAt: this.now().getTime()
275
+ lastFailureAt: this.clock.now().getTime()
246
276
  });
247
277
  throw new HttpError(401, "invalid_credentials", "Incorrect username or password.");
248
278
  }
249
279
  this.loginFailures.delete(userId);
250
- this.deps.authSessions.deleteExpired(this.now().toISOString());
280
+ this.authSessions.deleteExpired(this.clock.now().toISOString());
251
281
  return { user: toUserInfo(row), token: this.issueSession(row.userId, "password") };
252
282
  }
283
+ /**
284
+ * Whether a user is an admin, by id — for a caller that has a user's NAME rather than an
285
+ * authenticated request: the terminal relay reads the owner out of a pty reference the
286
+ * runtime has already matched against the signed-in user (machines/terminal-relay.ts), and
287
+ * what is left to decide is whether that user may reach machines at all. Unknown users are
288
+ * not admins.
289
+ */
290
+ isAdmin(userId) {
291
+ return this.users.findById(userId)?.isAdmin === true;
292
+ }
253
293
  /**
254
294
  * Desktop-mode sign-in: an admin session with no password check — the claim route already
255
295
  * redeemed the shell's one-shot token, which is the credential here. Throws only on a
256
296
  * broken deployment (seeding runs before the route exists).
257
297
  */
258
298
  loginDesktop() {
259
- const row = this.deps.users.findById(ADMIN_USER_ID);
299
+ const row = this.users.findById(ADMIN_USER_ID);
260
300
  if (!row) {
261
301
  throw new HttpError(500, "internal", "Built-in admin has not been seeded.");
262
302
  }
@@ -264,7 +304,7 @@ var AuthService = class {
264
304
  }
265
305
  /** Self password change (user settings): validates the old password first; the current session stays valid. */
266
306
  async changePassword(userId, oldPassword, newPassword) {
267
- const row = this.deps.users.findById(userId);
307
+ const row = this.users.findById(userId);
268
308
  if (!row || !await verifyPassword(oldPassword, row.passwordHash)) {
269
309
  throw new HttpError(400, "password_mismatch", "Current password is incorrect.");
270
310
  }
@@ -282,16 +322,16 @@ var AuthService = class {
282
322
  if (newPassword.length < MIN_PASSWORD_LENGTH) {
283
323
  throw new HttpError(400, "invalid_password", "Password must be at least 8 characters.");
284
324
  }
285
- this.deps.users.updatePassword(userId, await hashPassword(newPassword, this.hashCost), false);
325
+ this.users.updatePassword(userId, await this.hasher.hash(newPassword), false);
286
326
  this.loginFailures.delete(userId);
287
327
  if (userId === ADMIN_USER_ID) {
288
- this.deps.authSessions.deleteByUserAndVia(userId, "setup");
289
- this.deps.state.firstLoginToken = null;
328
+ this.authSessions.deleteByUserAndVia(userId, "setup");
329
+ this.state.firstLoginToken = null;
290
330
  }
291
331
  }
292
332
  /** Ends a session: the row is the session, so logout deletes it. Unknown token is a no-op. */
293
333
  logout(token) {
294
- this.deps.authSessions.delete(sessionTokenHash(token));
334
+ this.authSessions.delete(sessionTokenHash(token));
295
335
  }
296
336
  /**
297
337
  * The current boot's local API token (what control-env injection hands to tool
@@ -300,7 +340,7 @@ var AuthService = class {
300
340
  * outlive the App a push replaces (auth/runtime-state.ts).
301
341
  */
302
342
  localApiToken() {
303
- return this.deps.state.apiToken;
343
+ return this.state.apiToken;
304
344
  }
305
345
  /**
306
346
  * Validates a Bearer token against the boot's local API token (constant-time compare):
@@ -309,10 +349,10 @@ var AuthService = class {
309
349
  * null on mismatch, when no token was minted, or when the admin row is missing.
310
350
  */
311
351
  authenticateApiToken(token) {
312
- const apiToken = this.deps.state.apiToken;
352
+ const apiToken = this.state.apiToken;
313
353
  if (apiToken === null || token.length === 0) return null;
314
354
  if (!tokensEqual(token, apiToken)) return null;
315
- const user = this.deps.users.findById(ADMIN_USER_ID);
355
+ const user = this.users.findById(ADMIN_USER_ID);
316
356
  return user === null ? null : { user, via: "token" };
317
357
  }
318
358
  /**
@@ -323,52 +363,76 @@ var AuthService = class {
323
363
  */
324
364
  authenticateWithMeta(token) {
325
365
  const tokenHash = sessionTokenHash(token);
326
- const session = this.deps.authSessions.findByTokenHash(tokenHash);
366
+ const session = this.authSessions.findByTokenHash(tokenHash);
327
367
  if (!session) return null;
328
- const now = this.now();
368
+ const now = this.clock.now();
329
369
  const expiresAt = Date.parse(session.expiresAt);
330
370
  if (expiresAt <= now.getTime()) {
331
- this.deps.authSessions.delete(tokenHash);
371
+ this.authSessions.delete(tokenHash);
332
372
  return null;
333
373
  }
334
- const user = this.deps.users.findById(session.userId);
374
+ const user = this.users.findById(session.userId);
335
375
  if (!user) return null;
336
- const renewable = expiresAt - Date.parse(session.createdAt) >= this.deps.sessionRenewMs;
376
+ const renewable = expiresAt - Date.parse(session.createdAt) >= this.sessionRenewMs;
337
377
  let renewed = false;
338
- if (renewable && expiresAt - now.getTime() < this.deps.sessionRenewMs) {
339
- this.deps.authSessions.touch(
340
- tokenHash,
341
- new Date(now.getTime() + this.deps.sessionTtlMs).toISOString()
342
- );
378
+ if (renewable && expiresAt - now.getTime() < this.sessionRenewMs) {
379
+ this.authSessions.touch(tokenHash, new Date(now.getTime() + this.sessionTtlMs).toISOString());
343
380
  renewed = true;
344
381
  }
345
382
  const via = session.via === "desktop" ? "desktop" : session.via === "setup" ? "setup" : "password";
346
383
  return { user, via, renewed };
347
384
  }
385
+ /**
386
+ * Whether the session behind a cookie token still exists and has not expired — the same
387
+ * two facts {@link authenticateWithMeta} establishes, without its sliding renewal or its
388
+ * user lookup. A connection that outlives the request that opened it has to re-ask
389
+ * periodically (the SSE heartbeat does, once per beat), and asking through the renewing
390
+ * path would top the expiry up every time: a window nobody has touched since last week
391
+ * would stay signed in purely because it is still connected.
392
+ */
393
+ sessionIsLive(token) {
394
+ const session = this.authSessions.findByTokenHash(sessionTokenHash(token));
395
+ if (!session) return false;
396
+ return Date.parse(session.expiresAt) > this.clock.now().getTime();
397
+ }
348
398
  issueSession(userId, via) {
349
- return this.deps.authSessions.issue({
399
+ return this.authSessions.issue({
350
400
  userId,
351
401
  via,
352
- now: this.now(),
353
- ttlMs: this.deps.sessionTtlMs
402
+ now: this.clock.now(),
403
+ ttlMs: this.sessionTtlMs
354
404
  }).token;
355
405
  }
356
406
  };
407
+ _init3 = __decoratorStart(null);
408
+ __decorateElement(_init3, 5, "users", _users_dec, AuthService);
409
+ __decorateElement(_init3, 5, "authSessions", _authSessions_dec, AuthService);
410
+ __decorateElement(_init3, 5, "state", _state_dec, AuthService);
411
+ __decorateElement(_init3, 5, "provisioner", _provisioner_dec, AuthService);
412
+ __decorateElement(_init3, 5, "config", _config_dec, AuthService);
413
+ __decorateElement(_init3, 5, "clock", _clock_dec, AuthService);
414
+ __decorateElement(_init3, 5, "hasher", _hasher_dec, AuthService);
415
+ AuthService = __decorateElement(_init3, 0, "AuthService", _AuthService_decorators, AuthService);
416
+ __runInitializers(_init3, 1, AuthService);
417
+ var _InitialProjectProvisioner_decorators, _init4;
418
+ _InitialProjectProvisioner_decorators = [Interface2()];
419
+ var InitialProjectProvisioner = class {
420
+ };
421
+ _init4 = __decoratorStart(null);
422
+ InitialProjectProvisioner = __decorateElement(_init4, 0, "InitialProjectProvisioner", _InitialProjectProvisioner_decorators, InitialProjectProvisioner);
423
+ __runInitializers(_init4, 1, InitialProjectProvisioner);
357
424
 
358
425
  export {
359
- HttpError,
360
- errorBody,
361
- isMissingCredential,
362
- modelCredentialMissing,
363
- handleError,
364
426
  mintApiToken,
365
427
  storeApiToken,
366
- SCRYPT_COST,
367
428
  hashPassword,
429
+ PasswordHasher,
430
+ ScryptHasher,
368
431
  MIN_PASSWORD_LENGTH,
369
432
  ADMIN_USER_ID,
370
433
  generateInitialAdminPassword,
371
434
  toUserInfo,
372
- AuthService
435
+ AuthService,
436
+ InitialProjectProvisioner
373
437
  };
374
- //# sourceMappingURL=chunk-Q65VPAQS.js.map
438
+ //# sourceMappingURL=chunk-5Z4UCHDB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/auth/password.ts","../src/auth/service.ts","../src/auth/api-token.ts"],"sourcesContent":["import { Component, Interface } from \"@prismshadow/penguin-core/kernel\";\n/**\n * Password hashing (slow-hash storage).\n *\n * Uses node:crypto's scrypt (built-in, no extra dependency, meets the same\n * slow-hash requirement as bcrypt/argon2). Storage format:\n * `scrypt$N$r$p$<salt b64>$<hash b64>` — parameters are stored alongside the hash,\n * so old hashes remain verifiable after future parameter tuning; comparison uses\n * timingSafeEqual to guard against timing side-channels, and a sign-in for an account\n * that does not exist costs the same derivation as a wrong password\n * (verifyAccountPassword).\n */\nimport { randomBytes, scrypt, timingSafeEqual } from \"node:crypto\";\n\n/**\n * Work factor for new hashes. `hashPassword` takes it as a defaulted argument so the server's\n * own test suite can hash at a token cost: almost every case there seeds an admin, provisions\n * users and logs them in, and one derivation at this strength costs on the order of 100ms.\n * Nothing on the production path passes the argument, and no configuration reaches it —\n * `buildAppDeps`, which carries the test override, is not part of this package's exports.\n */\nexport const SCRYPT_COST = 16384;\nconst SCRYPT_R = 8;\nconst SCRYPT_P = 1;\nconst SALT_BYTES = 16;\nconst KEY_BYTES = 64;\n\nfunction scryptAsync(\n password: string,\n salt: Buffer,\n keyLen: number,\n n: number,\n r: number,\n p: number,\n): Promise<Buffer> {\n return new Promise((resolve, reject) => {\n scrypt(password, salt, keyLen, { N: n, r, p, maxmem: 128 * 1024 * 1024 }, (err, key) => {\n if (err) reject(err);\n else resolve(key);\n });\n });\n}\n\n/**\n * Generates a password hash in `scrypt$N$r$p$salt$hash` format. `cost` is scrypt's N and\n * is recorded in the hash, so `verifyPassword` re-derives at whatever cost produced the\n * stored string.\n */\nexport async function hashPassword(password: string, cost: number = SCRYPT_COST): Promise<string> {\n const salt = randomBytes(SALT_BYTES);\n const key = await scryptAsync(password, salt, KEY_BYTES, cost, SCRYPT_R, SCRYPT_P);\n return [\n \"scrypt\",\n String(cost),\n String(SCRYPT_R),\n String(SCRYPT_P),\n salt.toString(\"base64\"),\n key.toString(\"base64\"),\n ].join(\"$\");\n}\n\n/**\n * What checking a password against a stored string found. `match` and `mismatch` each cost one\n * scrypt derivation; `unverifiable` — not the `scrypt$N$r$p$salt$hash` format, or parameters\n * scrypt refuses — cost none.\n */\nexport type PasswordCheck = \"match\" | \"mismatch\" | \"unverifiable\";\n\n/** Checks a password against a stored hash. Never throws. */\nexport async function checkPassword(password: string, stored: string): Promise<PasswordCheck> {\n const parts = stored.split(\"$\");\n if (parts.length !== 6 || parts[0] !== \"scrypt\") return \"unverifiable\";\n const n = Number(parts[1]);\n const r = Number(parts[2]);\n const p = Number(parts[3]);\n if (!Number.isInteger(n) || !Number.isInteger(r) || !Number.isInteger(p)) return \"unverifiable\";\n const salt = Buffer.from(parts[4]!, \"base64\");\n const expected = Buffer.from(parts[5]!, \"base64\");\n if (salt.length === 0 || expected.length === 0) return \"unverifiable\";\n let actual: Buffer;\n try {\n actual = await scryptAsync(password, salt, expected.length, n, r, p);\n } catch {\n return \"unverifiable\";\n }\n return timingSafeEqual(actual, expected) ? \"match\" : \"mismatch\";\n}\n\n/** Verifies a password; returns false if the stored string has an invalid format (never throws, so the login path can uniformly treat it as a credential error). */\nexport async function verifyPassword(password: string, stored: string): Promise<boolean> {\n return (await checkPassword(password, stored)) === \"match\";\n}\n\n/**\n * Verifies a sign-in password for an account that may not exist, at the cost a real account's\n * check has. `stored` is the account's hash, or null when there is no such account. When there is\n * nothing to derive against — no account, an empty hash, or one `checkPassword` finds\n * unverifiable — the password is checked against `dummyHash` instead and the result is false, so\n * every call runs exactly one scrypt derivation and how long a failure takes does not tell a\n * missing username from a wrong password. `check` is a parameter so a test can count the\n * derivations.\n */\nexport async function verifyAccountPassword(\n password: string,\n stored: string | null,\n dummyHash: () => Promise<string>,\n check: (password: string, stored: string) => Promise<PasswordCheck> = checkPassword,\n): Promise<boolean> {\n const outcome = stored === null ? \"unverifiable\" : await check(password, stored);\n if (outcome !== \"unverifiable\") return outcome === \"match\";\n await check(password, await dummyHash());\n return false;\n}\n\n/** Hashes the passwords this server writes; a test stands in a cheap one. */\n@Interface()\nexport abstract class PasswordHasher {\n abstract hash(password: string): Promise<string>;\n}\n\n/** scrypt at full strength. */\n@Component()\nexport class ScryptHasher implements PasswordHasher {\n hash(password: string): Promise<string> {\n return hashPassword(password, SCRYPT_COST);\n }\n}\n","/**\n * Auth service: admin seeding / login / logout / password change / session validation.\n *\n * No open registration: an empty users table seeds `admin` with a random password hashed and\n * discarded unseen, claimed through the first-login link; every other user is created by an\n * admin. Sessions are rows in auth_sessions (cookie holds the token, the row its sha256), so\n * they outlive a restart and renew in place.\n */\nimport { randomBytes } from \"node:crypto\";\nimport { tokensEqual } from \"./api-token.js\";\nimport type { UserInfo } from \"../api/types.js\";\nimport { HttpError } from \"../http/errors.js\";\nimport type { UserRow } from \"../db/repos/users.js\";\nimport { sessionTokenHash } from \"../db/repos/auth-sessions.js\";\nimport type { SessionViaValue, AuthSessionsRepo } from \"../db/repos/auth-sessions.js\";\nimport type { AuthRuntimeState } from \"./runtime-state.js\";\nimport { verifyAccountPassword, verifyPassword } from \"./password.js\";\nimport type { PasswordHasher } from \"./password.js\";\nimport { Component, Use, Interface } from \"@prismshadow/penguin-core/kernel\";\nimport type { AuthState, Clock, Config } from \"../hmr/capabilities.js\";\nimport type { Auth, AuthSessions, Users } from \"../mechanisms/identity.js\";\n\nexport const MIN_PASSWORD_LENGTH = 8;\n\n/** Built-in admin user_id. */\nexport const ADMIN_USER_ID = \"admin\";\n\n/**\n * Login throttling, per userId. After LOGIN_FREE_ATTEMPTS failures each attempt waits an\n * exponentially growing delay (1s doubling to a 60s cap), settling at a guess per minute.\n * Kept for nonexistent userIds too, so it is not an account-existence oracle — and neither is\n * the time a failure takes: a nonexistent userId is checked against a dummy hash (loginDummyHash).\n * Deliberately NOT covered: a concurrent burst before the first failure lands, and guesses\n * spread across many accounts.\n */\nconst LOGIN_FREE_ATTEMPTS = 5;\nconst LOGIN_BACKOFF_START_MS = 1000;\nconst LOGIN_BACKOFF_CAP_MS = 60_000;\n/** Failure entries idle longer than this are swept (bounds the map; far above the cap). */\nconst LOGIN_FAILURE_IDLE_MS = 15 * 60_000;\n\n/** Characters of base64url in a seeded password — 18 random bytes, 144 bits. */\nconst SEED_PASSWORD_CHARS = 24;\n\n/**\n * Never read or typed — hashed at once and discarded — which is what lets it be long enough\n * that the login endpoint, reachable the moment the account exists, has no search space.\n */\nexport function generateInitialAdminPassword(): string {\n return randomBytes(SEED_PASSWORD_CHARS).toString(\"base64url\").slice(0, SEED_PASSWORD_CHARS);\n}\n\n/**\n * \"desktop\" and \"setup\" may set a password without the old one (theirs is random and was never\n * shown); desktop-only routes open to \"desktop\" alone. \"token\" is the local API token's Bearer\n * header — per request, never a stored row. Anything else reads as \"password\".\n */\nexport type SessionVia = \"password\" | \"desktop\" | \"setup\" | \"token\";\n\n/** Row -> DTO. The two profile columns are omitted rather than sent as null when unset. */\nexport function toUserInfo(row: UserRow): UserInfo {\n return {\n userId: row.userId,\n isAdmin: row.isAdmin,\n passwordIsInitial: row.passwordIsInitial,\n ...(row.displayName !== null ? { displayName: row.displayName } : {}),\n ...(row.avatar !== null ? { avatar: row.avatar } : {}),\n createdAt: row.createdAt,\n };\n}\n\n@Component()\nexport class AuthService implements Auth {\n @Use() private readonly users!: Users;\n @Use() private readonly authSessions!: AuthSessions;\n /**\n * Process-scoped auth values (runtime-state.ts). Held by the RUNTIME so the link a boot\n * printed survives a platform push; everything else about auth is rebuilt with the App.\n */\n @Use() private readonly state!: AuthState;\n /** Provisions the initial Project at signup — declared at the consumer, below. */\n @Use() private readonly provisioner!: InitialProjectProvisioner;\n @Use() private readonly config!: Config;\n @Use() private readonly clock!: Clock;\n @Use() private readonly hasher!: PasswordHasher;\n /** Session lifetime, for the cookie that must expire WITH the session, not before it. */\n get sessionTtlMs(): number {\n return this.config.authSessionTtlMs;\n }\n private get sessionRenewMs(): number {\n return this.config.authSessionRenewMs;\n }\n /** Fixed initial password for the seeded admin; null generates a random one at seed time. */\n private get seedAdminPassword(): string | null {\n return this.config.seedAdminPassword;\n }\n\n setup(): void {\n this.authSessions.deleteExpired(this.clock.now().toISOString());\n }\n\n /**\n * Null once the server is claimed, so the only setup session that exists is a printed one.\n * On demand rather than in the constructor: seedAdmin() runs after it, so \"claimed?\" has no\n * answer there. A cached link whose row is gone is re-minted, not handed out dead.\n */\n mintFirstLogin(): string | null {\n if (!this.adminPasswordIsInitial()) return null;\n if (\n this.state.firstLoginToken !== null &&\n this.authenticateWithMeta(this.state.firstLoginToken) === null\n ) {\n this.state.firstLoginToken = null;\n }\n this.state.firstLoginToken ??= this.issueSession(ADMIN_USER_ID, \"setup\");\n return this.state.firstLoginToken;\n }\n\n /**\n * For the startup notice's pinned-seed gate (index.ts): a pin usually means the operator\n * knows the password, but an offline reset makes it stale, and the gate must see through\n * that or the rescue link stays suppressed.\n */\n async adminPasswordIs(password: string): Promise<boolean> {\n const row = this.users.findById(ADMIN_USER_ID);\n return row !== null && (await verifyPassword(password, row.passwordHash));\n }\n\n /**\n * Startup seeding (idempotent): creates the built-in admin and adopts default_project when\n * the users table is empty; if the initial Project fails, the user row is rolled back and\n * the server retries on next startup.\n */\n async seedAdmin(): Promise<void> {\n if (this.users.count() > 0) return;\n const password = this.seedAdminPassword ?? generateInitialAdminPassword();\n // A pinned override must meet the same policy as every other password — rejected before\n // any insert, so a configuration typo cannot create a trivially weak privileged account.\n if (password.length < MIN_PASSWORD_LENGTH) {\n throw new Error(\n `PENGUIN_SEED_ADMIN_PASSWORD must be at least ${MIN_PASSWORD_LENGTH} characters.`,\n );\n }\n const user: UserRow = {\n userId: ADMIN_USER_ID,\n passwordHash: await this.hasher.hash(password),\n isAdmin: true,\n passwordIsInitial: true,\n displayName: null,\n avatar: null,\n createdAt: this.clock.now().toISOString(),\n };\n this.users.insert(user);\n try {\n await this.provisioner.provisionInitialProject(user, true);\n } catch (err) {\n this.users.delete(user.userId);\n throw err;\n }\n }\n\n /**\n * Compared against the printed value, not merely verified: a cookie made out of ANY valid\n * token would let one person hand another a link into the sender's account. Not single-use,\n * because a prefetching browser would burn it before its reader clicked.\n */\n redeemFirstLogin(given: string): string | null {\n const expected = this.state.firstLoginToken;\n if (expected === null || given === \"\" || !tokensEqual(given, expected)) return null;\n return this.authenticateWithMeta(expected) === null ? null : expected;\n }\n\n /** Whether the built-in admin still runs on its initial password (gates the first-login link). */\n adminPasswordIsInitial(): boolean {\n return this.users.findById(ADMIN_USER_ID)?.passwordIsInitial === true;\n }\n\n /** Consecutive login failures per userId (see the throttling comment on the constants). */\n private readonly loginFailures = new Map<string, { failures: number; lastFailureAt: number }>();\n\n /** Cache for loginDummyHash. */\n private dummyHash: string | null = null;\n\n /**\n * The hash a sign-in with no account to check is verified against (verifyAccountPassword), so\n * it costs what a wrong password costs. Made by this server's own hasher, hence at the cost its\n * real hashes carry, from a random password nobody holds; computed on the first such sign-in\n * and kept.\n */\n private async loginDummyHash(): Promise<string> {\n this.dummyHash ??= await this.hasher.hash(randomBytes(18).toString(\"base64url\"));\n return this.dummyHash;\n }\n\n /** The wait imposed after `failures` consecutive failures (0 while within the free attempts). */\n private loginDelayMs(failures: number): number {\n const excess = failures - LOGIN_FREE_ATTEMPTS;\n if (excess <= 0) return 0;\n return Math.min(LOGIN_BACKOFF_START_MS * 2 ** (excess - 1), LOGIN_BACKOFF_CAP_MS);\n }\n\n async login(userId: string, password: string): Promise<{ user: UserInfo; token: string }> {\n const nowMs = this.clock.now().getTime();\n for (const [key, entry] of this.loginFailures) {\n if (nowMs - entry.lastFailureAt > LOGIN_FAILURE_IDLE_MS) this.loginFailures.delete(key);\n }\n const failed = this.loginFailures.get(userId);\n if (failed) {\n const readyAt = failed.lastFailureAt + this.loginDelayMs(failed.failures);\n if (nowMs < readyAt) {\n throw new HttpError(\n 429,\n \"too_many_attempts\",\n `Too many failed sign-in attempts. Try again in ${Math.ceil((readyAt - nowMs) / 1000)}s.`,\n );\n }\n }\n const row = this.users.findById(userId);\n // A missing account, or one whose hash cannot be checked, still costs one scrypt\n // derivation, and fails with the same 401 as a wrong password.\n const ok = await verifyAccountPassword(password, row?.passwordHash ?? null, () =>\n this.loginDummyHash(),\n );\n if (!row || !ok) {\n this.loginFailures.set(userId, {\n failures: (failed?.failures ?? 0) + 1,\n lastFailureAt: this.clock.now().getTime(),\n });\n throw new HttpError(401, \"invalid_credentials\", \"Incorrect username or password.\");\n }\n this.loginFailures.delete(userId);\n this.authSessions.deleteExpired(this.clock.now().toISOString());\n return { user: toUserInfo(row), token: this.issueSession(row.userId, \"password\") };\n }\n\n /**\n * Whether a user is an admin, by id — for a caller that has a user's NAME rather than an\n * authenticated request: the terminal relay reads the owner out of a pty reference the\n * runtime has already matched against the signed-in user (machines/terminal-relay.ts), and\n * what is left to decide is whether that user may reach machines at all. Unknown users are\n * not admins.\n */\n isAdmin(userId: string): boolean {\n return this.users.findById(userId)?.isAdmin === true;\n }\n\n /**\n * Desktop-mode sign-in: an admin session with no password check — the claim route already\n * redeemed the shell's one-shot token, which is the credential here. Throws only on a\n * broken deployment (seeding runs before the route exists).\n */\n loginDesktop(): { user: UserInfo; token: string } {\n const row = this.users.findById(ADMIN_USER_ID);\n if (!row) {\n throw new HttpError(500, \"internal\", \"Built-in admin has not been seeded.\");\n }\n return { user: toUserInfo(row), token: this.issueSession(row.userId, \"desktop\") };\n }\n\n /** Self password change (user settings): validates the old password first; the current session stays valid. */\n async changePassword(userId: string, oldPassword: string, newPassword: string): Promise<void> {\n const row = this.users.findById(userId);\n if (!row || !(await verifyPassword(oldPassword, row.passwordHash))) {\n throw new HttpError(400, \"password_mismatch\", \"Current password is incorrect.\");\n }\n await this.setPassword(userId, newPassword);\n }\n\n /** No old-password check; the me route gates which sessions may call this. */\n async setInitialPassword(userId: string, newPassword: string): Promise<void> {\n await this.setPassword(userId, newPassword);\n }\n\n /**\n * Validation comes FIRST, so a rejected password leaves the first-login link alive: burning\n * it on a typo would strand the claimer until a restart.\n */\n private async setPassword(userId: string, newPassword: string): Promise<void> {\n if (newPassword.length < MIN_PASSWORD_LENGTH) {\n throw new HttpError(400, \"invalid_password\", \"Password must be at least 8 characters.\");\n }\n this.users.updatePassword(userId, await this.hasher.hash(newPassword), false);\n // A successful set proves at least what the successful login that resets the counter\n // proves (the old password, or a desktop/setup session), so it resets it too. Without\n // this, anyone spamming the login endpoint holds the backoff window open, and the sign-in\n // that follows a first-login claim (routes/me.ts) would 429 AFTER the password committed —\n // reporting failure for a change that took, with the claimer's setup session already gone.\n this.loginFailures.delete(userId);\n // EVERY first-login session for this account, not just the link this process printed: an\n // earlier boot's link can still be live in a terminal scrollback, and a `setup` session is\n // allowed to change the password without knowing the old one — so one left behind is an\n // account takeover waiting to happen.\n if (userId === ADMIN_USER_ID) {\n this.authSessions.deleteByUserAndVia(userId, \"setup\");\n this.state.firstLoginToken = null;\n }\n }\n\n /** Ends a session: the row is the session, so logout deletes it. Unknown token is a no-op. */\n logout(token: string): void {\n this.authSessions.delete(sessionTokenHash(token));\n }\n\n /**\n * The current boot's local API token (what control-env injection hands to tool\n * subprocesses); null when none was minted. It lives on the runtime state, not on this\n * service: the token was written to `<root>/api-token` by the process, so it must\n * outlive the App a push replaces (auth/runtime-state.ts).\n */\n localApiToken(): string | null {\n return this.state.apiToken;\n }\n\n /**\n * Validates a Bearer token against the boot's local API token (constant-time compare):\n * a match authenticates as the built-in admin — holding the token proves filesystem\n * access to the data root, which is admin authority (see auth/api-token.ts). Returns\n * null on mismatch, when no token was minted, or when the admin row is missing.\n */\n authenticateApiToken(token: string): { user: UserRow; via: SessionVia } | null {\n const apiToken = this.state.apiToken;\n if (apiToken === null || token.length === 0) return null;\n if (!tokensEqual(token, apiToken)) return null;\n const user = this.users.findById(ADMIN_USER_ID);\n return user === null ? null : { user, via: \"token\" };\n }\n\n /**\n * Validates the cookie token. Sliding renewal tops the expiry up IN PLACE, so the cookie\n * value never changes and there is no second identity to revoke. Only a session whose own\n * span reaches the renewal window slides — a one-hour minted token must expire at its hour,\n * not stretch by being used.\n */\n authenticateWithMeta(token: string): { user: UserRow; via: SessionVia; renewed: boolean } | null {\n const tokenHash = sessionTokenHash(token);\n const session = this.authSessions.findByTokenHash(tokenHash);\n if (!session) return null;\n const now = this.clock.now();\n const expiresAt = Date.parse(session.expiresAt);\n if (expiresAt <= now.getTime()) {\n this.authSessions.delete(tokenHash);\n return null;\n }\n const user = this.users.findById(session.userId);\n if (!user) return null;\n const renewable = expiresAt - Date.parse(session.createdAt) >= this.sessionRenewMs;\n let renewed = false;\n if (renewable && expiresAt - now.getTime() < this.sessionRenewMs) {\n this.authSessions.touch(tokenHash, new Date(now.getTime() + this.sessionTtlMs).toISOString());\n renewed = true;\n }\n const via: SessionVia =\n session.via === \"desktop\" ? \"desktop\" : session.via === \"setup\" ? \"setup\" : \"password\";\n return { user, via, renewed };\n }\n\n /**\n * Whether the session behind a cookie token still exists and has not expired — the same\n * two facts {@link authenticateWithMeta} establishes, without its sliding renewal or its\n * user lookup. A connection that outlives the request that opened it has to re-ask\n * periodically (the SSE heartbeat does, once per beat), and asking through the renewing\n * path would top the expiry up every time: a window nobody has touched since last week\n * would stay signed in purely because it is still connected.\n */\n sessionIsLive(token: string): boolean {\n const session = this.authSessions.findByTokenHash(sessionTokenHash(token));\n if (!session) return false;\n return Date.parse(session.expiresAt) > this.clock.now().getTime();\n }\n\n private issueSession(userId: string, via: SessionViaValue): string {\n return this.authSessions.issue({\n userId,\n via,\n now: this.clock.now(),\n ttlMs: this.sessionTtlMs,\n }).token;\n }\n}\n\n/** What signing a new user in needs of project administration — declared at the consumer. */\n@Interface()\nexport abstract class InitialProjectProvisioner {\n abstract provisionInitialProject(user: UserRow, isAdmin: boolean): Promise<void>;\n}\n","/**\n * Local API token (`<root>/api-token`): the machine-local credential behind\n * `Authorization: Bearer`.\n *\n * Minted fresh at every server boot (same recipe as auth-session tokens) and written to\n * the data root with owner-only permissions, so anything that can read the file can call\n * the API as the admin. That equivalence is the authorization model, not an accident:\n * local filesystem access to the data root already IS admin authority — the same rule\n * `penguin server reset-admin-password` stands on (whoever can run it owns web.db\n * anyway) — and agents driving their own harness through the CLI is the product feature\n * this token exists for (server-driven Sessions hand it to tool subprocesses as\n * PENGUIN_API_TOKEN). Rotation per boot bounds the life of any leaked copy to the\n * process that minted it.\n */\nimport { createHash, randomBytes, timingSafeEqual } from \"node:crypto\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nexport function apiTokenPath(root: string): string {\n return path.join(root, \"api-token\");\n}\n\n/** Mints a boot-scoped local API token (the auth-session token recipe). */\nexport function mintApiToken(): string {\n return randomBytes(32).toString(\"base64url\");\n}\n\n/**\n * Persists the boot token (owner-only file, tmp + rename so a concurrent reader never\n * sees a partial write). Best-effort like the initial-password file: an exotic read-only\n * root must not stop the server — local CLI callers then fall back to\n * PENGUIN_API_TOKEN.\n */\nexport function storeApiToken(root: string, token: string): void {\n try {\n fs.mkdirSync(root, { recursive: true });\n const target = apiTokenPath(root);\n const tmp = `${target}.${process.pid}.tmp`;\n fs.writeFileSync(tmp, `${token}\\n`, { mode: 0o600 });\n fs.renameSync(tmp, target);\n } catch {\n // Best-effort: Bearer auth still works for callers holding the token some other way.\n }\n}\n\n/** The stored token, or null when absent/unreadable/empty (shared with the CLI's file fallback). */\nexport function readApiToken(root: string): string | null {\n try {\n const value = fs.readFileSync(apiTokenPath(root), \"utf8\").trim();\n return value === \"\" ? null : value;\n } catch {\n return null;\n }\n}\n\n/**\n * Constant-time equality for token checks: both sides are reduced to fixed-size sha256\n * digests first, so the comparison's timing depends on neither the content nor the\n * length of an attacker-supplied value.\n */\nexport function tokensEqual(a: string, b: string): boolean {\n const digest = (v: string): Buffer => createHash(\"sha256\").update(v).digest();\n return timingSafeEqual(digest(a), digest(b));\n}\n"],"mappings":"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","names":["_init","randomBytes","randomBytes","timingSafeEqual","timingSafeEqual","Component","Interface","randomBytes","_init","Component","Interface"]}
@@ -0,0 +1,56 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : /* @__PURE__ */ Symbol.for("Symbol." + name);
5
+ var __typeError = (msg) => {
6
+ throw TypeError(msg);
7
+ };
8
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
9
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
10
+ var __decoratorStart = (base) => [, , , __create(base?.[__knownSymbol("metadata")] ?? null)];
11
+ var __decoratorStrings = ["class", "method", "getter", "setter", "accessor", "field", "value", "get", "set"];
12
+ var __expectFn = (fn) => fn !== void 0 && typeof fn !== "function" ? __typeError("Function expected") : fn;
13
+ var __decoratorContext = (kind, name, done, metadata, fns) => ({ kind: __decoratorStrings[kind], name, metadata, addInitializer: (fn) => done._ ? __typeError("Already initialized") : fns.push(__expectFn(fn || null)) });
14
+ var __decoratorMetadata = (array, target) => __defNormalProp(target, __knownSymbol("metadata"), array[3]);
15
+ var __runInitializers = (array, flags, self, value) => {
16
+ for (var i = 0, fns = array[flags >> 1], n = fns && fns.length; i < n; i++) flags & 1 ? fns[i].call(self) : value = fns[i].call(self, value);
17
+ return value;
18
+ };
19
+ var __decorateElement = (array, flags, name, decorators, target, extra) => {
20
+ var fn, it, done, ctx, access, k = flags & 7, s = !!(flags & 8), p = !!(flags & 16);
21
+ var j = k > 3 ? array.length + 1 : k ? s ? 1 : 2 : 0, key = __decoratorStrings[k + 5];
22
+ var initializers = k > 3 && (array[j - 1] = []), extraInitializers = array[j] || (array[j] = []);
23
+ var desc = k && (!p && !s && (target = target.prototype), k < 5 && (k > 3 || !p) && __getOwnPropDesc(k < 4 ? target : { get [name]() {
24
+ return __privateGet(this, extra);
25
+ }, set [name](x) {
26
+ return __privateSet(this, extra, x);
27
+ } }, name));
28
+ k ? p && k < 4 && __name(extra, (k > 2 ? "set " : k > 1 ? "get " : "") + name) : __name(target, name);
29
+ for (var i = decorators.length - 1; i >= 0; i--) {
30
+ ctx = __decoratorContext(k, name, done = {}, array[3], extraInitializers);
31
+ if (k) {
32
+ ctx.static = s, ctx.private = p, access = ctx.access = { has: p ? (x) => __privateIn(target, x) : (x) => name in x };
33
+ if (k ^ 3) access.get = p ? (x) => (k ^ 1 ? __privateGet : __privateMethod)(x, target, k ^ 4 ? extra : desc.get) : (x) => x[name];
34
+ if (k > 2) access.set = p ? (x, y) => __privateSet(x, target, y, k ^ 4 ? extra : desc.set) : (x, y) => x[name] = y;
35
+ }
36
+ it = (0, decorators[i])(k ? k < 4 ? p ? extra : desc[key] : k > 4 ? void 0 : { get: desc.get, set: desc.set } : target, ctx), done._ = 1;
37
+ if (k ^ 4 || it === void 0) __expectFn(it) && (k > 4 ? initializers.unshift(it) : k ? p ? extra = it : desc[key] = it : target = it);
38
+ else if (typeof it !== "object" || it === null) __typeError("Object expected");
39
+ else __expectFn(fn = it.get) && (desc.get = fn), __expectFn(fn = it.set) && (desc.set = fn), __expectFn(fn = it.init) && initializers.unshift(fn);
40
+ }
41
+ return k || __decoratorMetadata(array, target), desc && __defProp(target, name, desc), p ? k ^ 4 ? extra : desc : target;
42
+ };
43
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
44
+ var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
45
+ var __privateIn = (member, obj) => Object(obj) !== obj ? __typeError('Cannot use the "in" operator on this value') : member.has(obj);
46
+ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
47
+ var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
48
+ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
49
+
50
+ export {
51
+ __decoratorStart,
52
+ __runInitializers,
53
+ __decorateElement,
54
+ __publicField
55
+ };
56
+ //# sourceMappingURL=chunk-B5IP37ZQ.js.map
@@ -0,0 +1,18 @@
1
+ // src/secret-file.ts
2
+ import fs from "fs";
3
+ function writeSecretFile(filePath, contents) {
4
+ fs.rmSync(filePath, { force: true });
5
+ const flags = fs.constants.O_WRONLY | fs.constants.O_CREAT | fs.constants.O_EXCL | (fs.constants.O_NOFOLLOW ?? 0);
6
+ const fd = fs.openSync(filePath, flags, 384);
7
+ try {
8
+ fs.fchmodSync(fd, 384);
9
+ fs.writeSync(fd, contents);
10
+ } finally {
11
+ fs.closeSync(fd);
12
+ }
13
+ }
14
+
15
+ export {
16
+ writeSecretFile
17
+ };
18
+ //# sourceMappingURL=chunk-HX3WBUYX.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/secret-file.ts"],"sourcesContent":["/**\n * Writes a bearer secret to a 0600 file, refusing to follow a symlink parked at the path:\n * someone who can write the directory but not read the file could otherwise redirect the write\n * into a file they CAN read. Hence unlink + exclusive create, and chmod on the fd rather than\n * the path. Exported as `@prismshadow/penguin-server/secret-file` so the CLI shares it.\n */\nimport fs from \"node:fs\";\n\nexport function writeSecretFile(filePath: string, contents: string): void {\n fs.rmSync(filePath, { force: true });\n const flags =\n fs.constants.O_WRONLY |\n fs.constants.O_CREAT |\n fs.constants.O_EXCL |\n (fs.constants.O_NOFOLLOW ?? 0);\n const fd = fs.openSync(filePath, flags, 0o600);\n try {\n fs.fchmodSync(fd, 0o600);\n fs.writeSync(fd, contents);\n } finally {\n fs.closeSync(fd);\n }\n}\n"],"mappings":";AAMA,OAAO,QAAQ;AAER,SAAS,gBAAgB,UAAkB,UAAwB;AACxE,KAAG,OAAO,UAAU,EAAE,OAAO,KAAK,CAAC;AACnC,QAAM,QACJ,GAAG,UAAU,WACb,GAAG,UAAU,UACb,GAAG,UAAU,UACZ,GAAG,UAAU,cAAc;AAC9B,QAAM,KAAK,GAAG,SAAS,UAAU,OAAO,GAAK;AAC7C,MAAI;AACF,OAAG,WAAW,IAAI,GAAK;AACvB,OAAG,UAAU,IAAI,QAAQ;AAAA,EAC3B,UAAE;AACA,OAAG,UAAU,EAAE;AAAA,EACjB;AACF;","names":[]}
@@ -0,0 +1,19 @@
1
+ // src/api/types.ts
2
+ var MACHINE_PHASES = [
3
+ "build",
4
+ "check",
5
+ "install",
6
+ "handover",
7
+ "restart",
8
+ "connect",
9
+ "sync",
10
+ "stop",
11
+ "remove"
12
+ ];
13
+ var TICKET_SLUG_PATTERN = /^[a-z]+(?:-[a-z]+)*$/;
14
+
15
+ export {
16
+ MACHINE_PHASES,
17
+ TICKET_SLUG_PATTERN
18
+ };
19
+ //# sourceMappingURL=chunk-JKJXQTHH.js.map