@untangle-code/cli 0.0.0-stage → 0.1.1

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 +451 -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,312 @@
1
+ /**
2
+ * `untangle extensions add --from <url|path>`
3
+ *
4
+ * Installs ONE manifest into the user's extension root
5
+ * (`~/.untangle/extensions/<id>/manifest.toml`). Four gates stand between the
6
+ * argument and the file on disk, and none of them is optional:
7
+ *
8
+ * 1. **Transport.** A URL must be https and must carry `--digest`
9
+ * (`source.ts` explains why).
10
+ * 2. **Project boundary.** A path inside a project directory is refused
11
+ * unless the user types `--allow-project-local` in the same invocation.
12
+ * Automatic loading from a project directory does not exist at all: a
13
+ * cloned repository must not be able to hand a tool definition to the
14
+ * runtime (extensions.md §17).
15
+ * 3. **Manifest validity.** Structure and semantics both, X6 included: a
16
+ * container manifest without a fully pinned sha256 digest is rejected.
17
+ * 4. **License gate (X5).** Installing never acknowledges anything. A
18
+ * restricted tool is installed in state `unacknowledged`, and the exact
19
+ * command that would grant the acknowledgment is printed.
20
+ *
21
+ * `add` starts nothing — no process, no pull, no container (X1).
22
+ */
23
+ import { join } from "node:path";
24
+
25
+ import {
26
+ MANIFEST_FILE_NAME,
27
+ buildAcknowledgment,
28
+ extensionDirectory,
29
+ extensionManifestPath,
30
+ isProjectLocalManifest,
31
+ loadExtensionManifestFile,
32
+ parseExtensionManifest,
33
+ } from "@untangle-code/extension-runtime";
34
+
35
+ import { boolFlag, listFlag, stringFlag, type ParsedArgs } from "../../cli/args.js";
36
+ import { EXIT, OperationalError, UsageError } from "../../cli/exit.js";
37
+ import { line, note, type Io } from "../../cli/io.js";
38
+
39
+ import { gateFor, loadExtensionContext } from "./context.js";
40
+ import { canonicalize, resolveUserPath, type ExtensionEnvironmentV1 } from "./environment.js";
41
+ import { emitJson } from "./render.js";
42
+ import {
43
+ DIGEST_PATTERN,
44
+ ManifestSourceError,
45
+ fetchManifestFromUrl,
46
+ isUrlSource,
47
+ readManifestFromPath,
48
+ type FetchManifestOptions,
49
+ type ManifestSourceV1,
50
+ } from "./source.js";
51
+ import { saveAcknowledgments, upsertAcknowledgment } from "./state.js";
52
+
53
+ export interface AddDeps {
54
+ /** Injected in tests so no unit test opens a socket. */
55
+ fetchOptions?: FetchManifestOptions;
56
+ }
57
+
58
+ export async function runAdd(
59
+ environment: ExtensionEnvironmentV1,
60
+ args: ParsedArgs,
61
+ io: Io,
62
+ format: "text" | "json",
63
+ deps: AddDeps = {},
64
+ ): Promise<number> {
65
+ const from = stringFlag(args, "from");
66
+ if (from === undefined) {
67
+ throw new UsageError(
68
+ "`untangle extensions add` needs a source.",
69
+ "Write --from=<path to a manifest.toml> or --from=<https URL> --digest=sha256:<64 hex>.",
70
+ );
71
+ }
72
+ const expectedDigest = stringFlag(args, "digest");
73
+ if (expectedDigest !== undefined && !DIGEST_PATTERN.test(expectedDigest)) {
74
+ throw new UsageError(
75
+ `--digest must look like "sha256:<64 lowercase hex>", got "${expectedDigest}".`,
76
+ "Compute it with: shasum -a 256 manifest.toml",
77
+ );
78
+ }
79
+
80
+ const source = await readSource(environment, from, expectedDigest, args, deps);
81
+
82
+ if (expectedDigest !== undefined && source.digest !== expectedDigest) {
83
+ throw new OperationalError(
84
+ `Digest mismatch for ${source.resolved}: expected ${expectedDigest}, got ${source.digest}. ` +
85
+ "Nothing was installed.",
86
+ "Verify the digest with the publisher before installing this manifest.",
87
+ );
88
+ }
89
+
90
+ // --- manifest validity (structure + semantics, X6 included) -------------
91
+ const parsed = parseExtensionManifest(source.text);
92
+ if (parsed.manifest === null) {
93
+ note(io, `The manifest at ${source.resolved} is not valid; nothing was installed:`);
94
+ for (const issue of parsed.issues) {
95
+ note(io, ` ${issue.field}: ${issue.message}`);
96
+ }
97
+ throw new OperationalError(
98
+ `${String(parsed.issues.length)} problem(s) in the manifest at ${source.resolved}.`,
99
+ "Fix the fields listed above; the manifest schema is documented in extensions.md §5.2.",
100
+ );
101
+ }
102
+ const manifest = parsed.manifest;
103
+
104
+ // --- write --------------------------------------------------------------
105
+ const root = environment.roots[0];
106
+ if (root === undefined) {
107
+ throw new OperationalError(
108
+ "No extension root could be resolved for this user profile.",
109
+ "Set UNTANGLE_EXTENSIONS_HOME to a writable directory outside any project.",
110
+ );
111
+ }
112
+ const targetDirectory = extensionDirectory(root, manifest.id);
113
+ const targetPath = extensionManifestPath(root, manifest.id);
114
+ const existing = await environment.fs.stat(targetPath);
115
+ if (existing !== null && !boolFlag(args, "force")) {
116
+ throw new OperationalError(
117
+ `"${manifest.id}" is already installed at ${targetPath}.`,
118
+ `Repeat with --force to replace it, or remove it first: untangle extensions remove ${manifest.id}`,
119
+ );
120
+ }
121
+
122
+ await environment.fs.mkdir(targetDirectory, { recursive: true });
123
+ const temporary = join(targetDirectory, `${MANIFEST_FILE_NAME}.tmp`);
124
+ await environment.fs.writeFile(temporary, source.bytes);
125
+ await environment.fs.rename(temporary, targetPath);
126
+
127
+ // Re-read through the loader, so what is reported is what the runtime will
128
+ // see — not what this command believed it wrote.
129
+ const loaded = await loadExtensionManifestFile(environment.fs, targetPath, "user-data-dir", {
130
+ expectedId: manifest.id,
131
+ });
132
+ if (loaded.extension === null) {
133
+ for (const issue of loaded.issues) {
134
+ note(io, ` ${issue.field}: ${issue.message}`);
135
+ }
136
+ throw new OperationalError(
137
+ `The installed manifest at ${targetPath} does not load back.`,
138
+ "Remove the directory and install the manifest again.",
139
+ );
140
+ }
141
+ const installed = loaded.extension;
142
+
143
+ // --- license gate (X5) --------------------------------------------------
144
+ const context = await loadExtensionContext(environment);
145
+ let acknowledgments = context.acknowledgments;
146
+ const acknowledgedNow: string[] = [];
147
+ if (boolFlag(args, "acknowledge-license")) {
148
+ acknowledgments = upsertAcknowledgment(
149
+ acknowledgments,
150
+ buildAcknowledgment({
151
+ manifest,
152
+ acknowledgedAt: environment.clock.nowIso(),
153
+ acknowledgedBy: environment.userName,
154
+ }),
155
+ );
156
+ acknowledgedNow.push(`tool:${manifest.id}`);
157
+ }
158
+ for (const ruleset of listFlag(args, "acknowledge-ruleset")) {
159
+ acknowledgments = upsertAcknowledgment(
160
+ acknowledgments,
161
+ buildAcknowledgment({
162
+ manifest,
163
+ ruleset,
164
+ acknowledgedAt: environment.clock.nowIso(),
165
+ acknowledgedBy: environment.userName,
166
+ }),
167
+ );
168
+ acknowledgedNow.push(`ruleset:${ruleset}`);
169
+ }
170
+ let acknowledgmentFile: string | undefined;
171
+ if (acknowledgedNow.length > 0) {
172
+ acknowledgmentFile = await saveAcknowledgments(
173
+ environment.fs,
174
+ environment.userDataDir,
175
+ acknowledgments,
176
+ );
177
+ }
178
+
179
+ const gate = gateFor({ ...context, acknowledgments }, installed);
180
+
181
+ if (format === "json") {
182
+ emitJson(io, {
183
+ command: "extensions add",
184
+ extensionId: manifest.id,
185
+ displayName: manifest.displayName,
186
+ category: manifest.category,
187
+ invocation: manifest.invocation,
188
+ outputFormat: manifest.outputFormat,
189
+ source: { kind: source.kind, requested: source.requested, resolved: source.resolved },
190
+ manifestDigest: source.digest,
191
+ manifestSha256: installed.manifestSha256,
192
+ installedTo: targetPath,
193
+ replacedExisting: existing !== null,
194
+ containerDigest: manifest.container?.digest,
195
+ license: {
196
+ spdxId: manifest.license.spdxId,
197
+ usageRestriction: manifest.license.usageRestriction,
198
+ requiresAcknowledgment: manifest.requiresLicenseAcknowledgment,
199
+ gateStatus: gate.tool.status,
200
+ gateReason: gate.tool.reason,
201
+ rulesets: gate.rulesets.map((entry) => ({
202
+ ruleset: entry.ruleset,
203
+ status: entry.status,
204
+ reason: entry.reason,
205
+ })),
206
+ acknowledgedNow,
207
+ acknowledgmentFile,
208
+ },
209
+ networkAccess: manifest.networkAccess,
210
+ telemetry: manifest.telemetry,
211
+ enabled: false,
212
+ started: false,
213
+ nextSteps: gate.allowed
214
+ ? [`untangle extensions enable ${manifest.id}`]
215
+ : gate.acknowledgeCommands,
216
+ warnings: context.warnings,
217
+ });
218
+ } else {
219
+ line(io, `installed "${manifest.id}" (${manifest.displayName})`);
220
+ line(io, ` from ${source.resolved}`);
221
+ line(io, ` manifest ${targetPath}`);
222
+ line(io, ` digest ${source.digest}`);
223
+ if (manifest.container !== undefined) {
224
+ line(io, ` image ${manifest.container.image}@${manifest.container.digest}`);
225
+ }
226
+ line(io, ` invocation ${manifest.invocation.join(", ")}`);
227
+ line(io, ` format ${manifest.outputFormat}`);
228
+ line(
229
+ io,
230
+ ` license ${manifest.license.spdxId} (${manifest.license.usageRestriction}) — gate: ${gate.tool.status}`,
231
+ );
232
+ for (const entry of gate.rulesets) {
233
+ line(io, ` ruleset ${entry.ruleset} — gate: ${entry.status}`);
234
+ }
235
+ line(io, ` network ${manifest.networkAccess}`);
236
+ line(
237
+ io,
238
+ " enabled no — installing starts nothing (X1); enable it with " +
239
+ `untangle extensions enable ${manifest.id}`,
240
+ );
241
+ }
242
+
243
+ for (const warning of context.warnings) {
244
+ note(io, `warning: ${warning}`);
245
+ }
246
+ if (!gate.allowed) {
247
+ note(io, `The license gate is not satisfied: ${gate.tool.reason}`);
248
+ note(io, "Nothing will run until you acknowledge it:");
249
+ for (const command of gate.acknowledgeCommands) {
250
+ note(io, ` ${command}`);
251
+ }
252
+ }
253
+
254
+ // Installing succeeded even when the gate is still open: the manifest is on
255
+ // disk and `list` will show it. The gate is enforced where it matters — at
256
+ // `run` — so a successful install is not reported as a failure.
257
+ return EXIT.ok;
258
+ }
259
+
260
+ async function readSource(
261
+ environment: ExtensionEnvironmentV1,
262
+ from: string,
263
+ expectedDigest: string | undefined,
264
+ args: ParsedArgs,
265
+ deps: AddDeps,
266
+ ): Promise<ManifestSourceV1> {
267
+ if (isUrlSource(from)) {
268
+ if (expectedDigest === undefined) {
269
+ throw new UsageError(
270
+ `Refusing to install from a URL without --digest. "${from}" is not a fixed artifact: ` +
271
+ "whatever the server returns today would become a program invocation on this machine.",
272
+ "Ask the publisher for the sha256 of the manifest and pass --digest=sha256:<64 hex>, " +
273
+ "or download the file and use --from=<path>.",
274
+ );
275
+ }
276
+ try {
277
+ return await fetchManifestFromUrl(from, deps.fetchOptions ?? {});
278
+ } catch (cause) {
279
+ throw new OperationalError(
280
+ cause instanceof ManifestSourceError ? cause.message : String(cause),
281
+ "Check the URL, or download the manifest and install the local copy with --from=<path>.",
282
+ { cause },
283
+ );
284
+ }
285
+ }
286
+
287
+ // The boundary check compares lexically and does not resolve symlinks — the
288
+ // runtime says so explicitly. Canonicalizing here is what makes the check
289
+ // sound: without it a symlink (or, on macOS, the /var alias alone) would
290
+ // carry a path out of the project it really lives in.
291
+ const path = await canonicalize(environment.fs, resolveUserPath(environment.cwd, from));
292
+ if (
293
+ isProjectLocalManifest(path, environment.projectRoots) &&
294
+ !boolFlag(args, "allow-project-local")
295
+ ) {
296
+ throw new UsageError(
297
+ `Refusing to read a manifest from a project directory: "${path}" lies inside ` +
298
+ `${environment.projectRoots.join(", ")}. A manifest describes how to start a program, so a ` +
299
+ "cloned repository must never be able to supply one unnoticed (extensions.md §17).",
300
+ "If you wrote this manifest yourself, repeat the command with --allow-project-local.",
301
+ );
302
+ }
303
+ try {
304
+ return await readManifestFromPath(environment.fs, path);
305
+ } catch (cause) {
306
+ throw new OperationalError(
307
+ cause instanceof ManifestSourceError ? cause.message : String(cause),
308
+ "Check the path; --from accepts a manifest.toml or the directory containing it.",
309
+ { cause },
310
+ );
311
+ }
312
+ }
@@ -0,0 +1,82 @@
1
+ /** User-private credential configuration; values never appear in output or argv. */
2
+ import { readFile } from "node:fs/promises";
3
+
4
+ import { stringFlag, type ParsedArgs } from "../../cli/args.js";
5
+ import { EXIT, OperationalError, UsageError } from "../../cli/exit.js";
6
+ import { line, type Io } from "../../cli/io.js";
7
+
8
+ import { explainMissing, findExtension, loadExtensionContext } from "./context.js";
9
+ import { resolveUserPath, type ExtensionEnvironmentV1 } from "./environment.js";
10
+ import { emitJson } from "./render.js";
11
+ import {
12
+ parseSecretValues,
13
+ readStoredSecrets,
14
+ secretStorePath,
15
+ withSecretLock,
16
+ writeStoredSecrets,
17
+ } from "./secret-store.js";
18
+
19
+ export async function runConfigure(
20
+ environment: ExtensionEnvironmentV1,
21
+ args: ParsedArgs,
22
+ io: Io,
23
+ format: "text" | "json",
24
+ ): Promise<number> {
25
+ const id = args.positionals[1];
26
+ if (!id || args.positionals.length !== 2)
27
+ throw new UsageError(
28
+ "configure needs exactly one extension id.",
29
+ "untangle extensions configure <id> [--from=<private-json-file>]",
30
+ );
31
+ const context = await loadExtensionContext(environment);
32
+ const extension = findExtension(context, id);
33
+ if (!extension)
34
+ throw new OperationalError(explainMissing(context, id), "Install the extension first.");
35
+ const manifest = extension.manifest;
36
+ const source = stringFlag(args, "from");
37
+ let imported: Record<string, string> = {};
38
+ if (source !== undefined) {
39
+ let content: unknown;
40
+ try {
41
+ content = JSON.parse(await readFile(resolveUserPath(environment.cwd, source), "utf8"));
42
+ } catch {
43
+ throw new UsageError(
44
+ "Cannot read credential JSON; its contents were withheld.",
45
+ "Use a JSON object keyed by the secret names declared in the manifest.",
46
+ );
47
+ }
48
+ imported = parseSecretValues(content, manifest);
49
+ }
50
+ const values = await withSecretLock(environment, id, async () => {
51
+ const stored = await readStoredSecrets(environment, manifest);
52
+ const values = {
53
+ ...Object.fromEntries(manifest.secrets.map((secret) => [secret.name, ""])),
54
+ ...stored,
55
+ ...imported,
56
+ };
57
+ await writeStoredSecrets(environment, manifest, values);
58
+ return values;
59
+ });
60
+ const path = secretStorePath(environment, id);
61
+ const secrets = manifest.secrets.map((secret) => ({
62
+ name: secret.name,
63
+ envVar: secret.envVar,
64
+ configured: Boolean(values[secret.name]),
65
+ setupOnly: secret.setupOnly ?? false,
66
+ }));
67
+ if (format === "json")
68
+ emitJson(io, { command: "extensions configure", extensionId: id, path, secrets });
69
+ else {
70
+ line(io, `Private credential configuration (0600): ${path}`);
71
+ for (const secret of secrets)
72
+ line(
73
+ io,
74
+ ` ${secret.name}: ${secret.configured ? "configured" : "not set"}; environment override: ${secret.envVar}${secret.setupOnly ? " (setup only)" : ""}`,
75
+ );
76
+ line(
77
+ io,
78
+ `Edit the secrets object in that file, then run: untangle extensions setup ${id} --yes`,
79
+ );
80
+ }
81
+ return EXIT.ok;
82
+ }
@@ -0,0 +1,209 @@
1
+ /**
2
+ * Die Container-Grenze, bedient ueber ein Compose-fähiges Kommandozeilen-
3
+ * werkzeug des Nutzers.
4
+ *
5
+ * Untangle liefert keine Container-Runtime mit. Es ruft die auf, die auf dem
6
+ * Rechner steht — ueber dieselbe Prozessgrenze wie jedes andere fremde Programm
7
+ * (X4). Welches Kommando das ist, sagt `UNTANGLE_CONTAINER_CLI`; die Vorgabe
8
+ * ist das gebraeuchlichste.
9
+ *
10
+ * Zwei Dinge tragen hier die Sicherheit:
11
+ *
12
+ * 1. **Die Besitzprobe.** Auf einer Entwicklermaschine laufen fremde Container.
13
+ * `down` und `logs` greifen deshalb nie nach dem Namen allein, sondern
14
+ * verlangen BEIDE Labels aus §8.2. Findet sich ein Container des erwarteten
15
+ * Namens ohne sie, wird nichts angefasst und der Grund gemeldet — nicht
16
+ * „schon gut, ist ja unserer".
17
+ *
18
+ * 2. **Die Compose-Datei kommt von uns.** Sie wird bei jedem Lauf aus dem
19
+ * validierten Manifest gerendert (siehe `renderComposeFile`), damit der
20
+ * gepinnte Digest, die Loopback-Bindung und die Labels tatsaechlich gelten
21
+ * und nicht nur in einer mitgebrachten YAML behauptet werden.
22
+ */
23
+ import type { ExtensionManifestV1 } from "@untangle-code/domain";
24
+ import {
25
+ composeProjectName,
26
+ EXTENSION_LABEL,
27
+ MANAGED_LABEL,
28
+ type ContainerActionResultV1,
29
+ type ContainerDownInputV1,
30
+ type ContainerLogsResultV1,
31
+ type ContainerRuntimeAvailabilityV1,
32
+ type ContainerRuntimePort,
33
+ type ContainerStateV1,
34
+ type ContainerUpInputV1,
35
+ } from "@untangle-code/extension-runtime";
36
+ import type { ProcessLimitsV1, ProcessRunnerPort } from "@untangle-code/extension-runtime";
37
+
38
+ /** Vorgabe des Kommandos; ueberschreibbar mit `UNTANGLE_CONTAINER_CLI`. */
39
+ export const DEFAULT_CONTAINER_CLI = "docker";
40
+
41
+ /** Name des Containers einer Extension — bewusst vorhersagbar, nie geraten. */
42
+ export function containerNameFor(extensionId: string): string {
43
+ return `untangle-ext-${extensionId}`;
44
+ }
45
+
46
+ const INSPECT_FORMAT =
47
+ `{{index .Config.Labels "${MANAGED_LABEL}"}}\t` +
48
+ `{{index .Config.Labels "${EXTENSION_LABEL}"}}\t` +
49
+ `{{.State.Running}}\t{{.Config.Image}}`;
50
+
51
+ export interface ContainerCliOptions {
52
+ processRunner: ProcessRunnerPort;
53
+ limits: ProcessLimitsV1;
54
+ /** Kommando der Container-Runtime; kommt aus der Umgebung, nicht aus dem Quelltext. */
55
+ command?: string;
56
+ env?: Readonly<Record<string, string>>;
57
+ }
58
+
59
+ export function createContainerCli(options: ContainerCliOptions): ContainerRuntimePort {
60
+ const command = options.command ?? DEFAULT_CONTAINER_CLI;
61
+
62
+ const run = async (
63
+ args: readonly string[],
64
+ signal?: AbortSignal,
65
+ ): Promise<{ ok: boolean; stdout: string; stderr: string; detail: string }> => {
66
+ const result = await options.processRunner.run(
67
+ {
68
+ command,
69
+ args: [...args],
70
+ ...(options.env === undefined ? {} : { env: options.env }),
71
+ },
72
+ options.limits,
73
+ signal === undefined ? {} : { signal },
74
+ );
75
+ const ok = result.outcome === "completed" && (result.exitCode ?? 1) === 0;
76
+ return {
77
+ ok,
78
+ stdout: result.stdout,
79
+ stderr: result.stderr,
80
+ detail: ok
81
+ ? `${command} ${args[0] ?? ""} succeeded`
82
+ : `${command} ${args.join(" ")} failed (${result.outcome}, exit ${String(result.exitCode)})` +
83
+ `${result.stderr.trim() === "" ? "" : `: ${result.stderr.trim().slice(0, 300)}`}`,
84
+ };
85
+ };
86
+
87
+ return {
88
+ async available(opts = {}): Promise<ContainerRuntimeAvailabilityV1> {
89
+ const result = await run(["version", "--format", "{{.Server.Version}}"], opts.signal);
90
+ if (!result.ok) {
91
+ return {
92
+ available: false,
93
+ detail:
94
+ `no container runtime answered: ${result.detail}. Untangle neither ships nor starts ` +
95
+ `one; set UNTANGLE_CONTAINER_CLI if the command is named differently.`,
96
+ };
97
+ }
98
+ const version = result.stdout.trim();
99
+ return {
100
+ available: true,
101
+ detail: `container runtime ${version} answered on "${command}"`,
102
+ ...(version === "" ? {} : { version }),
103
+ };
104
+ },
105
+
106
+ async inspect(manifest: ExtensionManifestV1, opts = {}): Promise<ContainerStateV1> {
107
+ const name = containerNameFor(manifest.id);
108
+ const result = await run(["inspect", name, "--format", INSPECT_FORMAT], opts.signal);
109
+ if (!result.ok) {
110
+ return {
111
+ exists: false,
112
+ running: false,
113
+ ownedByUntangle: false,
114
+ detail: `no container named "${name}" exists`,
115
+ };
116
+ }
117
+ const [managed, extensionId, running, image] = result.stdout.trim().split("\t");
118
+ const owned = managed === "true" && extensionId === manifest.id;
119
+ if (!owned) {
120
+ // Der Name allein beweist nichts. Ohne beide Labels ist der Container
121
+ // fremd, und fremde Container fasst Untangle nicht an (spec.md §3.2).
122
+ return {
123
+ exists: true,
124
+ running: running === "true",
125
+ ownedByUntangle: false,
126
+ detail:
127
+ `a container named "${name}" exists but does not carry ${MANAGED_LABEL}=true and ` +
128
+ `${EXTENSION_LABEL}=${manifest.id}; Untangle does not touch containers it did not create`,
129
+ };
130
+ }
131
+ const digest = /@(sha256:[0-9a-f]{64})$/.exec(image ?? "")?.[1];
132
+ return {
133
+ exists: true,
134
+ running: running === "true",
135
+ ownedByUntangle: true,
136
+ ...(digest === undefined ? {} : { imageDigest: digest }),
137
+ detail: `container "${name}" is ${running === "true" ? "running" : "stopped"}`,
138
+ };
139
+ },
140
+
141
+ async up(input: ContainerUpInputV1, opts = {}): Promise<ContainerActionResultV1> {
142
+ const state = await this.inspect(input.manifest, opts);
143
+ if (state.exists && !state.ownedByUntangle) {
144
+ return { ok: false, detail: state.detail };
145
+ }
146
+ const result = await run(
147
+ [
148
+ "compose",
149
+ "--project-name",
150
+ composeProjectName(input.manifest.id),
151
+ "--file",
152
+ input.composeFilePath,
153
+ "up",
154
+ "--detach",
155
+ ],
156
+ opts.signal,
157
+ );
158
+ return { ok: result.ok, detail: result.detail };
159
+ },
160
+
161
+ async down(input: ContainerDownInputV1, opts = {}): Promise<ContainerActionResultV1> {
162
+ const state = await this.inspect(input.manifest, opts);
163
+ if (state.exists && !state.ownedByUntangle) {
164
+ return { ok: false, detail: state.detail };
165
+ }
166
+ const result = await run(
167
+ [
168
+ "compose",
169
+ "--project-name",
170
+ composeProjectName(input.manifest.id),
171
+ "--file",
172
+ input.composeFilePath,
173
+ "down",
174
+ ...(input.removeVolumes ? ["--volumes"] : []),
175
+ ],
176
+ opts.signal,
177
+ );
178
+ return { ok: result.ok, detail: result.detail };
179
+ },
180
+
181
+ async logs(
182
+ input: { manifest: ExtensionManifestV1; composeFilePath: string; tail: number },
183
+ opts = {},
184
+ ): Promise<ContainerLogsResultV1> {
185
+ const state = await this.inspect(input.manifest, opts);
186
+ if (state.exists && !state.ownedByUntangle) {
187
+ return { ok: false, text: "", detail: state.detail };
188
+ }
189
+ if (!state.exists) {
190
+ return { ok: false, text: "", detail: state.detail };
191
+ }
192
+ const result = await run(
193
+ [
194
+ "compose",
195
+ "--project-name",
196
+ composeProjectName(input.manifest.id),
197
+ "--file",
198
+ input.composeFilePath,
199
+ "logs",
200
+ "--no-color",
201
+ "--tail",
202
+ String(input.tail),
203
+ ],
204
+ opts.signal,
205
+ );
206
+ return { ok: result.ok, text: result.stdout, detail: result.detail };
207
+ },
208
+ };
209
+ }