studiograph 1.3.48-next.141 → 1.3.48-next.142

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 (259) hide show
  1. package/README.md +13 -9
  2. package/dist/agent/skills/interview/skill.md +0 -15
  3. package/dist/agent/tools/ops-tools.js +30 -23
  4. package/dist/agent/tools/ops-tools.js.map +1 -1
  5. package/dist/cli/commands/admin/audit-workspace.d.ts +23 -0
  6. package/dist/cli/commands/admin/audit-workspace.js +133 -0
  7. package/dist/cli/commands/admin/audit-workspace.js.map +1 -0
  8. package/dist/cli/commands/admin/audit.d.ts +21 -0
  9. package/dist/cli/commands/admin/audit.js +174 -0
  10. package/dist/cli/commands/admin/audit.js.map +1 -0
  11. package/dist/cli/commands/admin/backup.d.ts +54 -0
  12. package/dist/cli/commands/admin/backup.js +207 -0
  13. package/dist/cli/commands/admin/backup.js.map +1 -0
  14. package/dist/cli/commands/admin/folder.d.ts +11 -0
  15. package/dist/cli/commands/admin/folder.js +186 -0
  16. package/dist/cli/commands/admin/folder.js.map +1 -0
  17. package/dist/cli/commands/admin/index.d.ts +16 -0
  18. package/dist/cli/commands/admin/index.js +44 -0
  19. package/dist/cli/commands/admin/index.js.map +1 -0
  20. package/dist/cli/commands/admin/migrate.d.ts +56 -0
  21. package/dist/cli/commands/admin/migrate.js +263 -0
  22. package/dist/cli/commands/admin/migrate.js.map +1 -0
  23. package/dist/cli/commands/admin/restore.d.ts +24 -0
  24. package/dist/cli/commands/admin/restore.js +228 -0
  25. package/dist/cli/commands/admin/restore.js.map +1 -0
  26. package/dist/cli/commands/admin/secrets.d.ts +23 -0
  27. package/dist/cli/commands/admin/secrets.js +256 -0
  28. package/dist/cli/commands/admin/secrets.js.map +1 -0
  29. package/dist/cli/commands/admin/settings.d.ts +28 -0
  30. package/dist/cli/commands/admin/settings.js +284 -0
  31. package/dist/cli/commands/admin/settings.js.map +1 -0
  32. package/dist/cli/commands/admin/token.d.ts +42 -0
  33. package/dist/cli/commands/admin/token.js +126 -0
  34. package/dist/cli/commands/admin/token.js.map +1 -0
  35. package/dist/cli/commands/admin/transfer-ownership.d.ts +15 -0
  36. package/dist/cli/commands/admin/transfer-ownership.js +106 -0
  37. package/dist/cli/commands/admin/transfer-ownership.js.map +1 -0
  38. package/dist/cli/commands/admin/user.d.ts +11 -0
  39. package/dist/cli/commands/admin/user.js +187 -0
  40. package/dist/cli/commands/admin/user.js.map +1 -0
  41. package/dist/cli/commands/clone.js +22 -3
  42. package/dist/cli/commands/clone.js.map +1 -1
  43. package/dist/cli/commands/config.d.ts +23 -107
  44. package/dist/cli/commands/config.js +52 -260
  45. package/dist/cli/commands/config.js.map +1 -1
  46. package/dist/cli/commands/connector.d.ts +10 -13
  47. package/dist/cli/commands/connector.js +16 -58
  48. package/dist/cli/commands/connector.js.map +1 -1
  49. package/dist/cli/commands/deploy.js +17 -17
  50. package/dist/cli/commands/deploy.js.map +1 -1
  51. package/dist/cli/commands/init.js +3 -25
  52. package/dist/cli/commands/init.js.map +1 -1
  53. package/dist/cli/commands/redeploy.js +23 -10
  54. package/dist/cli/commands/redeploy.js.map +1 -1
  55. package/dist/cli/commands/reset.d.ts +22 -6
  56. package/dist/cli/commands/reset.js +132 -34
  57. package/dist/cli/commands/reset.js.map +1 -1
  58. package/dist/cli/commands/serve.js +20 -0
  59. package/dist/cli/commands/serve.js.map +1 -1
  60. package/dist/cli/commands/sync.js +66 -297
  61. package/dist/cli/commands/sync.js.map +1 -1
  62. package/dist/cli/crypto-bundle.d.ts +39 -0
  63. package/dist/cli/crypto-bundle.js +94 -0
  64. package/dist/cli/crypto-bundle.js.map +1 -0
  65. package/dist/cli/index.js +22 -30
  66. package/dist/cli/index.js.map +1 -1
  67. package/dist/cli/railway-pin.d.ts +68 -0
  68. package/dist/cli/railway-pin.js +96 -0
  69. package/dist/cli/railway-pin.js.map +1 -0
  70. package/dist/cli/setup-wizard.js +4 -2
  71. package/dist/cli/setup-wizard.js.map +1 -1
  72. package/dist/core/graph.d.ts +18 -0
  73. package/dist/core/graph.js +41 -5
  74. package/dist/core/graph.js.map +1 -1
  75. package/dist/core/secrets/registry.js +15 -0
  76. package/dist/core/secrets/registry.js.map +1 -1
  77. package/dist/core/user-config.d.ts +23 -0
  78. package/dist/core/user-config.js +36 -0
  79. package/dist/core/user-config.js.map +1 -1
  80. package/dist/core/workspace-manager.d.ts +3 -0
  81. package/dist/core/workspace-manager.js +10 -1
  82. package/dist/core/workspace-manager.js.map +1 -1
  83. package/dist/server/routes/auth-api.js +33 -10
  84. package/dist/server/routes/auth-api.js.map +1 -1
  85. package/dist/server/routes/git-http.js +4 -4
  86. package/dist/server/routes/git-http.js.map +1 -1
  87. package/dist/server/routes/graph-api.js +23 -1
  88. package/dist/server/routes/graph-api.js.map +1 -1
  89. package/dist/server/routes/insights-api.js +8 -41
  90. package/dist/server/routes/insights-api.js.map +1 -1
  91. package/dist/services/vector-service.d.ts +61 -2
  92. package/dist/services/vector-service.js +137 -3
  93. package/dist/services/vector-service.js.map +1 -1
  94. package/dist/utils/version-checker.d.ts +12 -22
  95. package/dist/utils/version-checker.js +14 -104
  96. package/dist/utils/version-checker.js.map +1 -1
  97. package/dist/web/_app/immutable/assets/{0.m6KHz5Ct.css → 0.rk06bb50.css} +1 -1
  98. package/dist/web/_app/immutable/assets/CalendarView.2_5KwEnm.css +1 -0
  99. package/dist/web/_app/immutable/assets/{Filters.DtCty8E-.css → Filters.DW9xqrSh.css} +1 -1
  100. package/dist/web/_app/immutable/assets/{KanbanView.G3NZ0uHb.css → KanbanView.BykCv6-6.css} +1 -1
  101. package/dist/web/_app/immutable/assets/{TimelineView.CTJIfMlQ.css → TimelineView.D5Vr4f4p.css} +1 -1
  102. package/dist/web/_app/immutable/chunks/{DrKGybIx.js → -6gQBbFR.js} +1 -1
  103. package/dist/web/_app/immutable/chunks/{hkz4tVDj.js → 0DopuZap.js} +1 -1
  104. package/dist/web/_app/immutable/chunks/{C6VKh19i2.js → 1-LQKXfZ2.js} +1 -1
  105. package/dist/web/_app/immutable/chunks/25df8L_v2.js +1 -0
  106. package/dist/web/_app/immutable/chunks/7DYGAJq32.js +1 -0
  107. package/dist/web/_app/immutable/chunks/{DoqF9D6X.js → B49iyw-B.js} +1 -1
  108. package/dist/web/_app/immutable/chunks/B8WVxDoi.js +1 -0
  109. package/dist/web/_app/immutable/chunks/{CMTVWAWD2.js → B8ern2gu2.js} +1 -1
  110. package/dist/web/_app/immutable/chunks/BL_MJFAi2.js +1 -0
  111. package/dist/web/_app/immutable/chunks/{BPLOxwd9.js → BQkTMTc1.js} +1 -1
  112. package/dist/web/_app/immutable/chunks/BRYgZsoN.js +1 -0
  113. package/dist/web/_app/immutable/chunks/{Brmm2B1F.js → Ba4GBqJu.js} +3 -3
  114. package/dist/web/_app/immutable/chunks/BbvKJFF_.js +1 -0
  115. package/dist/web/_app/immutable/chunks/{DFI49Ojd.js → Beinnj2F.js} +1 -1
  116. package/dist/web/_app/immutable/chunks/{3dvegJyw.js → BfYCB5cu.js} +4 -4
  117. package/dist/web/_app/immutable/chunks/{Bx_sUbFW2.js → Bgd45X5W2.js} +1 -1
  118. package/dist/web/_app/immutable/chunks/{B0sOCB6J2.js → Bn5UWofR2.js} +2 -2
  119. package/dist/web/_app/immutable/chunks/BnRO5LhI.js +1 -0
  120. package/dist/web/_app/immutable/chunks/Bq0v_R5r.js +2 -0
  121. package/dist/web/_app/immutable/chunks/{uYkLLAve.js → BrVXfxYL.js} +1 -1
  122. package/dist/web/_app/immutable/chunks/{BNMvG3vo.js → BzHJlS8U.js} +1 -1
  123. package/dist/web/_app/immutable/chunks/{D_x_Qx4b.js → C0r3tbe6.js} +1 -1
  124. package/dist/web/_app/immutable/chunks/{DWAwVvou2.js → C2rrtlqJ2.js} +1 -1
  125. package/dist/web/_app/immutable/chunks/{Cpzw6IR0.js → C6wTxDUN.js} +1 -1
  126. package/dist/web/_app/immutable/chunks/{DFa-r0hK2.js → C758laSC2.js} +1 -1
  127. package/dist/web/_app/immutable/chunks/{BsRJ3k1d.js → C7dZPzrF.js} +1 -1
  128. package/dist/web/_app/immutable/chunks/C7ehUIgK.js +1 -0
  129. package/dist/web/_app/immutable/chunks/{DimvZ1rk.js → CDdrTEPh.js} +1 -1
  130. package/dist/web/_app/immutable/chunks/{1lBMH6iW2.js → CDjqTDPq.js} +1 -1
  131. package/dist/web/_app/immutable/chunks/{H2kmhAjb2.js → CEzdXAzx.js} +1 -1
  132. package/dist/web/_app/immutable/chunks/CKyVp7pa.js +1 -0
  133. package/dist/web/_app/immutable/chunks/{CZl1ot9W.js → CNDUnAll.js} +1 -1
  134. package/dist/web/_app/immutable/chunks/{CQmPiyUp.js → CQZjBhsQ.js} +1 -1
  135. package/dist/web/_app/immutable/chunks/{BL1oxZiW2.js → CQpwu0Rw.js} +1 -1
  136. package/dist/web/_app/immutable/chunks/Ca4KscMv2.js +1 -0
  137. package/dist/web/_app/immutable/chunks/{DnvUa5lw2.js → CeH-DnOb2.js} +1 -1
  138. package/dist/web/_app/immutable/chunks/{DGzcahbp.js → Cl7sUEPM.js} +1 -1
  139. package/dist/web/_app/immutable/chunks/{D3fuCoSW2.js → ClZaQQEO2.js} +1 -1
  140. package/dist/web/_app/immutable/chunks/CqpDNs5Z.js +1 -0
  141. package/dist/web/_app/immutable/chunks/{Ds-56rNC.js → Cspt7VYo.js} +1 -1
  142. package/dist/web/_app/immutable/chunks/{C_SyfpYe.js → CvnXl5Rr.js} +1 -1
  143. package/dist/web/_app/immutable/chunks/{D5hsPE8N.js → Cw3xz8bO.js} +1 -1
  144. package/dist/web/_app/immutable/chunks/{Dz1qECzz.js → Cx1nIj6x.js} +1 -1
  145. package/dist/web/_app/immutable/chunks/{DuZvkPqs2.js → CyiNWqN72.js} +1 -1
  146. package/dist/web/_app/immutable/chunks/Cz2FjHF6.js +1 -0
  147. package/dist/web/_app/immutable/chunks/{DfLl5AcG2.js → Czwjp7ip2.js} +1 -1
  148. package/dist/web/_app/immutable/chunks/{DKVEBJ-32.js → D5YwRLyY2.js} +1 -1
  149. package/dist/web/_app/immutable/chunks/D5ydJQMZ.js +1 -0
  150. package/dist/web/_app/immutable/chunks/{iyvdeKmj.js → D9FQivYK.js} +1 -1
  151. package/dist/web/_app/immutable/chunks/{DOEenJe1.js → DARmfkV3.js} +1 -1
  152. package/dist/web/_app/immutable/chunks/DBANz5d9.js +1 -0
  153. package/dist/web/_app/immutable/chunks/DEsRD0Kx.js +1 -0
  154. package/dist/web/_app/immutable/chunks/{BqbXE992.js → DFGbrpeM.js} +3 -3
  155. package/dist/web/_app/immutable/chunks/DFKfEAag2.js +1 -0
  156. package/dist/web/_app/immutable/chunks/DGBLBaQ_.js +1 -0
  157. package/dist/web/_app/immutable/chunks/{CQ-2yccd.js → DJpbNaAK.js} +1 -1
  158. package/dist/web/_app/immutable/chunks/{yvIeeb_42.js → DNgAQxDP.js} +1 -1
  159. package/dist/web/_app/immutable/chunks/DPD8EOKr2.js +2 -0
  160. package/dist/web/_app/immutable/chunks/{DjuziFSq.js → DPYXG0kj.js} +1 -1
  161. package/dist/web/_app/immutable/chunks/{4pIH0_tT.js → DRPw0stG.js} +1 -1
  162. package/dist/web/_app/immutable/chunks/{BLhU-GJf.js → DR_cAG4D.js} +1 -1
  163. package/dist/web/_app/immutable/chunks/{xaGl2eMs.js → DTBwqHgG.js} +1 -1
  164. package/dist/web/_app/immutable/chunks/{CfK1GcGP2.js → DYvLXLU62.js} +1 -1
  165. package/dist/web/_app/immutable/chunks/{Qqt3Iwci2.js → DZHwUnTK.js} +1 -1
  166. package/dist/web/_app/immutable/chunks/{Byqqksev.js → DZV_JkdQ2.js} +1 -1
  167. package/dist/web/_app/immutable/chunks/{C83yuW3m2.js → Dha-MiFJ2.js} +1 -1
  168. package/dist/web/_app/immutable/chunks/DnawuswL2.js +1 -0
  169. package/dist/web/_app/immutable/chunks/{BdDPs-DM.js → Dux-JxEb.js} +1 -1
  170. package/dist/web/_app/immutable/chunks/F4YWa-kI.js +1 -0
  171. package/dist/web/_app/immutable/chunks/{Ci3J2iwp2.js → GbgQ0w_p2.js} +1 -1
  172. package/dist/web/_app/immutable/chunks/L1BSvKbu2.js +1 -0
  173. package/dist/web/_app/immutable/chunks/kW0emxZs.js +1 -0
  174. package/dist/web/_app/immutable/chunks/{DEcbx4K4.js → u2YWWW0D.js} +1 -1
  175. package/dist/web/_app/immutable/chunks/{CqX-MwhK.js → ud-80bN1.js} +1 -1
  176. package/dist/web/_app/immutable/chunks/wQ835Iqq2.js +83 -0
  177. package/dist/web/_app/immutable/entry/app.DcFury20.js +2 -0
  178. package/dist/web/_app/immutable/entry/start.31Egd-4X.js +1 -0
  179. package/dist/web/_app/immutable/nodes/{0.CITPEjbR.js → 0.C15TiBjR.js} +2 -2
  180. package/dist/web/_app/immutable/nodes/{1.DduJECtM.js → 1.DBqnCp5N.js} +1 -1
  181. package/dist/web/_app/immutable/nodes/{10.Cui_JZxb.js → 10.BoogCEfh.js} +1 -1
  182. package/dist/web/_app/immutable/nodes/{11.UeCoxbD-.js → 11.B5C95aiY.js} +1 -1
  183. package/dist/web/_app/immutable/nodes/{12.B9WJ7c9l.js → 12.Bo39gio2.js} +1 -1
  184. package/dist/web/_app/immutable/nodes/{13.DqgCQkJL.js → 13.DEPiNgiO.js} +1 -1
  185. package/dist/web/_app/immutable/nodes/2.Dqhur93F.js +106 -0
  186. package/dist/web/_app/immutable/nodes/{3.DZhsdFdZ.js → 3.DXrb2xtu.js} +1 -1
  187. package/dist/web/_app/immutable/nodes/4.BR9ghNP-.js +2 -0
  188. package/dist/web/_app/immutable/nodes/{5.CMsuIqT6.js → 5.B-uwmPkj.js} +1 -1
  189. package/dist/web/_app/immutable/nodes/{6.CkWVXmyL.js → 6.CtKXZ-rA.js} +1 -1
  190. package/dist/web/_app/immutable/nodes/{7.BkYENY24.js → 7.CQ40ZEvw.js} +1 -1
  191. package/dist/web/_app/immutable/nodes/{8.DwdTJOgA.js → 8.DHbQ0NZN.js} +1 -1
  192. package/dist/web/_app/immutable/nodes/{9.DKZ3Sgx1.js → 9.5fODFcxN.js} +1 -1
  193. package/dist/web/_app/version.json +1 -1
  194. package/dist/web/index.html +14 -14
  195. package/package.json +1 -1
  196. package/dist/web/_app/immutable/assets/CalendarView.B_hbOAbM.css +0 -1
  197. package/dist/web/_app/immutable/chunks/-ioccU5s.js +0 -2
  198. package/dist/web/_app/immutable/chunks/BK0ggYL62.js +0 -1
  199. package/dist/web/_app/immutable/chunks/CA4g7cjE2.js +0 -1
  200. package/dist/web/_app/immutable/chunks/CF8PYvJA.js +0 -1
  201. package/dist/web/_app/immutable/chunks/CGKzi17I2.js +0 -1
  202. package/dist/web/_app/immutable/chunks/ConbjvYQ2.js +0 -1
  203. package/dist/web/_app/immutable/chunks/D0e8PVhd2.js +0 -1
  204. package/dist/web/_app/immutable/chunks/D8tqcUuZ.js +0 -1
  205. package/dist/web/_app/immutable/chunks/D9PNm1z6.js +0 -1
  206. package/dist/web/_app/immutable/chunks/DO51xrVU.js +0 -1
  207. package/dist/web/_app/immutable/chunks/DT8BrRgZ.js +0 -1
  208. package/dist/web/_app/immutable/chunks/DU5E-t7g.js +0 -1
  209. package/dist/web/_app/immutable/chunks/DYdnKpvC2.js +0 -2
  210. package/dist/web/_app/immutable/chunks/DfGc2Vbl.js +0 -1
  211. package/dist/web/_app/immutable/chunks/Dvmab3aw2.js +0 -1
  212. package/dist/web/_app/immutable/chunks/JKJTTpmw.js +0 -1
  213. package/dist/web/_app/immutable/chunks/LB81VOAq.js +0 -1
  214. package/dist/web/_app/immutable/chunks/SRjhqDO_.js +0 -1
  215. package/dist/web/_app/immutable/chunks/YyBqtYe3.js +0 -1
  216. package/dist/web/_app/immutable/chunks/gULFBDXq2.js +0 -83
  217. package/dist/web/_app/immutable/entry/app.Bx-aFaCy.js +0 -2
  218. package/dist/web/_app/immutable/entry/start.B58d5Pp4.js +0 -1
  219. package/dist/web/_app/immutable/nodes/2.CuIyeEFg.js +0 -106
  220. package/dist/web/_app/immutable/nodes/4.BOsIV0oS.js +0 -2
  221. /package/dist/web/_app/immutable/chunks/{ByqcwQIl.js → 0y07qhHv.js} +0 -0
  222. /package/dist/web/_app/immutable/chunks/{C0Prwfom.js → 3Ddap93k.js} +0 -0
  223. /package/dist/web/_app/immutable/chunks/{CU3SD7Uz.js → BAQqEuSW.js} +0 -0
  224. /package/dist/web/_app/immutable/chunks/{CQzfplZr.js → BAwCCELm.js} +0 -0
  225. /package/dist/web/_app/immutable/chunks/{C50qCxM2.js → BBVt71H0.js} +0 -0
  226. /package/dist/web/_app/immutable/chunks/{BY2QDF2w2.js → BJDI0CVm2.js} +0 -0
  227. /package/dist/web/_app/immutable/chunks/{Cd727XFk.js → BLZ_gUXk.js} +0 -0
  228. /package/dist/web/_app/immutable/chunks/{DuxlyVaW.js → BM8OckeF.js} +0 -0
  229. /package/dist/web/_app/immutable/chunks/{BRcFsc6v.js → BNjJ851o.js} +0 -0
  230. /package/dist/web/_app/immutable/chunks/{DTsh-rY8.js → BQAzQWNc.js} +0 -0
  231. /package/dist/web/_app/immutable/chunks/{BSz-Rs6A.js → BaRWyZJp.js} +0 -0
  232. /package/dist/web/_app/immutable/chunks/{XMWvwY0B2.js → BdEEvMm72.js} +0 -0
  233. /package/dist/web/_app/immutable/chunks/{Dpq3LnpX.js → BzdIirhc.js} +0 -0
  234. /package/dist/web/_app/immutable/chunks/{BzeVNab0.js → C4ezn1Zj.js} +0 -0
  235. /package/dist/web/_app/immutable/chunks/{Mj7EytRp.js → C4q5lyFs.js} +0 -0
  236. /package/dist/web/_app/immutable/chunks/{C4_lca3x.js → C4qg8l0L2.js} +0 -0
  237. /package/dist/web/_app/immutable/chunks/{DQKRvmzW.js → C4wPmO56.js} +0 -0
  238. /package/dist/web/_app/immutable/chunks/{DxAl1xVd.js → CBNzpT1u.js} +0 -0
  239. /package/dist/web/_app/immutable/chunks/{C9bebE2N.js → CBb1eVhA.js} +0 -0
  240. /package/dist/web/_app/immutable/chunks/{_3ZPFErk.js → CCvrA-Jl.js} +0 -0
  241. /package/dist/web/_app/immutable/chunks/{DllsEP8T.js → CLHWE-_g.js} +0 -0
  242. /package/dist/web/_app/immutable/chunks/{C2A9kXuc.js → CQ-uDjOs.js} +0 -0
  243. /package/dist/web/_app/immutable/chunks/{A6bT_qFs.js → CgE_evqe2.js} +0 -0
  244. /package/dist/web/_app/immutable/chunks/{DazIzF5w.js → ChSBCyG-.js} +0 -0
  245. /package/dist/web/_app/immutable/chunks/{Ct9eObjX2.js → ChdqjvhH2.js} +0 -0
  246. /package/dist/web/_app/immutable/chunks/{Br5pOq3s2.js → CjiKtAHC2.js} +0 -0
  247. /package/dist/web/_app/immutable/chunks/{DihOyosf2.js → CltHJTT32.js} +0 -0
  248. /package/dist/web/_app/immutable/chunks/{UkaYCElu.js → CnXnpq3_.js} +0 -0
  249. /package/dist/web/_app/immutable/chunks/{c-GqbtBN.js → Cw58x-kY.js} +0 -0
  250. /package/dist/web/_app/immutable/chunks/{DW4yjnj8.js → D1f8I7Vy.js} +0 -0
  251. /package/dist/web/_app/immutable/chunks/{BgGI_ZrC.js → D6KPkxcJ.js} +0 -0
  252. /package/dist/web/_app/immutable/chunks/{DZZTHHPW.js → DP3v2upT.js} +0 -0
  253. /package/dist/web/_app/immutable/chunks/{BuHDhb_3.js → Dsmkh2We.js} +0 -0
  254. /package/dist/web/_app/immutable/chunks/{NKbVWJ8w.js → DzMSiHnE.js} +0 -0
  255. /package/dist/web/_app/immutable/chunks/{Dwtqnses.js → E1QJ8qxh.js} +0 -0
  256. /package/dist/web/_app/immutable/chunks/{DhF8zQQ3.js → EW0uyMSW.js} +0 -0
  257. /package/dist/web/_app/immutable/chunks/{DPqDmSD4.js → YrKPpvrI2.js} +0 -0
  258. /package/dist/web/_app/immutable/chunks/{DLG3I4qA.js → hEijmR6g.js} +0 -0
  259. /package/dist/web/_app/immutable/chunks/{CsmcxOCI2.js → wR_dFW8K2.js} +0 -0
@@ -0,0 +1,54 @@
1
+ /**
2
+ * studiograph admin backup — produce a passphrase-wrapped, manifest-aware
3
+ * snapshot of the entire local workspace.
4
+ *
5
+ * Pairs with `admin restore`. Distinct from `clone`:
6
+ * - `clone` pulls from a running server; strips machine-specific config
7
+ * (r2_config, railway, master-key, JWT secret); good for setting up
8
+ * a new dev machine.
9
+ * - `admin backup` snapshots the local workspace; includes secrets.db,
10
+ * auth.db, r2_config, railway IDs, and a manifest of the Railway env
11
+ * vars (master key, JWT secret) the owner provides at backup time;
12
+ * good for "server is dead, restore me."
13
+ *
14
+ * Bundle contents (encrypted as a single .sgbackup file):
15
+ * - manifest.json — env-var values + Railway IDs + workspace name + ts
16
+ * - workspace/ — tar of the workspace directory, minus
17
+ * node_modules/, .DS_Store, and any *.log files
18
+ *
19
+ * Crypto: passphrase → scrypt → key → xchacha20poly1305(tar.gz).
20
+ * See [src/cli/crypto-bundle.ts] for the wire format.
21
+ *
22
+ * Refuses to write the bundle to a destination directory unless it
23
+ * exists with mode 0700, or is being created (we make it 0700). Bundle
24
+ * file is written with mode 0600. Defense against world-readable backups
25
+ * that contain bcrypt hashes from auth.db.
26
+ */
27
+ import { Command } from 'commander';
28
+ interface BackupManifest {
29
+ workspace_name: string;
30
+ created_at: string;
31
+ format_version: 1;
32
+ /** Railway-side env vars the operator supplied at backup time. The
33
+ * backup intentionally re-prompts for these (rather than reading from
34
+ * the workspace's secrets.db) so a single passphrase-wrapped bundle
35
+ * carries everything restore needs. */
36
+ env: {
37
+ STUDIOGRAPH_MASTER_KEY: string;
38
+ STUDIOGRAPH_JWT_SECRET: string;
39
+ };
40
+ /** Railway link, if any. Each field is optional in workspace.json
41
+ * schema, so the manifest carries them as optional too — restore
42
+ * reports the gap if a value is missing rather than rejecting the
43
+ * whole bundle. */
44
+ railway?: {
45
+ project_id?: string;
46
+ service_id?: string;
47
+ environment_id?: string;
48
+ };
49
+ /** Cosmetic only — restore uses this to print "this bundle is from
50
+ * workspace X, created Y". Does not affect the restore behavior. */
51
+ notes?: string;
52
+ }
53
+ export declare const adminBackupCommand: Command;
54
+ export type { BackupManifest };
@@ -0,0 +1,207 @@
1
+ /**
2
+ * studiograph admin backup — produce a passphrase-wrapped, manifest-aware
3
+ * snapshot of the entire local workspace.
4
+ *
5
+ * Pairs with `admin restore`. Distinct from `clone`:
6
+ * - `clone` pulls from a running server; strips machine-specific config
7
+ * (r2_config, railway, master-key, JWT secret); good for setting up
8
+ * a new dev machine.
9
+ * - `admin backup` snapshots the local workspace; includes secrets.db,
10
+ * auth.db, r2_config, railway IDs, and a manifest of the Railway env
11
+ * vars (master key, JWT secret) the owner provides at backup time;
12
+ * good for "server is dead, restore me."
13
+ *
14
+ * Bundle contents (encrypted as a single .sgbackup file):
15
+ * - manifest.json — env-var values + Railway IDs + workspace name + ts
16
+ * - workspace/ — tar of the workspace directory, minus
17
+ * node_modules/, .DS_Store, and any *.log files
18
+ *
19
+ * Crypto: passphrase → scrypt → key → xchacha20poly1305(tar.gz).
20
+ * See [src/cli/crypto-bundle.ts] for the wire format.
21
+ *
22
+ * Refuses to write the bundle to a destination directory unless it
23
+ * exists with mode 0700, or is being created (we make it 0700). Bundle
24
+ * file is written with mode 0600. Defense against world-readable backups
25
+ * that contain bcrypt hashes from auth.db.
26
+ */
27
+ import { Command } from 'commander';
28
+ import { intro, outro, log, spinner, password, isCancel, confirm } from '@clack/prompts';
29
+ import { execFileSync } from 'child_process';
30
+ import { existsSync, mkdirSync, writeFileSync, statSync, mkdtempSync, rmSync, readFileSync } from 'fs';
31
+ import { join, resolve } from 'path';
32
+ import { tmpdir } from 'os';
33
+ import { Workspace } from '../../../core/workspace.js';
34
+ import { sealBundle } from '../../crypto-bundle.js';
35
+ export const adminBackupCommand = new Command('backup')
36
+ .description('Snapshot the local workspace into a passphrase-wrapped bundle')
37
+ .option('--out <path>', 'Output directory for the .sgbackup file (default: cwd)')
38
+ .option('--master-key <value>', 'STUDIOGRAPH_MASTER_KEY env value (also reads STUDIOGRAPH_MASTER_KEY env var)')
39
+ .option('--jwt-secret <value>', 'STUDIOGRAPH_JWT_SECRET env value (also reads STUDIOGRAPH_JWT_SECRET env var)')
40
+ .option('--passphrase-stdin', 'Read the bundle passphrase from stdin (single line)')
41
+ .action(async (opts) => {
42
+ intro('Studiograph workspace backup');
43
+ const workspace = new Workspace();
44
+ if (!workspace.isWorkspace()) {
45
+ outro('Not a Studiograph workspace. Run from your workspace root.');
46
+ process.exit(1);
47
+ return;
48
+ }
49
+ const config = await workspace.loadConfig();
50
+ // Step 1: gather the env-var manifest. These are NOT in the workspace
51
+ // dir — they live in Railway's variables. The backup is useless
52
+ // without them, so we make collecting them an explicit, blocking
53
+ // step.
54
+ const masterKey = opts.masterKey?.trim() || process.env.STUDIOGRAPH_MASTER_KEY?.trim();
55
+ const jwtSecret = opts.jwtSecret?.trim() || process.env.STUDIOGRAPH_JWT_SECRET?.trim();
56
+ let mk;
57
+ let jwt;
58
+ if (masterKey && jwtSecret) {
59
+ mk = masterKey;
60
+ jwt = jwtSecret;
61
+ log.info('Using STUDIOGRAPH_MASTER_KEY + STUDIOGRAPH_JWT_SECRET from flags/env');
62
+ }
63
+ else {
64
+ if (!process.stdout.isTTY) {
65
+ outro('No TTY. Pass --master-key and --jwt-secret, or set the matching env vars.');
66
+ process.exit(1);
67
+ return;
68
+ }
69
+ log.message('These two values live in Railway, not in the workspace. Copy them from\n' +
70
+ ' Railway → your service → Variables → STUDIOGRAPH_MASTER_KEY / STUDIOGRAPH_JWT_SECRET\n' +
71
+ 'Without them the restored workspace cannot decrypt secrets.db or verify any\n' +
72
+ 'existing JWT cookies.');
73
+ const mkInput = await password({ message: 'STUDIOGRAPH_MASTER_KEY:', validate: (v) => v.trim() ? undefined : 'Required' });
74
+ if (isCancel(mkInput)) {
75
+ outro('Cancelled');
76
+ process.exit(0);
77
+ return;
78
+ }
79
+ const jwtInput = await password({ message: 'STUDIOGRAPH_JWT_SECRET:', validate: (v) => v.trim() ? undefined : 'Required' });
80
+ if (isCancel(jwtInput)) {
81
+ outro('Cancelled');
82
+ process.exit(0);
83
+ return;
84
+ }
85
+ mk = String(mkInput).trim();
86
+ jwt = String(jwtInput).trim();
87
+ }
88
+ // Step 2: passphrase for the bundle.
89
+ let passphrase;
90
+ if (opts.passphraseStdin) {
91
+ passphrase = await readPassphraseStdin();
92
+ }
93
+ else if (process.stdout.isTTY) {
94
+ const pp1 = await password({
95
+ message: 'Bundle passphrase (min 12 chars):',
96
+ validate: (v) => (v.length >= 12 ? undefined : 'At least 12 characters'),
97
+ });
98
+ if (isCancel(pp1)) {
99
+ outro('Cancelled');
100
+ process.exit(0);
101
+ return;
102
+ }
103
+ const pp2 = await password({ message: 'Confirm passphrase:' });
104
+ if (isCancel(pp2)) {
105
+ outro('Cancelled');
106
+ process.exit(0);
107
+ return;
108
+ }
109
+ if (String(pp1) !== String(pp2)) {
110
+ outro('Passphrases did not match.');
111
+ process.exit(1);
112
+ return;
113
+ }
114
+ passphrase = String(pp1);
115
+ }
116
+ else {
117
+ outro('No TTY. Pass --passphrase-stdin and pipe the passphrase to stdin.');
118
+ process.exit(1);
119
+ return;
120
+ }
121
+ // Step 3: validate output directory + file.
122
+ const outDir = resolve(opts.out ?? process.cwd());
123
+ if (!existsSync(outDir)) {
124
+ mkdirSync(outDir, { recursive: true, mode: 0o700 });
125
+ }
126
+ else {
127
+ const dirMode = statSync(outDir).mode & 0o777;
128
+ if ((dirMode & 0o077) !== 0) {
129
+ const proceed = await confirm({
130
+ message: `Output directory ${outDir} is mode 0${dirMode.toString(8)} — group/world readable. Continue anyway?`,
131
+ initialValue: false,
132
+ });
133
+ if (!proceed || isCancel(proceed)) {
134
+ outro('Cancelled — chmod 700 the directory and retry.');
135
+ process.exit(0);
136
+ return;
137
+ }
138
+ }
139
+ }
140
+ const fileName = `studiograph-backup-${(config.team_name || 'workspace').toLowerCase().replace(/[^a-z0-9]+/g, '-')}-${new Date().toISOString().slice(0, 10)}.sgbackup`;
141
+ const filePath = join(outDir, fileName);
142
+ if (existsSync(filePath)) {
143
+ outro(`Refusing to overwrite ${filePath}. Move or delete the existing bundle and retry.`);
144
+ process.exit(1);
145
+ return;
146
+ }
147
+ // Step 4: build the bundle. tar the workspace + manifest into a temp
148
+ // file, encrypt, write. Temp lives in os.tmpdir(); we clean up in
149
+ // finally even on errors.
150
+ const tmpRoot = mkdtempSync(join(tmpdir(), 'sg-backup-'));
151
+ const manifestPath = join(tmpRoot, 'manifest.json');
152
+ const tarPath = join(tmpRoot, 'bundle.tar.gz');
153
+ try {
154
+ const manifest = {
155
+ workspace_name: config.team_name || 'unknown',
156
+ created_at: new Date().toISOString(),
157
+ format_version: 1,
158
+ env: {
159
+ STUDIOGRAPH_MASTER_KEY: mk,
160
+ STUDIOGRAPH_JWT_SECRET: jwt,
161
+ },
162
+ railway: config.railway,
163
+ };
164
+ writeFileSync(manifestPath, JSON.stringify(manifest, null, 2), { encoding: 'utf-8', mode: 0o600 });
165
+ const spin = spinner();
166
+ spin.start('Tarring workspace...');
167
+ // -C tmpRoot for manifest.json + -C cwd for workspace contents.
168
+ // Two `-C` flags = tar resets the chdir per following path. The
169
+ // workspace contents land at top-level of the tar so restore is
170
+ // a single expand. The manifest sits beside them.
171
+ // Exclusions: node_modules, .DS_Store, *.log keep the bundle lean
172
+ // without dropping anything load-bearing.
173
+ execFileSync('tar', [
174
+ '-czf', tarPath,
175
+ '--exclude', 'node_modules',
176
+ '--exclude', '.DS_Store',
177
+ '--exclude', '*.log',
178
+ '-C', tmpRoot, 'manifest.json',
179
+ '-C', process.cwd(), '.',
180
+ ], { stdio: 'pipe' });
181
+ spin.stop('Tarred');
182
+ spin.start('Encrypting (scrypt is intentionally slow)...');
183
+ const plaintext = readFileSync(tarPath);
184
+ const ciphertext = sealBundle(plaintext, passphrase);
185
+ spin.stop('Encrypted');
186
+ writeFileSync(filePath, ciphertext, { mode: 0o600 });
187
+ log.success(`Wrote ${filePath} (${(ciphertext.length / 1024).toFixed(1)} KB)`);
188
+ log.message('Keep this file AND its passphrase separately. The bundle contains\n' +
189
+ 'bcrypt password hashes, encrypted secrets.db, and your Railway env\n' +
190
+ 'vars in plaintext (within the encrypted envelope) — treat it like\n' +
191
+ 'a credential.');
192
+ outro('Backup complete.');
193
+ }
194
+ finally {
195
+ rmSync(tmpRoot, { recursive: true, force: true });
196
+ }
197
+ });
198
+ async function readPassphraseStdin() {
199
+ return new Promise((resolveFn, rejectFn) => {
200
+ let buf = '';
201
+ process.stdin.setEncoding('utf-8');
202
+ process.stdin.on('data', (chunk) => (buf += chunk));
203
+ process.stdin.on('end', () => resolveFn(buf.replace(/\r?\n$/, '')));
204
+ process.stdin.on('error', rejectFn);
205
+ });
206
+ }
207
+ //# sourceMappingURL=backup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backup.js","sourceRoot":"","sources":["../../../../src/cli/commands/admin/backup.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * studiograph folder command
3
+ *
4
+ * Subcommands:
5
+ * studiograph folder add <name> — create a new folder
6
+ * studiograph folder list — list all folders with entity counts
7
+ * studiograph folder rename <old> <new> — rename a folder
8
+ * studiograph folder remove <name> — remove a folder (with confirmation)
9
+ */
10
+ import { Command } from 'commander';
11
+ export declare const folderCommand: Command;
@@ -0,0 +1,186 @@
1
+ /**
2
+ * studiograph folder command
3
+ *
4
+ * Subcommands:
5
+ * studiograph folder add <name> — create a new folder
6
+ * studiograph folder list — list all folders with entity counts
7
+ * studiograph folder rename <old> <new> — rename a folder
8
+ * studiograph folder remove <name> — remove a folder (with confirmation)
9
+ */
10
+ import { Command } from 'commander';
11
+ import { log, confirm } from '@clack/prompts';
12
+ import { existsSync } from 'fs';
13
+ import { join } from 'path';
14
+ import { Workspace } from '../../../core/workspace.js';
15
+ import { BaseGraphManager } from '../../../core/graph.js';
16
+ function requireWorkspace() {
17
+ const workspace = new Workspace();
18
+ if (!workspace.isWorkspace()) {
19
+ console.error('Not a Studiograph workspace. Run `studiograph init` first.');
20
+ return null;
21
+ }
22
+ return workspace;
23
+ }
24
+ // ─── add ──────────────────────────────────────────────────────────────────────
25
+ const addCommand = new Command('add')
26
+ .description('Create a new folder')
27
+ .argument('<name>', 'Folder name (kebab-case)')
28
+ .option('-d, --description <desc>', 'Folder description')
29
+ .action(async (name, opts) => {
30
+ const workspace = requireWorkspace();
31
+ if (!workspace) {
32
+ process.exit(1);
33
+ return;
34
+ }
35
+ // Validate name is kebab-case
36
+ if (!/^[a-z0-9][a-z0-9-]*$/.test(name)) {
37
+ log.error('Folder name must be kebab-case (e.g., "client-projects")');
38
+ process.exit(1);
39
+ return;
40
+ }
41
+ try {
42
+ const repo = await workspace.registerRepo({
43
+ name,
44
+ description: opts.description,
45
+ });
46
+ log.success(`Folder "${repo.name}" created at ${repo.path}/`);
47
+ }
48
+ catch (err) {
49
+ log.error(err instanceof Error ? err.message : 'Unknown error');
50
+ process.exit(1);
51
+ }
52
+ });
53
+ // ─── list ─────────────────────────────────────────────────────────────────────
54
+ const listCommand = new Command('list')
55
+ .description('List all folders with entity counts')
56
+ .action(async () => {
57
+ const workspace = requireWorkspace();
58
+ if (!workspace) {
59
+ process.exit(1);
60
+ return;
61
+ }
62
+ const config = await workspace.loadConfig();
63
+ const repos = config.repos;
64
+ if (repos.length === 0) {
65
+ log.info('No folders. Run `studiograph folder add <name>` to create one.');
66
+ return;
67
+ }
68
+ console.log('\nFolders\n');
69
+ console.log(' Name Entities Description');
70
+ console.log(' ' + '\u2500'.repeat(72));
71
+ for (const repo of repos) {
72
+ let entityCount = 0;
73
+ const repoPath = join(workspace.getWorkspacePath(), repo.path);
74
+ if (existsSync(repoPath)) {
75
+ try {
76
+ const graph = new BaseGraphManager({
77
+ repoPath,
78
+ repoName: repo.name,
79
+ gitUser: { id: 'cli', name: 'cli', email: 'cli@studiograph.local' },
80
+ });
81
+ entityCount = graph.list().length;
82
+ }
83
+ catch { /* non-fatal */ }
84
+ }
85
+ const rname = repo.name.padEnd(30);
86
+ const count = String(entityCount).padStart(4);
87
+ const desc = repo.description || '';
88
+ const suffix = repo.personal ? ' (personal)' : '';
89
+ console.log(` ${rname} ${count} ${desc}${suffix}`);
90
+ }
91
+ console.log('');
92
+ });
93
+ // ─── rename ───────────────────────────────────────────────────────────────────
94
+ const renameCommand = new Command('rename')
95
+ .description('Rename a folder')
96
+ .argument('<old-name>', 'Current folder name')
97
+ .argument('<new-name>', 'New folder name (kebab-case)')
98
+ .action(async (oldName, newName) => {
99
+ const workspace = requireWorkspace();
100
+ if (!workspace) {
101
+ process.exit(1);
102
+ return;
103
+ }
104
+ if (!/^[a-z0-9][a-z0-9-]*$/.test(newName)) {
105
+ log.error('New name must be kebab-case (e.g., "client-projects")');
106
+ process.exit(1);
107
+ return;
108
+ }
109
+ const config = await workspace.loadConfig();
110
+ const repo = config.repos.find(r => r.name === oldName);
111
+ if (!repo) {
112
+ log.error(`Folder "${oldName}" not found.`);
113
+ process.exit(1);
114
+ return;
115
+ }
116
+ if (config.repos.some(r => r.name === newName)) {
117
+ log.error(`Folder "${newName}" already exists.`);
118
+ process.exit(1);
119
+ return;
120
+ }
121
+ const oldPath = join(workspace.getWorkspacePath(), repo.path);
122
+ const newPath = join(workspace.getWorkspacePath(), newName);
123
+ // Rename directory
124
+ if (existsSync(oldPath)) {
125
+ const { renameSync } = await import('fs');
126
+ renameSync(oldPath, newPath);
127
+ }
128
+ // Update config
129
+ repo.name = newName;
130
+ repo.path = newName;
131
+ workspace.writeConfig(config);
132
+ // Update .studiograph marker in the repo
133
+ const markerPath = join(newPath, '.studiograph');
134
+ if (existsSync(markerPath)) {
135
+ const { writeFileSync } = await import('fs');
136
+ writeFileSync(markerPath, JSON.stringify({ repo_name: newName }, null, 2), 'utf-8');
137
+ }
138
+ log.success(`Folder renamed: "${oldName}" → "${newName}"`);
139
+ });
140
+ // ─── remove ───────────────────────────────────────────────────────────────────
141
+ const removeCommand = new Command('remove')
142
+ .description('Remove a folder from the workspace')
143
+ .argument('<name>', 'Folder name to remove')
144
+ .option('--delete-files', 'Also delete the folder directory from disk')
145
+ .action(async (name, opts) => {
146
+ const workspace = requireWorkspace();
147
+ if (!workspace) {
148
+ process.exit(1);
149
+ return;
150
+ }
151
+ const config = await workspace.loadConfig();
152
+ const repoIndex = config.repos.findIndex(r => r.name === name);
153
+ if (repoIndex === -1) {
154
+ log.error(`Folder "${name}" not found.`);
155
+ process.exit(1);
156
+ return;
157
+ }
158
+ const repo = config.repos[repoIndex];
159
+ const repoPath = join(workspace.getWorkspacePath(), repo.path);
160
+ const yes = await confirm({
161
+ message: opts.deleteFiles
162
+ ? `Remove folder "${name}" and delete all files at ${repo.path}/?`
163
+ : `Remove folder "${name}" from workspace config? (files at ${repo.path}/ will be kept)`,
164
+ });
165
+ if (!yes || typeof yes === 'symbol')
166
+ return;
167
+ // Remove from config
168
+ config.repos.splice(repoIndex, 1);
169
+ workspace.writeConfig(config);
170
+ if (opts.deleteFiles && existsSync(repoPath)) {
171
+ const { rmSync } = await import('fs');
172
+ rmSync(repoPath, { recursive: true, force: true });
173
+ log.success(`Folder "${name}" removed and files deleted.`);
174
+ }
175
+ else {
176
+ log.success(`Folder "${name}" removed from config. Files at ${repo.path}/ were kept.`);
177
+ }
178
+ });
179
+ // ─── parent command ───────────────────────────────────────────────────────────
180
+ export const folderCommand = new Command('folder')
181
+ .description('Manage workspace folders')
182
+ .addCommand(addCommand)
183
+ .addCommand(listCommand)
184
+ .addCommand(renameCommand)
185
+ .addCommand(removeCommand);
186
+ //# sourceMappingURL=folder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"folder.js","sourceRoot":"","sources":["../../../../src/cli/commands/admin/folder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * studiograph admin — owner-only ops surface.
3
+ *
4
+ * Subcommands accumulate here as Phase A lands:
5
+ * - admin token (A4)
6
+ * - admin migrate (A5)
7
+ * - admin backup (A6)
8
+ * - admin restore (A6)
9
+ * - admin transfer-ownership (A8)
10
+ * - admin audit-workspace (A8)
11
+ *
12
+ * In Phase D, the existing top-level user/folder/secrets/settings/audit
13
+ * commands also move under this parent.
14
+ */
15
+ import { Command } from 'commander';
16
+ export declare const adminCommand: Command;
@@ -0,0 +1,44 @@
1
+ /**
2
+ * studiograph admin — owner-only ops surface.
3
+ *
4
+ * Subcommands accumulate here as Phase A lands:
5
+ * - admin token (A4)
6
+ * - admin migrate (A5)
7
+ * - admin backup (A6)
8
+ * - admin restore (A6)
9
+ * - admin transfer-ownership (A8)
10
+ * - admin audit-workspace (A8)
11
+ *
12
+ * In Phase D, the existing top-level user/folder/secrets/settings/audit
13
+ * commands also move under this parent.
14
+ */
15
+ import { Command } from 'commander';
16
+ import { adminTokenCommand } from './token.js';
17
+ import { adminMigrateCommand } from './migrate.js';
18
+ import { adminBackupCommand } from './backup.js';
19
+ import { adminRestoreCommand } from './restore.js';
20
+ import { adminTransferOwnershipCommand } from './transfer-ownership.js';
21
+ import { adminAuditWorkspaceCommand } from './audit-workspace.js';
22
+ import { userCommand } from './user.js';
23
+ import { folderCommand } from './folder.js';
24
+ import { secretsCommand } from './secrets.js';
25
+ import { settingsCommand } from './settings.js';
26
+ import { auditCommand } from './audit.js';
27
+ export const adminCommand = new Command('admin').description('Owner-only administrative commands');
28
+ // Phase D1: the five workspace-management subcommands (user, folder,
29
+ // secrets, settings, audit) moved from top-level into admin/. Top-level
30
+ // aliases stay for one release — see src/cli/index.ts argv shim. The
31
+ // next release drops the shim and these become admin-only.
32
+ adminCommand.addCommand(userCommand);
33
+ adminCommand.addCommand(folderCommand);
34
+ adminCommand.addCommand(secretsCommand);
35
+ adminCommand.addCommand(settingsCommand);
36
+ adminCommand.addCommand(auditCommand);
37
+ // New admin verbs added through Phase A.
38
+ adminCommand.addCommand(adminTokenCommand);
39
+ adminCommand.addCommand(adminMigrateCommand);
40
+ adminCommand.addCommand(adminBackupCommand);
41
+ adminCommand.addCommand(adminRestoreCommand);
42
+ adminCommand.addCommand(adminTransferOwnershipCommand);
43
+ adminCommand.addCommand(adminAuditWorkspaceCommand);
44
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/cli/commands/admin/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,6BAA6B,EAAE,MAAM,yBAAyB,CAAC;AACxE,OAAO,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,oCAAoC,CAAC,CAAC;AAEnG,qEAAqE;AACrE,wEAAwE;AACxE,qEAAqE;AACrE,2DAA2D;AAC3D,YAAY,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AACrC,YAAY,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AACvC,YAAY,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;AACxC,YAAY,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;AACzC,YAAY,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;AAEtC,yCAAyC;AACzC,YAAY,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC;AAC3C,YAAY,CAAC,UAAU,CAAC,mBAAmB,CAAC,CAAC;AAC7C,YAAY,CAAC,UAAU,CAAC,kBAAkB,CAAC,CAAC;AAC5C,YAAY,CAAC,UAAU,CAAC,mBAAmB,CAAC,CAAC;AAC7C,YAAY,CAAC,UAAU,CAAC,6BAA6B,CAAC,CAAC;AACvD,YAAY,CAAC,UAAU,CAAC,0BAA0B,CAAC,CAAC"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * studiograph admin migrate — bulk regex find-replace across workspace repos.
3
+ *
4
+ * Codifies the hand-rolled sed pattern the owner has reached for twice
5
+ * during schema renames. Walks every repo in workspace.json (or a
6
+ * `--repos`-filtered subset), applies the regex, and produces one commit
7
+ * per repo with the same message. `--dry-run` reports without writing.
8
+ * `--also-rename-files` does a second pass that `git mv`s any files
9
+ * whose name matches the regex.
10
+ *
11
+ * Safety:
12
+ * - Refuses if ANY targeted repo has uncommitted changes. Catches
13
+ * half-finished local edits before they're caught up in the rewrite.
14
+ * - Runs the regex against the file contents read with utf-8; commit
15
+ * uses `git -c core.quotepath=false` so non-ASCII file paths in
16
+ * summaries don't render as `\xxx` escapes.
17
+ * - Skips the .git/, .studiograph/, and node_modules/ subtrees of every
18
+ * repo (defensive — none of those should ever match a workspace glob,
19
+ * but a stray `--in '**'` shouldn't pull them in either).
20
+ */
21
+ import { Command } from 'commander';
22
+ import type { RepoConfig } from '../../../core/types.js';
23
+ interface RepoChange {
24
+ repoName: string;
25
+ repoPath: string;
26
+ fileChanges: Array<{
27
+ relPath: string;
28
+ replacements: number;
29
+ }>;
30
+ fileRenames: Array<{
31
+ from: string;
32
+ to: string;
33
+ }>;
34
+ }
35
+ export declare const adminMigrateCommand: Command;
36
+ /**
37
+ * Walk one repo, regex-replace contents in every file matching `pattern`
38
+ * (the glob pattern, not the regex). Returns a summary; writes files
39
+ * unless `dryRun` is true.
40
+ */
41
+ export declare function migrateRepoContent(repo: RepoConfig, globPattern: string, regex: RegExp, replacement: string, dryRun: boolean): Promise<RepoChange>;
42
+ /**
43
+ * Apply a replacement-string template the way String.prototype.replace
44
+ * does when given a string (not a function): expand $1..$9 to capture
45
+ * groups, $$ to a literal $, $& to the whole match.
46
+ *
47
+ * We re-implement this because we call replace with a *function* (to
48
+ * count matches) but want the literal-string substitution semantics for
49
+ * the actual replacement text. Without this, $1/$2 would render
50
+ * literally instead of being expanded.
51
+ */
52
+ declare function applyReplacementString(template: string, match: string, args: unknown[]): string;
53
+ export declare const __internals: {
54
+ applyReplacementString: typeof applyReplacementString;
55
+ };
56
+ export {};