@untangle-code/cli 0.0.0-stage → 0.1.0

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 (571) hide show
  1. package/LICENSE +661 -0
  2. package/NOTICE +90 -0
  3. package/README.md +424 -2
  4. package/THIRD_PARTY_LICENSES.md +152 -0
  5. package/dist/cli/args.d.ts +48 -0
  6. package/dist/cli/args.d.ts.map +1 -0
  7. package/dist/cli/args.js +167 -0
  8. package/dist/cli/args.js.map +1 -0
  9. package/dist/cli/command.d.ts +69 -0
  10. package/dist/cli/command.d.ts.map +1 -0
  11. package/dist/cli/command.js +82 -0
  12. package/dist/cli/command.js.map +1 -0
  13. package/dist/cli/deadline.d.ts +33 -0
  14. package/dist/cli/deadline.d.ts.map +1 -0
  15. package/dist/cli/deadline.js +49 -0
  16. package/dist/cli/deadline.js.map +1 -0
  17. package/dist/cli/embedder-deadline.d.ts +72 -0
  18. package/dist/cli/embedder-deadline.d.ts.map +1 -0
  19. package/dist/cli/embedder-deadline.js +117 -0
  20. package/dist/cli/embedder-deadline.js.map +1 -0
  21. package/dist/cli/exit.d.ts +71 -0
  22. package/dist/cli/exit.d.ts.map +1 -0
  23. package/dist/cli/exit.js +81 -0
  24. package/dist/cli/exit.js.map +1 -0
  25. package/dist/cli/graphs.d.ts +65 -0
  26. package/dist/cli/graphs.d.ts.map +1 -0
  27. package/dist/cli/graphs.js +108 -0
  28. package/dist/cli/graphs.js.map +1 -0
  29. package/dist/cli/index-freshness.d.ts +13 -0
  30. package/dist/cli/index-freshness.d.ts.map +1 -0
  31. package/dist/cli/index-freshness.js +226 -0
  32. package/dist/cli/index-freshness.js.map +1 -0
  33. package/dist/cli/index-refresh.d.ts +10 -0
  34. package/dist/cli/index-refresh.d.ts.map +1 -0
  35. package/dist/cli/index-refresh.js +76 -0
  36. package/dist/cli/index-refresh.js.map +1 -0
  37. package/dist/cli/index-state.d.ts +184 -0
  38. package/dist/cli/index-state.d.ts.map +1 -0
  39. package/dist/cli/index-state.js +852 -0
  40. package/dist/cli/index-state.js.map +1 -0
  41. package/dist/cli/io.d.ts +29 -0
  42. package/dist/cli/io.d.ts.map +1 -0
  43. package/dist/cli/io.js +42 -0
  44. package/dist/cli/io.js.map +1 -0
  45. package/dist/cli/language-support.d.ts +77 -0
  46. package/dist/cli/language-support.d.ts.map +1 -0
  47. package/dist/cli/language-support.js +152 -0
  48. package/dist/cli/language-support.js.map +1 -0
  49. package/dist/cli/renewing-lease.d.ts +26 -0
  50. package/dist/cli/renewing-lease.d.ts.map +1 -0
  51. package/dist/cli/renewing-lease.js +102 -0
  52. package/dist/cli/renewing-lease.js.map +1 -0
  53. package/dist/cli/search-graph-enrichment.d.ts +16 -0
  54. package/dist/cli/search-graph-enrichment.d.ts.map +1 -0
  55. package/dist/cli/search-graph-enrichment.js +428 -0
  56. package/dist/cli/search-graph-enrichment.js.map +1 -0
  57. package/dist/cli/system.d.ts +34 -0
  58. package/dist/cli/system.d.ts.map +1 -0
  59. package/dist/cli/system.js +89 -0
  60. package/dist/cli/system.js.map +1 -0
  61. package/dist/cli/vector-store-policy.d.ts +116 -0
  62. package/dist/cli/vector-store-policy.d.ts.map +1 -0
  63. package/dist/cli/vector-store-policy.js +160 -0
  64. package/dist/cli/vector-store-policy.js.map +1 -0
  65. package/dist/cli/version.d.ts +3 -0
  66. package/dist/cli/version.d.ts.map +1 -0
  67. package/dist/cli/version.js +3 -0
  68. package/dist/cli/version.js.map +1 -0
  69. package/dist/cli/workspace.d.ts +105 -0
  70. package/dist/cli/workspace.d.ts.map +1 -0
  71. package/dist/cli/workspace.js +215 -0
  72. package/dist/cli/workspace.js.map +1 -0
  73. package/dist/commands/complexity.d.ts +72 -0
  74. package/dist/commands/complexity.d.ts.map +1 -0
  75. package/dist/commands/complexity.js +580 -0
  76. package/dist/commands/complexity.js.map +1 -0
  77. package/dist/commands/doctor.d.ts +66 -0
  78. package/dist/commands/doctor.d.ts.map +1 -0
  79. package/dist/commands/doctor.js +764 -0
  80. package/dist/commands/doctor.js.map +1 -0
  81. package/dist/commands/doctor.languages.d.ts +37 -0
  82. package/dist/commands/doctor.languages.d.ts.map +1 -0
  83. package/dist/commands/doctor.languages.js +143 -0
  84. package/dist/commands/doctor.languages.js.map +1 -0
  85. package/dist/commands/doctor.storage.d.ts +17 -0
  86. package/dist/commands/doctor.storage.d.ts.map +1 -0
  87. package/dist/commands/doctor.storage.js +91 -0
  88. package/dist/commands/doctor.storage.js.map +1 -0
  89. package/dist/commands/extensions/add.d.ts +10 -0
  90. package/dist/commands/extensions/add.d.ts.map +1 -0
  91. package/dist/commands/extensions/add.js +213 -0
  92. package/dist/commands/extensions/add.js.map +1 -0
  93. package/dist/commands/extensions/configure.d.ts +5 -0
  94. package/dist/commands/extensions/configure.d.ts.map +1 -0
  95. package/dist/commands/extensions/configure.js +58 -0
  96. package/dist/commands/extensions/configure.js.map +1 -0
  97. package/dist/commands/extensions/container.d.ts +15 -0
  98. package/dist/commands/extensions/container.d.ts.map +1 -0
  99. package/dist/commands/extensions/container.js +135 -0
  100. package/dist/commands/extensions/container.js.map +1 -0
  101. package/dist/commands/extensions/context.d.ts +37 -0
  102. package/dist/commands/extensions/context.d.ts.map +1 -0
  103. package/dist/commands/extensions/context.js +72 -0
  104. package/dist/commands/extensions/context.js.map +1 -0
  105. package/dist/commands/extensions/enable.d.ts +6 -0
  106. package/dist/commands/extensions/enable.d.ts.map +1 -0
  107. package/dist/commands/extensions/enable.js +180 -0
  108. package/dist/commands/extensions/enable.js.map +1 -0
  109. package/dist/commands/extensions/environment.d.ts +74 -0
  110. package/dist/commands/extensions/environment.d.ts.map +1 -0
  111. package/dist/commands/extensions/environment.js +168 -0
  112. package/dist/commands/extensions/environment.js.map +1 -0
  113. package/dist/commands/extensions/feature-scan.d.ts +48 -0
  114. package/dist/commands/extensions/feature-scan.d.ts.map +1 -0
  115. package/dist/commands/extensions/feature-scan.js +156 -0
  116. package/dist/commands/extensions/feature-scan.js.map +1 -0
  117. package/dist/commands/extensions/invoke.d.ts +60 -0
  118. package/dist/commands/extensions/invoke.d.ts.map +1 -0
  119. package/dist/commands/extensions/invoke.js +275 -0
  120. package/dist/commands/extensions/invoke.js.map +1 -0
  121. package/dist/commands/extensions/list.d.ts +5 -0
  122. package/dist/commands/extensions/list.d.ts.map +1 -0
  123. package/dist/commands/extensions/list.js +125 -0
  124. package/dist/commands/extensions/list.js.map +1 -0
  125. package/dist/commands/extensions/logs.d.ts +5 -0
  126. package/dist/commands/extensions/logs.d.ts.map +1 -0
  127. package/dist/commands/extensions/logs.js +74 -0
  128. package/dist/commands/extensions/logs.js.map +1 -0
  129. package/dist/commands/extensions/provision.d.ts +36 -0
  130. package/dist/commands/extensions/provision.d.ts.map +1 -0
  131. package/dist/commands/extensions/provision.js +137 -0
  132. package/dist/commands/extensions/provision.js.map +1 -0
  133. package/dist/commands/extensions/remove.d.ts +5 -0
  134. package/dist/commands/extensions/remove.d.ts.map +1 -0
  135. package/dist/commands/extensions/remove.js +77 -0
  136. package/dist/commands/extensions/remove.js.map +1 -0
  137. package/dist/commands/extensions/render.d.ts +16 -0
  138. package/dist/commands/extensions/render.d.ts.map +1 -0
  139. package/dist/commands/extensions/render.js +25 -0
  140. package/dist/commands/extensions/render.js.map +1 -0
  141. package/dist/commands/extensions/run.d.ts +30 -0
  142. package/dist/commands/extensions/run.d.ts.map +1 -0
  143. package/dist/commands/extensions/run.js +292 -0
  144. package/dist/commands/extensions/run.js.map +1 -0
  145. package/dist/commands/extensions/secret-store.d.ts +15 -0
  146. package/dist/commands/extensions/secret-store.d.ts.map +1 -0
  147. package/dist/commands/extensions/secret-store.js +164 -0
  148. package/dist/commands/extensions/secret-store.js.map +1 -0
  149. package/dist/commands/extensions/setup.d.ts +17 -0
  150. package/dist/commands/extensions/setup.d.ts.map +1 -0
  151. package/dist/commands/extensions/setup.js +94 -0
  152. package/dist/commands/extensions/setup.js.map +1 -0
  153. package/dist/commands/extensions/source.d.ts +47 -0
  154. package/dist/commands/extensions/source.d.ts.map +1 -0
  155. package/dist/commands/extensions/source.js +142 -0
  156. package/dist/commands/extensions/source.js.map +1 -0
  157. package/dist/commands/extensions/state.d.ts +62 -0
  158. package/dist/commands/extensions/state.d.ts.map +1 -0
  159. package/dist/commands/extensions/state.js +177 -0
  160. package/dist/commands/extensions/state.js.map +1 -0
  161. package/dist/commands/extensions/status.d.ts +9 -0
  162. package/dist/commands/extensions/status.d.ts.map +1 -0
  163. package/dist/commands/extensions/status.js +239 -0
  164. package/dist/commands/extensions/status.js.map +1 -0
  165. package/dist/commands/extensions.d.ts +3 -0
  166. package/dist/commands/extensions.d.ts.map +1 -0
  167. package/dist/commands/extensions.js +223 -0
  168. package/dist/commands/extensions.js.map +1 -0
  169. package/dist/commands/flow/index.d.ts +3 -0
  170. package/dist/commands/flow/index.d.ts.map +1 -0
  171. package/dist/commands/flow/index.js +295 -0
  172. package/dist/commands/flow/index.js.map +1 -0
  173. package/dist/commands/flow/limits.d.ts +12 -0
  174. package/dist/commands/flow/limits.d.ts.map +1 -0
  175. package/dist/commands/flow/limits.js +13 -0
  176. package/dist/commands/flow/limits.js.map +1 -0
  177. package/dist/commands/flow/output.d.ts +8 -0
  178. package/dist/commands/flow/output.d.ts.map +1 -0
  179. package/dist/commands/flow/output.js +11 -0
  180. package/dist/commands/flow/output.js.map +1 -0
  181. package/dist/commands/flow/render.d.ts +51 -0
  182. package/dist/commands/flow/render.d.ts.map +1 -0
  183. package/dist/commands/flow/render.js +220 -0
  184. package/dist/commands/flow/render.js.map +1 -0
  185. package/dist/commands/flow/select.d.ts +31 -0
  186. package/dist/commands/flow/select.d.ts.map +1 -0
  187. package/dist/commands/flow/select.js +62 -0
  188. package/dist/commands/flow/select.js.map +1 -0
  189. package/dist/commands/graph/boundaries-input.d.ts +26 -0
  190. package/dist/commands/graph/boundaries-input.d.ts.map +1 -0
  191. package/dist/commands/graph/boundaries-input.js +54 -0
  192. package/dist/commands/graph/boundaries-input.js.map +1 -0
  193. package/dist/commands/graph/boundaries.d.ts +4 -0
  194. package/dist/commands/graph/boundaries.d.ts.map +1 -0
  195. package/dist/commands/graph/boundaries.js +141 -0
  196. package/dist/commands/graph/boundaries.js.map +1 -0
  197. package/dist/commands/graph/bounds.d.ts +16 -0
  198. package/dist/commands/graph/bounds.d.ts.map +1 -0
  199. package/dist/commands/graph/bounds.js +22 -0
  200. package/dist/commands/graph/bounds.js.map +1 -0
  201. package/dist/commands/graph/category-clusters.d.ts +20 -0
  202. package/dist/commands/graph/category-clusters.d.ts.map +1 -0
  203. package/dist/commands/graph/category-clusters.js +158 -0
  204. package/dist/commands/graph/category-clusters.js.map +1 -0
  205. package/dist/commands/graph/feature-3d.d.ts +22 -0
  206. package/dist/commands/graph/feature-3d.d.ts.map +1 -0
  207. package/dist/commands/graph/feature-3d.js +114 -0
  208. package/dist/commands/graph/feature-3d.js.map +1 -0
  209. package/dist/commands/graph/feature-clusters.d.ts +17 -0
  210. package/dist/commands/graph/feature-clusters.d.ts.map +1 -0
  211. package/dist/commands/graph/feature-clusters.js +94 -0
  212. package/dist/commands/graph/feature-clusters.js.map +1 -0
  213. package/dist/commands/graph/feature-html.d.ts +26 -0
  214. package/dist/commands/graph/feature-html.d.ts.map +1 -0
  215. package/dist/commands/graph/feature-html.js +314 -0
  216. package/dist/commands/graph/feature-html.js.map +1 -0
  217. package/dist/commands/graph/feature-map.d.ts +31 -0
  218. package/dist/commands/graph/feature-map.d.ts.map +1 -0
  219. package/dist/commands/graph/feature-map.js +217 -0
  220. package/dist/commands/graph/feature-map.js.map +1 -0
  221. package/dist/commands/graph/feature-model.d.ts +55 -0
  222. package/dist/commands/graph/feature-model.d.ts.map +1 -0
  223. package/dist/commands/graph/feature-model.js +167 -0
  224. package/dist/commands/graph/feature-model.js.map +1 -0
  225. package/dist/commands/graph/feature-untangle-motion.d.ts +33 -0
  226. package/dist/commands/graph/feature-untangle-motion.d.ts.map +1 -0
  227. package/dist/commands/graph/feature-untangle-motion.js +155 -0
  228. package/dist/commands/graph/feature-untangle-motion.js.map +1 -0
  229. package/dist/commands/graph/index.d.ts +3 -0
  230. package/dist/commands/graph/index.d.ts.map +1 -0
  231. package/dist/commands/graph/index.js +414 -0
  232. package/dist/commands/graph/index.js.map +1 -0
  233. package/dist/commands/graph/render.d.ts +63 -0
  234. package/dist/commands/graph/render.d.ts.map +1 -0
  235. package/dist/commands/graph/render.js +352 -0
  236. package/dist/commands/graph/render.js.map +1 -0
  237. package/dist/commands/graph/select.d.ts +34 -0
  238. package/dist/commands/graph/select.d.ts.map +1 -0
  239. package/dist/commands/graph/select.js +55 -0
  240. package/dist/commands/graph/select.js.map +1 -0
  241. package/dist/commands/index/index.d.ts +6 -0
  242. package/dist/commands/index/index.d.ts.map +1 -0
  243. package/dist/commands/index/index.js +461 -0
  244. package/dist/commands/index/index.js.map +1 -0
  245. package/dist/commands/index/render.d.ts +53 -0
  246. package/dist/commands/index/render.d.ts.map +1 -0
  247. package/dist/commands/index/render.js +205 -0
  248. package/dist/commands/index/render.js.map +1 -0
  249. package/dist/commands/index/target.d.ts +34 -0
  250. package/dist/commands/index/target.d.ts.map +1 -0
  251. package/dist/commands/index/target.js +97 -0
  252. package/dist/commands/index/target.js.map +1 -0
  253. package/dist/commands/index-watch.d.ts +30 -0
  254. package/dist/commands/index-watch.d.ts.map +1 -0
  255. package/dist/commands/index-watch.js +138 -0
  256. package/dist/commands/index-watch.js.map +1 -0
  257. package/dist/commands/init/command.d.ts +25 -0
  258. package/dist/commands/init/command.d.ts.map +1 -0
  259. package/dist/commands/init/command.js +198 -0
  260. package/dist/commands/init/command.js.map +1 -0
  261. package/dist/commands/init/config-draft.d.ts +48 -0
  262. package/dist/commands/init/config-draft.d.ts.map +1 -0
  263. package/dist/commands/init/config-draft.js +201 -0
  264. package/dist/commands/init/config-draft.js.map +1 -0
  265. package/dist/commands/init/diff.d.ts +33 -0
  266. package/dist/commands/init/diff.d.ts.map +1 -0
  267. package/dist/commands/init/diff.js +109 -0
  268. package/dist/commands/init/diff.js.map +1 -0
  269. package/dist/commands/init/http-probe.d.ts +26 -0
  270. package/dist/commands/init/http-probe.d.ts.map +1 -0
  271. package/dist/commands/init/http-probe.js +144 -0
  272. package/dist/commands/init/http-probe.js.map +1 -0
  273. package/dist/commands/init/ignore-rules.d.ts +70 -0
  274. package/dist/commands/init/ignore-rules.d.ts.map +1 -0
  275. package/dist/commands/init/ignore-rules.js +146 -0
  276. package/dist/commands/init/ignore-rules.js.map +1 -0
  277. package/dist/commands/init/index.d.ts +33 -0
  278. package/dist/commands/init/index.d.ts.map +1 -0
  279. package/dist/commands/init/index.js +32 -0
  280. package/dist/commands/init/index.js.map +1 -0
  281. package/dist/commands/init/integrations-apply.d.ts +50 -0
  282. package/dist/commands/init/integrations-apply.d.ts.map +1 -0
  283. package/dist/commands/init/integrations-apply.js +452 -0
  284. package/dist/commands/init/integrations-apply.js.map +1 -0
  285. package/dist/commands/init/integrations-plan.d.ts +68 -0
  286. package/dist/commands/init/integrations-plan.d.ts.map +1 -0
  287. package/dist/commands/init/integrations-plan.js +515 -0
  288. package/dist/commands/init/integrations-plan.js.map +1 -0
  289. package/dist/commands/init/integrations.d.ts +5 -0
  290. package/dist/commands/init/integrations.d.ts.map +1 -0
  291. package/dist/commands/init/integrations.js +4 -0
  292. package/dist/commands/init/integrations.js.map +1 -0
  293. package/dist/commands/init/languages.d.ts +55 -0
  294. package/dist/commands/init/languages.d.ts.map +1 -0
  295. package/dist/commands/init/languages.js +245 -0
  296. package/dist/commands/init/languages.js.map +1 -0
  297. package/dist/commands/init/product-context.d.ts +63 -0
  298. package/dist/commands/init/product-context.d.ts.map +1 -0
  299. package/dist/commands/init/product-context.js +390 -0
  300. package/dist/commands/init/product-context.js.map +1 -0
  301. package/dist/commands/init/render.d.ts +38 -0
  302. package/dist/commands/init/render.d.ts.map +1 -0
  303. package/dist/commands/init/render.js +501 -0
  304. package/dist/commands/init/render.js.map +1 -0
  305. package/dist/commands/init/report.d.ts +24 -0
  306. package/dist/commands/init/report.d.ts.map +1 -0
  307. package/dist/commands/init/report.js +163 -0
  308. package/dist/commands/init/report.js.map +1 -0
  309. package/dist/commands/init/run.d.ts +71 -0
  310. package/dist/commands/init/run.d.ts.map +1 -0
  311. package/dist/commands/init/run.js +253 -0
  312. package/dist/commands/init/run.js.map +1 -0
  313. package/dist/commands/init/services.d.ts +82 -0
  314. package/dist/commands/init/services.d.ts.map +1 -0
  315. package/dist/commands/init/services.js +209 -0
  316. package/dist/commands/init/services.js.map +1 -0
  317. package/dist/commands/init/storage.d.ts +8 -0
  318. package/dist/commands/init/storage.d.ts.map +1 -0
  319. package/dist/commands/init/storage.js +102 -0
  320. package/dist/commands/init/storage.js.map +1 -0
  321. package/dist/commands/init/toml.d.ts +65 -0
  322. package/dist/commands/init/toml.d.ts.map +1 -0
  323. package/dist/commands/init/toml.js +159 -0
  324. package/dist/commands/init/toml.js.map +1 -0
  325. package/dist/commands/init/topology.d.ts +54 -0
  326. package/dist/commands/init/topology.d.ts.map +1 -0
  327. package/dist/commands/init/topology.js +146 -0
  328. package/dist/commands/init/topology.js.map +1 -0
  329. package/dist/commands/init/types.d.ts +334 -0
  330. package/dist/commands/init/types.d.ts.map +1 -0
  331. package/dist/commands/init/types.js +31 -0
  332. package/dist/commands/init/types.js.map +1 -0
  333. package/dist/commands/init/wizard-terminal.d.ts +36 -0
  334. package/dist/commands/init/wizard-terminal.d.ts.map +1 -0
  335. package/dist/commands/init/wizard-terminal.js +163 -0
  336. package/dist/commands/init/wizard-terminal.js.map +1 -0
  337. package/dist/commands/init/wizard.d.ts +25 -0
  338. package/dist/commands/init/wizard.d.ts.map +1 -0
  339. package/dist/commands/init/wizard.js +358 -0
  340. package/dist/commands/init/wizard.js.map +1 -0
  341. package/dist/commands/mcp.d.ts +4 -0
  342. package/dist/commands/mcp.d.ts.map +1 -0
  343. package/dist/commands/mcp.js +111 -0
  344. package/dist/commands/mcp.js.map +1 -0
  345. package/dist/commands/product-test-runner.d.ts +4 -0
  346. package/dist/commands/product-test-runner.d.ts.map +1 -0
  347. package/dist/commands/product-test-runner.js +85 -0
  348. package/dist/commands/product-test-runner.js.map +1 -0
  349. package/dist/commands/product.d.ts +16 -0
  350. package/dist/commands/product.d.ts.map +1 -0
  351. package/dist/commands/product.js +262 -0
  352. package/dist/commands/product.js.map +1 -0
  353. package/dist/commands/query.d.ts +114 -0
  354. package/dist/commands/query.d.ts.map +1 -0
  355. package/dist/commands/query.js +783 -0
  356. package/dist/commands/query.js.map +1 -0
  357. package/dist/commands/scan.d.ts +10 -0
  358. package/dist/commands/scan.d.ts.map +1 -0
  359. package/dist/commands/scan.js +302 -0
  360. package/dist/commands/scan.js.map +1 -0
  361. package/dist/commands/sdd.d.ts +24 -0
  362. package/dist/commands/sdd.d.ts.map +1 -0
  363. package/dist/commands/sdd.js +195 -0
  364. package/dist/commands/sdd.js.map +1 -0
  365. package/dist/commands/unavailable.d.ts +40 -0
  366. package/dist/commands/unavailable.d.ts.map +1 -0
  367. package/dist/commands/unavailable.js +73 -0
  368. package/dist/commands/unavailable.js.map +1 -0
  369. package/dist/commands/watch/analyze.d.ts +69 -0
  370. package/dist/commands/watch/analyze.d.ts.map +1 -0
  371. package/dist/commands/watch/analyze.js +402 -0
  372. package/dist/commands/watch/analyze.js.map +1 -0
  373. package/dist/commands/watch/cli.d.ts +8 -0
  374. package/dist/commands/watch/cli.d.ts.map +1 -0
  375. package/dist/commands/watch/cli.js +97 -0
  376. package/dist/commands/watch/cli.js.map +1 -0
  377. package/dist/commands/watch/delta.d.ts +46 -0
  378. package/dist/commands/watch/delta.d.ts.map +1 -0
  379. package/dist/commands/watch/delta.js +170 -0
  380. package/dist/commands/watch/delta.js.map +1 -0
  381. package/dist/commands/watch/events.d.ts +214 -0
  382. package/dist/commands/watch/events.d.ts.map +1 -0
  383. package/dist/commands/watch/events.js +13 -0
  384. package/dist/commands/watch/events.js.map +1 -0
  385. package/dist/commands/watch/index.d.ts +19 -0
  386. package/dist/commands/watch/index.d.ts.map +1 -0
  387. package/dist/commands/watch/index.js +15 -0
  388. package/dist/commands/watch/index.js.map +1 -0
  389. package/dist/commands/watch/options.d.ts +43 -0
  390. package/dist/commands/watch/options.d.ts.map +1 -0
  391. package/dist/commands/watch/options.js +193 -0
  392. package/dist/commands/watch/options.js.map +1 -0
  393. package/dist/commands/watch/render.d.ts +26 -0
  394. package/dist/commands/watch/render.d.ts.map +1 -0
  395. package/dist/commands/watch/render.js +175 -0
  396. package/dist/commands/watch/render.js.map +1 -0
  397. package/dist/commands/watch/run.d.ts +14 -0
  398. package/dist/commands/watch/run.d.ts.map +1 -0
  399. package/dist/commands/watch/run.js +460 -0
  400. package/dist/commands/watch/run.js.map +1 -0
  401. package/dist/commands/watch/runtime.d.ts +67 -0
  402. package/dist/commands/watch/runtime.d.ts.map +1 -0
  403. package/dist/commands/watch/runtime.js +149 -0
  404. package/dist/commands/watch/runtime.js.map +1 -0
  405. package/dist/commands/watch-command.d.ts +3 -0
  406. package/dist/commands/watch-command.d.ts.map +1 -0
  407. package/dist/commands/watch-command.js +273 -0
  408. package/dist/commands/watch-command.js.map +1 -0
  409. package/dist/entry-point.d.ts +11 -0
  410. package/dist/entry-point.d.ts.map +1 -0
  411. package/dist/entry-point.js +65 -0
  412. package/dist/entry-point.js.map +1 -0
  413. package/dist/index.d.ts +38 -0
  414. package/dist/index.d.ts.map +1 -0
  415. package/dist/index.js +245 -0
  416. package/dist/index.js.map +1 -0
  417. package/dist/mcp/boundaries-schema.d.ts +262 -0
  418. package/dist/mcp/boundaries-schema.d.ts.map +1 -0
  419. package/dist/mcp/boundaries-schema.js +183 -0
  420. package/dist/mcp/boundaries-schema.js.map +1 -0
  421. package/dist/mcp/default-runtime.d.ts +16 -0
  422. package/dist/mcp/default-runtime.d.ts.map +1 -0
  423. package/dist/mcp/default-runtime.js +718 -0
  424. package/dist/mcp/default-runtime.js.map +1 -0
  425. package/dist/mcp/envelope.d.ts +13 -0
  426. package/dist/mcp/envelope.d.ts.map +1 -0
  427. package/dist/mcp/envelope.js +29 -0
  428. package/dist/mcp/envelope.js.map +1 -0
  429. package/dist/mcp/index.d.ts +8 -0
  430. package/dist/mcp/index.d.ts.map +1 -0
  431. package/dist/mcp/index.js +8 -0
  432. package/dist/mcp/index.js.map +1 -0
  433. package/dist/mcp/output-schemas.d.ts +5928 -0
  434. package/dist/mcp/output-schemas.d.ts.map +1 -0
  435. package/dist/mcp/output-schemas.js +2814 -0
  436. package/dist/mcp/output-schemas.js.map +1 -0
  437. package/dist/mcp/path-sandbox.d.ts +35 -0
  438. package/dist/mcp/path-sandbox.d.ts.map +1 -0
  439. package/dist/mcp/path-sandbox.js +128 -0
  440. package/dist/mcp/path-sandbox.js.map +1 -0
  441. package/dist/mcp/server.d.ts +155 -0
  442. package/dist/mcp/server.d.ts.map +1 -0
  443. package/dist/mcp/server.js +257 -0
  444. package/dist/mcp/server.js.map +1 -0
  445. package/dist/mcp/stdio.d.ts +20 -0
  446. package/dist/mcp/stdio.d.ts.map +1 -0
  447. package/dist/mcp/stdio.js +71 -0
  448. package/dist/mcp/stdio.js.map +1 -0
  449. package/dist/mcp/tools.d.ts +355 -0
  450. package/dist/mcp/tools.d.ts.map +1 -0
  451. package/dist/mcp/tools.js +319 -0
  452. package/dist/mcp/tools.js.map +1 -0
  453. package/dist/mcp/types.d.ts +15 -0
  454. package/dist/mcp/types.d.ts.map +1 -0
  455. package/dist/mcp/types.js +45 -0
  456. package/dist/mcp/types.js.map +1 -0
  457. package/package.json +99 -3
  458. package/src/cli/args.ts +231 -0
  459. package/src/cli/command.ts +146 -0
  460. package/src/cli/deadline.ts +56 -0
  461. package/src/cli/embedder-deadline.ts +187 -0
  462. package/src/cli/exit.ts +94 -0
  463. package/src/cli/graphs.ts +191 -0
  464. package/src/cli/index-freshness.ts +303 -0
  465. package/src/cli/index-refresh.ts +125 -0
  466. package/src/cli/index-state.ts +1217 -0
  467. package/src/cli/io.ts +56 -0
  468. package/src/cli/language-support.ts +203 -0
  469. package/src/cli/renewing-lease.ts +121 -0
  470. package/src/cli/search-graph-enrichment.ts +639 -0
  471. package/src/cli/system.ts +94 -0
  472. package/src/cli/vector-store-policy.ts +213 -0
  473. package/src/cli/version.ts +2 -0
  474. package/src/cli/workspace.ts +324 -0
  475. package/src/commands/complexity.ts +776 -0
  476. package/src/commands/doctor.languages.ts +187 -0
  477. package/src/commands/doctor.storage.ts +124 -0
  478. package/src/commands/doctor.ts +946 -0
  479. package/src/commands/extensions/add.ts +312 -0
  480. package/src/commands/extensions/configure.ts +82 -0
  481. package/src/commands/extensions/container.ts +209 -0
  482. package/src/commands/extensions/context.ts +109 -0
  483. package/src/commands/extensions/enable.ts +237 -0
  484. package/src/commands/extensions/environment.ts +218 -0
  485. package/src/commands/extensions/feature-scan.ts +232 -0
  486. package/src/commands/extensions/invoke.ts +368 -0
  487. package/src/commands/extensions/list.ts +158 -0
  488. package/src/commands/extensions/logs.ts +104 -0
  489. package/src/commands/extensions/provision.ts +206 -0
  490. package/src/commands/extensions/remove.ts +110 -0
  491. package/src/commands/extensions/render.ts +32 -0
  492. package/src/commands/extensions/run.ts +386 -0
  493. package/src/commands/extensions/secret-store.ts +223 -0
  494. package/src/commands/extensions/setup.ts +140 -0
  495. package/src/commands/extensions/source.ts +189 -0
  496. package/src/commands/extensions/state.ts +252 -0
  497. package/src/commands/extensions/status.ts +320 -0
  498. package/src/commands/extensions.ts +280 -0
  499. package/src/commands/flow/index.ts +402 -0
  500. package/src/commands/flow/limits.ts +14 -0
  501. package/src/commands/flow/output.ts +16 -0
  502. package/src/commands/flow/render.ts +318 -0
  503. package/src/commands/flow/select.ts +101 -0
  504. package/src/commands/graph/boundaries-input.ts +63 -0
  505. package/src/commands/graph/boundaries.ts +182 -0
  506. package/src/commands/graph/bounds.ts +25 -0
  507. package/src/commands/graph/category-clusters.ts +194 -0
  508. package/src/commands/graph/feature-3d.ts +141 -0
  509. package/src/commands/graph/feature-clusters.ts +125 -0
  510. package/src/commands/graph/feature-html.ts +336 -0
  511. package/src/commands/graph/feature-map.ts +270 -0
  512. package/src/commands/graph/feature-model.ts +234 -0
  513. package/src/commands/graph/feature-untangle-motion.ts +192 -0
  514. package/src/commands/graph/index.ts +562 -0
  515. package/src/commands/graph/render.ts +503 -0
  516. package/src/commands/graph/select.ts +77 -0
  517. package/src/commands/index/index.ts +595 -0
  518. package/src/commands/index/render.ts +325 -0
  519. package/src/commands/index/target.ts +136 -0
  520. package/src/commands/index-watch.ts +206 -0
  521. package/src/commands/init/command.ts +238 -0
  522. package/src/commands/init/config-draft.ts +235 -0
  523. package/src/commands/init/diff.ts +117 -0
  524. package/src/commands/init/http-probe.ts +150 -0
  525. package/src/commands/init/ignore-rules.ts +170 -0
  526. package/src/commands/init/index.ts +63 -0
  527. package/src/commands/init/integrations-apply.ts +618 -0
  528. package/src/commands/init/integrations-plan.ts +634 -0
  529. package/src/commands/init/integrations.ts +8 -0
  530. package/src/commands/init/languages.ts +320 -0
  531. package/src/commands/init/product-context.ts +576 -0
  532. package/src/commands/init/render.ts +598 -0
  533. package/src/commands/init/report.ts +204 -0
  534. package/src/commands/init/run.ts +349 -0
  535. package/src/commands/init/services.ts +271 -0
  536. package/src/commands/init/storage.ts +136 -0
  537. package/src/commands/init/toml.ts +174 -0
  538. package/src/commands/init/topology.ts +192 -0
  539. package/src/commands/init/types.ts +366 -0
  540. package/src/commands/init/wizard-terminal.ts +206 -0
  541. package/src/commands/init/wizard.ts +450 -0
  542. package/src/commands/mcp.ts +123 -0
  543. package/src/commands/product-test-runner.ts +80 -0
  544. package/src/commands/product.ts +331 -0
  545. package/src/commands/query.ts +1032 -0
  546. package/src/commands/scan.ts +360 -0
  547. package/src/commands/sdd.ts +243 -0
  548. package/src/commands/unavailable.ts +92 -0
  549. package/src/commands/watch/README.md +160 -0
  550. package/src/commands/watch/analyze.ts +600 -0
  551. package/src/commands/watch/cli.ts +108 -0
  552. package/src/commands/watch/delta.ts +186 -0
  553. package/src/commands/watch/events.ts +235 -0
  554. package/src/commands/watch/index.ts +53 -0
  555. package/src/commands/watch/options.ts +234 -0
  556. package/src/commands/watch/render.ts +240 -0
  557. package/src/commands/watch/run.ts +553 -0
  558. package/src/commands/watch/runtime.ts +167 -0
  559. package/src/commands/watch-command.ts +294 -0
  560. package/src/entry-point.ts +67 -0
  561. package/src/index.ts +291 -0
  562. package/src/mcp/boundaries-schema.ts +193 -0
  563. package/src/mcp/default-runtime.ts +1034 -0
  564. package/src/mcp/envelope.ts +57 -0
  565. package/src/mcp/index.ts +28 -0
  566. package/src/mcp/output-schemas.ts +3071 -0
  567. package/src/mcp/path-sandbox.ts +156 -0
  568. package/src/mcp/server.ts +358 -0
  569. package/src/mcp/stdio.ts +92 -0
  570. package/src/mcp/tools.ts +563 -0
  571. package/src/mcp/types.ts +66 -0
@@ -0,0 +1,140 @@
1
+ /** Runs a user-supplied setup provider after consent, ownership and digest checks. */
2
+ import type { ExtensionManifestV1 } from "@untangle-code/domain";
3
+ import {
4
+ isLoopbackUrl,
5
+ type ProcessLimitsV1,
6
+ type ProcessRunnerPort,
7
+ } from "@untangle-code/extension-runtime";
8
+
9
+ import type { ExtensionEnvironmentV1 } from "./environment.js";
10
+ import { primaryHostPort, type ProvisionResultV1 } from "./provision.js";
11
+ import {
12
+ credentialEndpoint,
13
+ parseSecretValues,
14
+ readStoredSecrets,
15
+ secretEnvironment,
16
+ withSecretLock,
17
+ writeStoredSecrets,
18
+ } from "./secret-store.js";
19
+
20
+ export function missingAnalyzerSecrets(
21
+ manifest: ExtensionManifestV1,
22
+ env: Readonly<Record<string, string | undefined>>,
23
+ ): string[] {
24
+ return manifest.secrets
25
+ .filter(
26
+ (secret) =>
27
+ !secret.setupOnly &&
28
+ (secret.required || secret.name === manifest.http?.authSecretName) &&
29
+ !env[secret.envVar],
30
+ )
31
+ .map((secret) => secret.name);
32
+ }
33
+
34
+ export async function setupCredentials(input: {
35
+ environment: ExtensionEnvironmentV1;
36
+ manifest: ExtensionManifestV1;
37
+ provision?: ProvisionResultV1;
38
+ consent: boolean;
39
+ url?: string;
40
+ processRunner: ProcessRunnerPort;
41
+ limits: ProcessLimitsV1;
42
+ signal?: AbortSignal;
43
+ }): Promise<Record<string, string | undefined>> {
44
+ const { environment, manifest, provision } = input;
45
+ const setup = manifest.setup;
46
+ if (!input.consent) throw new Error("Credential setup requires --yes.");
47
+ if (
48
+ !setup ||
49
+ !manifest.container ||
50
+ !provision?.healthy ||
51
+ !provision.state.running ||
52
+ !provision.state.ownedByUntangle ||
53
+ provision.state.imageDigest !== manifest.container.digest
54
+ ) {
55
+ throw new Error(
56
+ "Credential setup requires a healthy, owned container whose digest matches the manifest.",
57
+ );
58
+ }
59
+ const url = input.url ?? manifest.http?.defaultUrl;
60
+ if (
61
+ !url ||
62
+ !isLoopbackUrl(url) ||
63
+ credentialEndpoint(url) !== credentialEndpoint(manifest.http?.defaultUrl)
64
+ ) {
65
+ throw new Error(
66
+ "Credential setup only uses the declared loopback endpoint of the managed container.",
67
+ );
68
+ }
69
+ const endpoint = new URL(url);
70
+ if (
71
+ Number(endpoint.port || (endpoint.protocol === "https:" ? 443 : 80)) !==
72
+ primaryHostPort(manifest)
73
+ ) {
74
+ throw new Error("Credential setup endpoint must match the managed container's published port.");
75
+ }
76
+ return withSecretLock(environment, manifest.id, async () => {
77
+ input.signal?.throwIfAborted();
78
+ const stored = await readStoredSecrets(environment, manifest, url);
79
+ const effectiveEnv = secretEnvironment(environment, manifest, stored);
80
+ if (missingAnalyzerSecrets(manifest, effectiveEnv).length === 0) return effectiveEnv;
81
+ const env: Record<string, string> = {
82
+ PATH: environment.env["PATH"] ?? "",
83
+ UNTANGLE_SETUP_URL: url,
84
+ UNTANGLE_SETUP_ID: manifest.id,
85
+ };
86
+ for (const name of ["HOME", "LANG"]) {
87
+ const value = environment.env[name];
88
+ if (value !== undefined) env[name] = value;
89
+ }
90
+ for (const secret of manifest.secrets) {
91
+ const value = effectiveEnv[secret.envVar];
92
+ if (value) env[secret.envVar] = value;
93
+ }
94
+ const result = await input.processRunner.run(
95
+ {
96
+ command: setup.command,
97
+ args: setup.args,
98
+ cwd: environment.userDataDir,
99
+ env,
100
+ },
101
+ {
102
+ ...input.limits,
103
+ timeoutMs: Math.min(input.limits.timeoutMs, 120_000),
104
+ maxOutputBytes: 1_048_576,
105
+ },
106
+ input.signal === undefined ? {} : { signal: input.signal },
107
+ );
108
+ input.signal?.throwIfAborted();
109
+ // Neither stdout nor stderr may appear in diagnostics: both can contain freshly issued secrets.
110
+ if (result.outcome !== "completed" || result.exitCode !== 0 || result.stdoutTruncated) {
111
+ throw new Error(
112
+ `Credential setup provider failed (${result.outcome}, exit ${String(result.exitCode)}). Check the configured administrator credentials and service availability.`,
113
+ );
114
+ }
115
+ let response: unknown;
116
+ try {
117
+ response = JSON.parse(result.stdout);
118
+ } catch {
119
+ throw new Error("Credential setup provider returned invalid JSON; output was withheld.");
120
+ }
121
+ if (
122
+ response === null ||
123
+ typeof response !== "object" ||
124
+ !("schemaVersion" in response) ||
125
+ response.schemaVersion !== 1 ||
126
+ !("secrets" in response)
127
+ ) {
128
+ throw new Error(
129
+ "Credential setup provider must return schemaVersion 1 and declared secrets; output was withheld.",
130
+ );
131
+ }
132
+ const generated = parseSecretValues(response.secrets, manifest);
133
+ const combined = { ...stored, ...generated };
134
+ const resolved = secretEnvironment(environment, manifest, combined);
135
+ if (missingAnalyzerSecrets(manifest, resolved).length > 0)
136
+ throw new Error("Credential setup provider did not supply the required analyzer secrets.");
137
+ await writeStoredSecrets(environment, manifest, combined, url);
138
+ return resolved;
139
+ });
140
+ }
@@ -0,0 +1,189 @@
1
+ /**
2
+ * Where an `add` gets its manifest from, and what it must prove first.
3
+ *
4
+ * A manifest is a description of how to start a program. Fetching one over
5
+ * the network and writing it into the user profile is therefore a supply-chain
6
+ * step, and it is treated like one:
7
+ *
8
+ * - **https only.** Plain http would let anyone on the path replace the
9
+ * invocation. There is no `--insecure` escape hatch; a local copy plus
10
+ * `--from <path>` is the supported answer for an internal http host.
11
+ * - **`--digest` is mandatory for a URL.** Without it, "the file at this URL"
12
+ * is not a fixed artifact — it is whatever the server serves today. This is
13
+ * the same reason X6 forbids moving image tags: an artifact that can change
14
+ * under a stable name changes findings silently.
15
+ * - **A size ceiling.** A manifest is a small TOML file; an endless response
16
+ * must not become an endless allocation.
17
+ *
18
+ * The digest is sha256 over the RAW BYTES, which is exactly what
19
+ * `shasum -a 256 <file>` and `sha256sum <file>` print — so the value a
20
+ * publisher advertises can be verified by hand.
21
+ */
22
+ import { createHash } from "node:crypto";
23
+
24
+ import type { FileSystemPort } from "@untangle-code/domain";
25
+ import { MANIFEST_FILE_NAME } from "@untangle-code/extension-runtime";
26
+
27
+ /** Largest manifest this CLI will accept from a URL. */
28
+ export const MAX_MANIFEST_BYTES = 256 * 1024;
29
+
30
+ /** Network read budget for one manifest fetch. */
31
+ export const FETCH_TIMEOUT_MS = 30_000;
32
+
33
+ export const DIGEST_PATTERN = /^sha256:[0-9a-f]{64}$/;
34
+
35
+ export interface ManifestSourceV1 {
36
+ kind: "path" | "url";
37
+ /** What the user typed, for the report. */
38
+ requested: string;
39
+ /** Absolute path or final URL the bytes actually came from. */
40
+ resolved: string;
41
+ bytes: Uint8Array;
42
+ text: string;
43
+ /** `sha256:<64 hex>` over `bytes`. */
44
+ digest: string;
45
+ }
46
+
47
+ export class ManifestSourceError extends Error {
48
+ public constructor(message: string) {
49
+ super(message);
50
+ this.name = "ManifestSourceError";
51
+ }
52
+ }
53
+
54
+ /** True when the argument looks like a URL rather than a path. */
55
+ export function isUrlSource(from: string): boolean {
56
+ return /^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//.test(from);
57
+ }
58
+
59
+ export function digestOf(bytes: Uint8Array): string {
60
+ return `sha256:${createHash("sha256").update(bytes).digest("hex")}`;
61
+ }
62
+
63
+ export interface FetchManifestOptions {
64
+ /** Injected so unit tests never touch the network (CONTRIBUTING, §13). */
65
+ fetchImpl?: typeof fetch;
66
+ maxBytes?: number;
67
+ timeoutMs?: number;
68
+ signal?: AbortSignal;
69
+ }
70
+
71
+ /**
72
+ * Reads a manifest from a local path.
73
+ *
74
+ * `path` may be the manifest file or the directory containing it; the same
75
+ * convenience `loadExtensionFrom` offers, applied to the raw bytes so the
76
+ * digest is computed over the file that will actually be installed.
77
+ */
78
+ export async function readManifestFromPath(
79
+ fs: FileSystemPort,
80
+ path: string,
81
+ ): Promise<ManifestSourceV1> {
82
+ const stat = await fs.stat(path);
83
+ if (stat === null) {
84
+ throw new ManifestSourceError(`no such file or directory: "${path}"`);
85
+ }
86
+ const filePath = stat.kind === "directory" ? `${path}/${MANIFEST_FILE_NAME}` : path;
87
+ let bytes: Uint8Array;
88
+ try {
89
+ bytes = await fs.readFile(filePath);
90
+ } catch (cause) {
91
+ throw new ManifestSourceError(
92
+ `cannot read "${filePath}": ${cause instanceof Error ? cause.message : String(cause)}`,
93
+ );
94
+ }
95
+ return {
96
+ kind: "path",
97
+ requested: path,
98
+ resolved: filePath,
99
+ bytes,
100
+ text: new TextDecoder("utf-8", { fatal: false }).decode(bytes),
101
+ digest: digestOf(bytes),
102
+ };
103
+ }
104
+
105
+ /**
106
+ * Downloads a manifest over https.
107
+ *
108
+ * Redirects are followed but the FINAL url is reported, so a redirect never
109
+ * hides where the bytes came from. The mandatory `--digest` check happens in
110
+ * the caller, against whatever this returns.
111
+ */
112
+ export async function fetchManifestFromUrl(
113
+ url: string,
114
+ options: FetchManifestOptions = {},
115
+ ): Promise<ManifestSourceV1> {
116
+ const parsed = safeParseUrl(url);
117
+ if (parsed === null) {
118
+ throw new ManifestSourceError(`"${url}" is not a valid URL`);
119
+ }
120
+ if (parsed.protocol !== "https:") {
121
+ throw new ManifestSourceError(
122
+ `refusing to download a manifest over "${parsed.protocol}//" — ` +
123
+ "a manifest describes how to start a program, so the transport must be authenticated. " +
124
+ "Download it yourself and install the local copy with --from <path>",
125
+ );
126
+ }
127
+
128
+ const fetchImpl = options.fetchImpl ?? fetch;
129
+ const maxBytes = options.maxBytes ?? MAX_MANIFEST_BYTES;
130
+ const controller = new AbortController();
131
+ const timer = setTimeout(() => {
132
+ controller.abort();
133
+ }, options.timeoutMs ?? FETCH_TIMEOUT_MS);
134
+ options.signal?.addEventListener("abort", () => {
135
+ controller.abort();
136
+ });
137
+
138
+ try {
139
+ const response = await fetchImpl(parsed.toString(), {
140
+ redirect: "follow",
141
+ signal: controller.signal,
142
+ headers: { accept: "text/plain, application/toml, */*" },
143
+ });
144
+ if (!response.ok) {
145
+ throw new ManifestSourceError(
146
+ `${parsed.toString()} answered HTTP ${String(response.status)}; no manifest was installed`,
147
+ );
148
+ }
149
+ const buffer = new Uint8Array(await response.arrayBuffer());
150
+ if (buffer.byteLength > maxBytes) {
151
+ throw new ManifestSourceError(
152
+ `the response is ${String(buffer.byteLength)} bytes, above the ${String(maxBytes)}-byte ` +
153
+ "ceiling for a manifest; nothing was installed",
154
+ );
155
+ }
156
+ const resolved =
157
+ typeof response.url === "string" && response.url !== "" ? response.url : parsed.toString();
158
+ return {
159
+ kind: "url",
160
+ requested: url,
161
+ resolved,
162
+ bytes: buffer,
163
+ text: new TextDecoder("utf-8", { fatal: false }).decode(buffer),
164
+ digest: digestOf(buffer),
165
+ };
166
+ } catch (cause) {
167
+ if (cause instanceof ManifestSourceError) {
168
+ throw cause;
169
+ }
170
+ if (controller.signal.aborted) {
171
+ throw new ManifestSourceError(
172
+ `downloading ${parsed.toString()} exceeded the ${String(options.timeoutMs ?? FETCH_TIMEOUT_MS)} ms budget`,
173
+ );
174
+ }
175
+ throw new ManifestSourceError(
176
+ `cannot download ${parsed.toString()}: ${cause instanceof Error ? cause.message : String(cause)}`,
177
+ );
178
+ } finally {
179
+ clearTimeout(timer);
180
+ }
181
+ }
182
+
183
+ function safeParseUrl(url: string): URL | null {
184
+ try {
185
+ return new URL(url);
186
+ } catch {
187
+ return null;
188
+ }
189
+ }
@@ -0,0 +1,252 @@
1
+ /**
2
+ * Persisted user-level state for the extension surface.
3
+ *
4
+ * Two files, both in the OS user data directory and never in a project
5
+ * directory (extensions.md §9.2):
6
+ *
7
+ * - `license-acknowledgments.json` — the personal declarations that satisfy
8
+ * the license gate. Read by the runtime, written here.
9
+ * - `cli-state.json` — which extensions the user enabled, and a summary of
10
+ * the last run per extension, so `list` can answer "status, last run"
11
+ * without re-running anything.
12
+ *
13
+ * Both are written temp-then-rename. A half-written acknowledgment file would
14
+ * read back as "nothing acknowledged", which is safe, but a half-written run
15
+ * record would silently lose the previous one.
16
+ */
17
+ import { dirname, join } from "node:path";
18
+
19
+ import type { FileSystemPort } from "@untangle-code/domain";
20
+ import { compareCodepoints } from "@untangle-code/domain";
21
+ import {
22
+ ACKNOWLEDGMENT_FILE_NAME,
23
+ acknowledgmentFilePath,
24
+ type ExtensionRunV1,
25
+ type LicenseAcknowledgmentFileV1,
26
+ type LicenseAcknowledgmentV1,
27
+ } from "@untangle-code/extension-runtime";
28
+
29
+ /** File name of the CLI's own state, next to the acknowledgment file. */
30
+ export const CLI_STATE_FILE_NAME = "cli-state.json";
31
+
32
+ /** Summary of one finished run — enough for `list`, not a substitute for it. */
33
+ export interface LastRunRecordV1 {
34
+ runId: string;
35
+ startedAt: string;
36
+ finishedAt?: string;
37
+ exitStatus: ExtensionRunV1["exitStatus"];
38
+ findingsTotal: number;
39
+ errorCode?: string;
40
+ }
41
+
42
+ export interface CliStateV1 {
43
+ schemaVersion: 1;
44
+ /** Extension ids the user enabled (X1: enabling starts nothing). */
45
+ enabled: string[];
46
+ lastRuns: Record<string, LastRunRecordV1>;
47
+ }
48
+
49
+ export function summarizeRun(run: ExtensionRunV1): LastRunRecordV1 {
50
+ return {
51
+ runId: run.runId,
52
+ startedAt: run.startedAt,
53
+ ...(run.finishedAt === undefined ? {} : { finishedAt: run.finishedAt }),
54
+ exitStatus: run.exitStatus,
55
+ findingsTotal: run.findingsTotal,
56
+ ...(run.errorCode === undefined ? {} : { errorCode: run.errorCode }),
57
+ };
58
+ }
59
+
60
+ export function emptyCliState(): CliStateV1 {
61
+ return { schemaVersion: 1, enabled: [], lastRuns: {} };
62
+ }
63
+
64
+ export function cliStatePath(userDataDirectory: string): string {
65
+ return join(userDataDirectory, "extensions", CLI_STATE_FILE_NAME);
66
+ }
67
+
68
+ /** Result of reading a state file: the state plus anything unreadable (E4). */
69
+ export interface LoadedCliStateV1 {
70
+ state: CliStateV1;
71
+ warnings: string[];
72
+ }
73
+
74
+ /**
75
+ * Reads the CLI state. A missing file means "nothing enabled, nothing run" —
76
+ * a valid starting state, not an error. A corrupt file is reported and
77
+ * treated as empty rather than crashing the command (X2).
78
+ */
79
+ export async function loadCliState(
80
+ fs: FileSystemPort,
81
+ userDataDirectory: string,
82
+ ): Promise<LoadedCliStateV1> {
83
+ const path = cliStatePath(userDataDirectory);
84
+ let text: string;
85
+ try {
86
+ text = await fs.readTextFile(path);
87
+ } catch {
88
+ return { state: emptyCliState(), warnings: [] };
89
+ }
90
+ let document: unknown;
91
+ try {
92
+ document = JSON.parse(text) as unknown;
93
+ } catch (cause) {
94
+ return {
95
+ state: emptyCliState(),
96
+ warnings: [
97
+ `"${path}" is not valid JSON (${cause instanceof Error ? cause.message : String(cause)}); ` +
98
+ "enabled flags and last-run records are shown as unknown until the file is repaired",
99
+ ],
100
+ };
101
+ }
102
+ if (typeof document !== "object" || document === null || Array.isArray(document)) {
103
+ return { state: emptyCliState(), warnings: [`"${path}" is not a JSON object; ignored`] };
104
+ }
105
+ const record = document as Record<string, unknown>;
106
+ const enabled = Array.isArray(record["enabled"])
107
+ ? record["enabled"].filter((entry): entry is string => typeof entry === "string")
108
+ : [];
109
+ const lastRuns: Record<string, LastRunRecordV1> = {};
110
+ const rawRuns = record["lastRuns"];
111
+ if (typeof rawRuns === "object" && rawRuns !== null && !Array.isArray(rawRuns)) {
112
+ for (const [id, value] of Object.entries(rawRuns as Record<string, unknown>)) {
113
+ const parsed = readLastRun(value);
114
+ if (parsed !== null) {
115
+ lastRuns[id] = parsed;
116
+ }
117
+ }
118
+ }
119
+ return {
120
+ state: { schemaVersion: 1, enabled: [...enabled].sort(compareCodepoints), lastRuns },
121
+ warnings: [],
122
+ };
123
+ }
124
+
125
+ function readLastRun(value: unknown): LastRunRecordV1 | null {
126
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
127
+ return null;
128
+ }
129
+ const record = value as Record<string, unknown>;
130
+ const runId = record["runId"];
131
+ const startedAt = record["startedAt"];
132
+ const exitStatus = record["exitStatus"];
133
+ const findingsTotal = record["findingsTotal"];
134
+ if (
135
+ typeof runId !== "string" ||
136
+ typeof startedAt !== "string" ||
137
+ typeof exitStatus !== "string"
138
+ ) {
139
+ return null;
140
+ }
141
+ const finishedAt = record["finishedAt"];
142
+ const errorCode = record["errorCode"];
143
+ return {
144
+ runId,
145
+ startedAt,
146
+ exitStatus: exitStatus as ExtensionRunV1["exitStatus"],
147
+ findingsTotal: typeof findingsTotal === "number" ? findingsTotal : 0,
148
+ ...(typeof finishedAt === "string" ? { finishedAt } : {}),
149
+ ...(typeof errorCode === "string" ? { errorCode } : {}),
150
+ };
151
+ }
152
+
153
+ export async function saveCliState(
154
+ fs: FileSystemPort,
155
+ userDataDirectory: string,
156
+ state: CliStateV1,
157
+ ): Promise<string> {
158
+ const path = cliStatePath(userDataDirectory);
159
+ const ordered: CliStateV1 = {
160
+ schemaVersion: 1,
161
+ enabled: [...state.enabled].sort(compareCodepoints),
162
+ lastRuns: Object.fromEntries(
163
+ Object.entries(state.lastRuns).sort(([left], [right]) => compareCodepoints(left, right)),
164
+ ),
165
+ };
166
+ await writeJsonAtomic(fs, path, ordered);
167
+ return path;
168
+ }
169
+
170
+ /** Where acknowledgments are written; re-exported so callers need one import. */
171
+ export function acknowledgmentPath(userDataDirectory: string): string {
172
+ return acknowledgmentFilePath(userDataDirectory);
173
+ }
174
+
175
+ export { ACKNOWLEDGMENT_FILE_NAME };
176
+
177
+ /**
178
+ * Writes the acknowledgment file. Entries are ordered by
179
+ * `(extensionId, ruleset)` via codepoint comparison so the file has one
180
+ * canonical form — a diff between two machines shows real changes only.
181
+ */
182
+ export async function saveAcknowledgments(
183
+ fs: FileSystemPort,
184
+ userDataDirectory: string,
185
+ acknowledgments: readonly LicenseAcknowledgmentV1[],
186
+ ): Promise<string> {
187
+ const path = acknowledgmentFilePath(userDataDirectory);
188
+ const document: LicenseAcknowledgmentFileV1 = {
189
+ schemaVersion: 1,
190
+ acknowledgments: [...acknowledgments].sort(
191
+ (left, right) =>
192
+ compareCodepoints(left.extensionId, right.extensionId) ||
193
+ compareCodepoints(left.ruleset ?? "", right.ruleset ?? ""),
194
+ ),
195
+ };
196
+ await writeJsonAtomic(fs, path, document);
197
+ return path;
198
+ }
199
+
200
+ /**
201
+ * Replaces the entry for one `(extensionId, ruleset)` pair, keeping the rest.
202
+ * A repeated acknowledgment updates in place instead of stacking duplicates.
203
+ */
204
+ export function upsertAcknowledgment(
205
+ existing: readonly LicenseAcknowledgmentV1[],
206
+ entry: LicenseAcknowledgmentV1,
207
+ ): LicenseAcknowledgmentV1[] {
208
+ const kept = existing.filter(
209
+ (candidate) =>
210
+ candidate.extensionId !== entry.extensionId ||
211
+ (candidate.ruleset ?? "") !== (entry.ruleset ?? ""),
212
+ );
213
+ return [...kept, entry];
214
+ }
215
+
216
+ /**
217
+ * Marks every acknowledgment for one extension as withdrawn (§9.3).
218
+ *
219
+ * The entry is kept and stamped with `revokedAt` rather than deleted. Both
220
+ * shapes refuse the run, so this is not about safety — it is about what the
221
+ * user can be told afterwards. A deleted row makes "you never acknowledged
222
+ * this" and "you acknowledged this and took it back" indistinguishable, and
223
+ * §9.3 asks `status` to be able to show the gate status `revoked`, which a
224
+ * deleted row can never produce.
225
+ */
226
+ export function revokeAcknowledgments(
227
+ existing: readonly LicenseAcknowledgmentV1[],
228
+ extensionId: string,
229
+ revokedAt: string,
230
+ ): LicenseAcknowledgmentV1[] {
231
+ return existing.map((candidate) =>
232
+ candidate.extensionId === extensionId && candidate.revokedAt === undefined
233
+ ? { ...candidate, revokedAt }
234
+ : candidate,
235
+ );
236
+ }
237
+
238
+ /** Drops every acknowledgment for one extension — used when it is uninstalled. */
239
+ export function removeAcknowledgments(
240
+ existing: readonly LicenseAcknowledgmentV1[],
241
+ extensionId: string,
242
+ ): LicenseAcknowledgmentV1[] {
243
+ return existing.filter((candidate) => candidate.extensionId !== extensionId);
244
+ }
245
+
246
+ async function writeJsonAtomic(fs: FileSystemPort, path: string, value: unknown): Promise<void> {
247
+ await fs.mkdir(dirname(path), { recursive: true });
248
+ const temporary = `${path}.tmp`;
249
+ const bytes = new TextEncoder().encode(`${JSON.stringify(value, null, 2)}\n`);
250
+ await fs.writeFile(temporary, bytes);
251
+ await fs.rename(temporary, path);
252
+ }