@mesh-tech/mesh-cli 0.1.1 → 0.12.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 (504) hide show
  1. package/assets/intent/agents-fence.md +10 -0
  2. package/assets/intent/intent-claude-gate.mjs +255 -0
  3. package/assets/log-shipper.mjs +94 -0
  4. package/bin/mesh.mjs +80 -0
  5. package/dist/bin/mesh.d.ts +7 -9
  6. package/dist/bin/mesh.d.ts.map +1 -1
  7. package/dist/bin/mesh.js +20826 -37
  8. package/dist/bin/mesh.js.map +7 -1
  9. package/dist/build-info.json +4 -0
  10. package/dist/src/commands/agent-api-client.d.ts +79 -0
  11. package/dist/src/commands/agent-api-client.d.ts.map +1 -0
  12. package/dist/src/commands/agent-api-client.js +170 -0
  13. package/dist/src/commands/agent-api-client.js.map +1 -0
  14. package/dist/src/commands/artifacts.d.ts +13 -0
  15. package/dist/src/commands/artifacts.d.ts.map +1 -0
  16. package/dist/src/commands/artifacts.js +140 -0
  17. package/dist/src/commands/artifacts.js.map +1 -0
  18. package/dist/src/commands/cluster.d.ts +45 -0
  19. package/dist/src/commands/cluster.d.ts.map +1 -0
  20. package/dist/src/commands/cluster.js +259 -0
  21. package/dist/src/commands/cluster.js.map +1 -0
  22. package/dist/src/commands/conversations.d.ts +61 -0
  23. package/dist/src/commands/conversations.d.ts.map +1 -0
  24. package/dist/src/commands/conversations.js +239 -0
  25. package/dist/src/commands/conversations.js.map +1 -0
  26. package/dist/src/commands/create-app.d.ts +26 -3
  27. package/dist/src/commands/create-app.d.ts.map +1 -1
  28. package/dist/src/commands/create-app.js +465 -107
  29. package/dist/src/commands/create-app.js.map +1 -1
  30. package/dist/src/commands/deploy.d.ts +19 -0
  31. package/dist/src/commands/deploy.d.ts.map +1 -1
  32. package/dist/src/commands/deploy.js +83 -142
  33. package/dist/src/commands/deploy.js.map +1 -1
  34. package/dist/src/commands/dev-doctor.d.ts +137 -0
  35. package/dist/src/commands/dev-doctor.d.ts.map +1 -0
  36. package/dist/src/commands/dev-doctor.js +671 -0
  37. package/dist/src/commands/dev-doctor.js.map +1 -0
  38. package/dist/src/commands/dev-launch.d.ts +59 -0
  39. package/dist/src/commands/dev-launch.d.ts.map +1 -0
  40. package/dist/src/commands/dev-launch.js +118 -0
  41. package/dist/src/commands/dev-launch.js.map +1 -0
  42. package/dist/src/commands/dev-token-server.d.ts +32 -0
  43. package/dist/src/commands/dev-token-server.d.ts.map +1 -0
  44. package/dist/src/commands/dev-token-server.js +68 -0
  45. package/dist/src/commands/dev-token-server.js.map +1 -0
  46. package/dist/src/commands/dev.d.ts +289 -2
  47. package/dist/src/commands/dev.d.ts.map +1 -1
  48. package/dist/src/commands/dev.js +2501 -574
  49. package/dist/src/commands/dev.js.map +1 -1
  50. package/dist/src/commands/docs.d.ts +3 -0
  51. package/dist/src/commands/docs.d.ts.map +1 -0
  52. package/dist/src/commands/docs.js +262 -0
  53. package/dist/src/commands/docs.js.map +1 -0
  54. package/dist/src/commands/hub/index.d.ts +99 -0
  55. package/dist/src/commands/hub/index.d.ts.map +1 -0
  56. package/dist/src/commands/hub/index.js +452 -0
  57. package/dist/src/commands/hub/index.js.map +1 -0
  58. package/dist/src/commands/init.d.ts +65 -0
  59. package/dist/src/commands/init.d.ts.map +1 -0
  60. package/dist/src/commands/init.js +370 -0
  61. package/dist/src/commands/init.js.map +1 -0
  62. package/dist/src/commands/install-shim.d.ts +21 -0
  63. package/dist/src/commands/install-shim.d.ts.map +1 -0
  64. package/dist/src/commands/install-shim.js +132 -0
  65. package/dist/src/commands/install-shim.js.map +1 -0
  66. package/dist/src/commands/local/auth-provision.d.ts +71 -0
  67. package/dist/src/commands/local/auth-provision.d.ts.map +1 -0
  68. package/dist/src/commands/local/auth-provision.js +286 -0
  69. package/dist/src/commands/local/auth-provision.js.map +1 -0
  70. package/dist/src/commands/local/dev-local.d.ts +97 -0
  71. package/dist/src/commands/local/dev-local.d.ts.map +1 -0
  72. package/dist/src/commands/local/dev-local.js +306 -0
  73. package/dist/src/commands/local/dev-local.js.map +1 -0
  74. package/dist/src/commands/local/docker-runner.d.ts +37 -0
  75. package/dist/src/commands/local/docker-runner.d.ts.map +1 -0
  76. package/dist/src/commands/local/docker-runner.js +104 -0
  77. package/dist/src/commands/local/docker-runner.js.map +1 -0
  78. package/dist/src/commands/local/helpers.d.ts +22 -0
  79. package/dist/src/commands/local/helpers.d.ts.map +1 -0
  80. package/dist/src/commands/local/helpers.js +46 -0
  81. package/dist/src/commands/local/helpers.js.map +1 -0
  82. package/dist/src/commands/local/hub-local.d.ts +51 -0
  83. package/dist/src/commands/local/hub-local.d.ts.map +1 -0
  84. package/dist/src/commands/local/hub-local.js +197 -0
  85. package/dist/src/commands/local/hub-local.js.map +1 -0
  86. package/dist/src/commands/local/index.d.ts +23 -0
  87. package/dist/src/commands/local/index.d.ts.map +1 -0
  88. package/dist/src/commands/local/index.js +386 -0
  89. package/dist/src/commands/local/index.js.map +1 -0
  90. package/dist/src/commands/local/mocks.d.ts +361 -0
  91. package/dist/src/commands/local/mocks.d.ts.map +1 -0
  92. package/dist/src/commands/local/mocks.js +756 -0
  93. package/dist/src/commands/local/mocks.js.map +1 -0
  94. package/dist/src/commands/local/seed-zitadel.d.ts +151 -0
  95. package/dist/src/commands/local/seed-zitadel.d.ts.map +1 -0
  96. package/dist/src/commands/local/seed-zitadel.js +408 -0
  97. package/dist/src/commands/local/seed-zitadel.js.map +1 -0
  98. package/dist/src/commands/local/seed.d.ts +106 -0
  99. package/dist/src/commands/local/seed.d.ts.map +1 -0
  100. package/dist/src/commands/local/seed.js +252 -0
  101. package/dist/src/commands/local/seed.js.map +1 -0
  102. package/dist/src/commands/local/stack.d.ts +173 -0
  103. package/dist/src/commands/local/stack.d.ts.map +1 -0
  104. package/dist/src/commands/local/stack.js +499 -0
  105. package/dist/src/commands/local/stack.js.map +1 -0
  106. package/dist/src/commands/login.d.ts +256 -12
  107. package/dist/src/commands/login.d.ts.map +1 -1
  108. package/dist/src/commands/login.js +978 -50
  109. package/dist/src/commands/login.js.map +1 -1
  110. package/dist/src/commands/peer-addressing.d.ts +51 -0
  111. package/dist/src/commands/peer-addressing.d.ts.map +1 -0
  112. package/dist/src/commands/peer-addressing.js +64 -0
  113. package/dist/src/commands/peer-addressing.js.map +1 -0
  114. package/dist/src/commands/port-ownership.d.ts +69 -0
  115. package/dist/src/commands/port-ownership.d.ts.map +1 -0
  116. package/dist/src/commands/port-ownership.js +161 -0
  117. package/dist/src/commands/port-ownership.js.map +1 -0
  118. package/dist/src/commands/registry-publish.d.ts +3 -0
  119. package/dist/src/commands/registry-publish.d.ts.map +1 -0
  120. package/dist/src/commands/registry-publish.js +161 -0
  121. package/dist/src/commands/registry-publish.js.map +1 -0
  122. package/dist/src/commands/registry.d.ts +146 -2
  123. package/dist/src/commands/registry.d.ts.map +1 -1
  124. package/dist/src/commands/registry.js +541 -85
  125. package/dist/src/commands/registry.js.map +1 -1
  126. package/dist/src/commands/secrets/index.d.ts.map +1 -1
  127. package/dist/src/commands/secrets/index.js +15 -1
  128. package/dist/src/commands/secrets/index.js.map +1 -1
  129. package/dist/src/commands/secrets/migrate-config.d.ts +24 -0
  130. package/dist/src/commands/secrets/migrate-config.d.ts.map +1 -0
  131. package/dist/src/commands/secrets/migrate-config.js +277 -0
  132. package/dist/src/commands/secrets/migrate-config.js.map +1 -0
  133. package/dist/src/commands/secrets/set.d.ts +1 -0
  134. package/dist/src/commands/secrets/set.d.ts.map +1 -1
  135. package/dist/src/commands/secrets/set.js +96 -2
  136. package/dist/src/commands/secrets/set.js.map +1 -1
  137. package/dist/src/commands/skills.d.ts +34 -0
  138. package/dist/src/commands/skills.d.ts.map +1 -0
  139. package/dist/src/commands/skills.js +207 -0
  140. package/dist/src/commands/skills.js.map +1 -0
  141. package/dist/src/commands/stack.d.ts.map +1 -1
  142. package/dist/src/commands/stack.js +361 -23
  143. package/dist/src/commands/stack.js.map +1 -1
  144. package/dist/src/commands/temporal.d.ts +15 -0
  145. package/dist/src/commands/temporal.d.ts.map +1 -0
  146. package/dist/src/commands/temporal.js +781 -0
  147. package/dist/src/commands/temporal.js.map +1 -0
  148. package/dist/src/commands/tenant.d.ts +56 -0
  149. package/dist/src/commands/tenant.d.ts.map +1 -0
  150. package/dist/src/commands/tenant.js +233 -0
  151. package/dist/src/commands/tenant.js.map +1 -0
  152. package/dist/src/commands/tunnel/index.d.ts +49 -3
  153. package/dist/src/commands/tunnel/index.d.ts.map +1 -1
  154. package/dist/src/commands/tunnel/index.js +331 -8
  155. package/dist/src/commands/tunnel/index.js.map +1 -1
  156. package/dist/src/commands/vcs/clone.d.ts +3 -0
  157. package/dist/src/commands/vcs/clone.d.ts.map +1 -0
  158. package/dist/src/commands/vcs/clone.js +20 -0
  159. package/dist/src/commands/vcs/clone.js.map +1 -0
  160. package/dist/src/commands/vcs/common.d.ts +21 -0
  161. package/dist/src/commands/vcs/common.d.ts.map +1 -0
  162. package/dist/src/commands/vcs/common.js +62 -0
  163. package/dist/src/commands/vcs/common.js.map +1 -0
  164. package/dist/src/commands/vcs/drafts.d.ts +13 -0
  165. package/dist/src/commands/vcs/drafts.d.ts.map +1 -0
  166. package/dist/src/commands/vcs/drafts.js +45 -0
  167. package/dist/src/commands/vcs/drafts.js.map +1 -0
  168. package/dist/src/commands/vcs/get.d.ts +8 -0
  169. package/dist/src/commands/vcs/get.d.ts.map +1 -0
  170. package/dist/src/commands/vcs/get.js +61 -0
  171. package/dist/src/commands/vcs/get.js.map +1 -0
  172. package/dist/src/commands/vcs/index.d.ts +3 -0
  173. package/dist/src/commands/vcs/index.d.ts.map +1 -0
  174. package/dist/src/commands/vcs/index.js +58 -0
  175. package/dist/src/commands/vcs/index.js.map +1 -0
  176. package/dist/src/commands/vcs/propose.d.ts +23 -0
  177. package/dist/src/commands/vcs/propose.d.ts.map +1 -0
  178. package/dist/src/commands/vcs/propose.js +94 -0
  179. package/dist/src/commands/vcs/propose.js.map +1 -0
  180. package/dist/src/commands/vcs/review.d.ts +15 -0
  181. package/dist/src/commands/vcs/review.d.ts.map +1 -0
  182. package/dist/src/commands/vcs/review.js +35 -0
  183. package/dist/src/commands/vcs/review.js.map +1 -0
  184. package/dist/src/commands/vcs-enrich.d.ts +15 -0
  185. package/dist/src/commands/vcs-enrich.d.ts.map +1 -0
  186. package/dist/src/commands/vcs-enrich.js +28 -0
  187. package/dist/src/commands/vcs-enrich.js.map +1 -0
  188. package/dist/src/commands/vpn/index.d.ts +24 -0
  189. package/dist/src/commands/vpn/index.d.ts.map +1 -0
  190. package/dist/src/commands/vpn/index.js +543 -0
  191. package/dist/src/commands/vpn/index.js.map +1 -0
  192. package/dist/src/commands/vpn/tunnel.d.ts +11 -0
  193. package/dist/src/commands/vpn/tunnel.d.ts.map +1 -0
  194. package/dist/src/commands/vpn/tunnel.js +188 -0
  195. package/dist/src/commands/vpn/tunnel.js.map +1 -0
  196. package/dist/src/commands/workflow.d.ts +24 -0
  197. package/dist/src/commands/workflow.d.ts.map +1 -0
  198. package/dist/src/commands/workflow.js +577 -0
  199. package/dist/src/commands/workflow.js.map +1 -0
  200. package/dist/src/docs/assemble.d.ts +217 -0
  201. package/dist/src/docs/assemble.d.ts.map +1 -0
  202. package/dist/src/docs/assemble.js +739 -0
  203. package/dist/src/docs/assemble.js.map +1 -0
  204. package/dist/src/docs/cli-reference.d.ts +93 -0
  205. package/dist/src/docs/cli-reference.d.ts.map +1 -0
  206. package/dist/src/docs/cli-reference.js +256 -0
  207. package/dist/src/docs/cli-reference.js.map +1 -0
  208. package/dist/src/docs/discover.d.ts +60 -0
  209. package/dist/src/docs/discover.d.ts.map +1 -0
  210. package/dist/src/docs/discover.js +233 -0
  211. package/dist/src/docs/discover.js.map +1 -0
  212. package/dist/src/docs/portal.d.ts +79 -0
  213. package/dist/src/docs/portal.d.ts.map +1 -0
  214. package/dist/src/docs/portal.js +242 -0
  215. package/dist/src/docs/portal.js.map +1 -0
  216. package/dist/src/docs/registry-docs.d.ts +43 -0
  217. package/dist/src/docs/registry-docs.d.ts.map +1 -0
  218. package/dist/src/docs/registry-docs.js +138 -0
  219. package/dist/src/docs/registry-docs.js.map +1 -0
  220. package/dist/src/docs/schema.d.ts +48 -0
  221. package/dist/src/docs/schema.d.ts.map +1 -0
  222. package/dist/src/docs/schema.js +96 -0
  223. package/dist/src/docs/schema.js.map +1 -0
  224. package/dist/src/docs/serve.d.ts +27 -0
  225. package/dist/src/docs/serve.d.ts.map +1 -0
  226. package/dist/src/docs/serve.js +102 -0
  227. package/dist/src/docs/serve.js.map +1 -0
  228. package/dist/src/docs/start.d.ts +80 -0
  229. package/dist/src/docs/start.d.ts.map +1 -0
  230. package/dist/src/docs/start.js +313 -0
  231. package/dist/src/docs/start.js.map +1 -0
  232. package/dist/src/eval/agent-eval.d.mts +14 -0
  233. package/dist/src/eval/agent-eval.d.mts.map +1 -0
  234. package/dist/src/eval/agent-eval.mjs +273 -0
  235. package/dist/src/eval/agent-eval.mjs.map +1 -0
  236. package/dist/src/index.js +624 -7
  237. package/dist/src/index.js.map +7 -1
  238. package/dist/src/program.d.ts +26 -0
  239. package/dist/src/program.d.ts.map +1 -0
  240. package/dist/src/program.js +76 -0
  241. package/dist/src/program.js.map +1 -0
  242. package/dist/src/utils/auth-preflight.d.ts +159 -0
  243. package/dist/src/utils/auth-preflight.d.ts.map +1 -0
  244. package/dist/src/utils/auth-preflight.js +298 -0
  245. package/dist/src/utils/auth-preflight.js.map +1 -0
  246. package/dist/src/utils/aws-auth.d.ts +181 -0
  247. package/dist/src/utils/aws-auth.d.ts.map +1 -0
  248. package/dist/src/utils/aws-auth.js +527 -0
  249. package/dist/src/utils/aws-auth.js.map +1 -0
  250. package/dist/src/utils/bastion.d.ts +1 -1
  251. package/dist/src/utils/bastion.d.ts.map +1 -1
  252. package/dist/src/utils/bastion.js +29 -8
  253. package/dist/src/utils/bastion.js.map +1 -1
  254. package/dist/src/utils/build-info.d.ts +33 -0
  255. package/dist/src/utils/build-info.d.ts.map +1 -0
  256. package/dist/src/utils/build-info.js +102 -0
  257. package/dist/src/utils/build-info.js.map +1 -0
  258. package/dist/src/utils/capture-history.d.ts +62 -0
  259. package/dist/src/utils/capture-history.d.ts.map +1 -0
  260. package/dist/src/utils/capture-history.js +94 -0
  261. package/dist/src/utils/capture-history.js.map +1 -0
  262. package/dist/src/utils/deploy-preflight.d.ts +52 -0
  263. package/dist/src/utils/deploy-preflight.d.ts.map +1 -0
  264. package/dist/src/utils/deploy-preflight.js +183 -0
  265. package/dist/src/utils/deploy-preflight.js.map +1 -0
  266. package/dist/src/utils/errors.d.ts +75 -0
  267. package/dist/src/utils/errors.d.ts.map +1 -0
  268. package/dist/src/utils/errors.js +106 -0
  269. package/dist/src/utils/errors.js.map +1 -0
  270. package/dist/src/utils/first-party-contexts.d.ts +40 -0
  271. package/dist/src/utils/first-party-contexts.d.ts.map +1 -0
  272. package/dist/src/utils/first-party-contexts.js +53 -0
  273. package/dist/src/utils/first-party-contexts.js.map +1 -0
  274. package/dist/src/utils/index.d.ts +2 -0
  275. package/dist/src/utils/index.d.ts.map +1 -1
  276. package/dist/src/utils/index.js +2 -0
  277. package/dist/src/utils/index.js.map +1 -1
  278. package/dist/src/utils/kubeconfig.d.ts +62 -0
  279. package/dist/src/utils/kubeconfig.d.ts.map +1 -0
  280. package/dist/src/utils/kubeconfig.js +118 -0
  281. package/dist/src/utils/kubeconfig.js.map +1 -0
  282. package/dist/src/utils/log.d.ts +27 -1
  283. package/dist/src/utils/log.d.ts.map +1 -1
  284. package/dist/src/utils/log.js +59 -5
  285. package/dist/src/utils/log.js.map +1 -1
  286. package/dist/src/utils/pid.d.ts +47 -0
  287. package/dist/src/utils/pid.d.ts.map +1 -0
  288. package/dist/src/utils/pid.js +83 -0
  289. package/dist/src/utils/pid.js.map +1 -0
  290. package/dist/src/utils/pulumi-run.d.ts +23 -0
  291. package/dist/src/utils/pulumi-run.d.ts.map +1 -0
  292. package/dist/src/utils/pulumi-run.js +112 -0
  293. package/dist/src/utils/pulumi-run.js.map +1 -0
  294. package/dist/src/utils/pulumi.d.ts +15 -0
  295. package/dist/src/utils/pulumi.d.ts.map +1 -1
  296. package/dist/src/utils/pulumi.js +35 -0
  297. package/dist/src/utils/pulumi.js.map +1 -1
  298. package/dist/src/utils/reachability.d.ts +29 -0
  299. package/dist/src/utils/reachability.d.ts.map +1 -0
  300. package/dist/src/utils/reachability.js +81 -0
  301. package/dist/src/utils/reachability.js.map +1 -0
  302. package/dist/src/utils/recover-conversation.d.ts +154 -0
  303. package/dist/src/utils/recover-conversation.d.ts.map +1 -0
  304. package/dist/src/utils/recover-conversation.js +314 -0
  305. package/dist/src/utils/recover-conversation.js.map +1 -0
  306. package/dist/src/utils/registry-broker.d.ts +148 -0
  307. package/dist/src/utils/registry-broker.d.ts.map +1 -0
  308. package/dist/src/utils/registry-broker.js +180 -0
  309. package/dist/src/utils/registry-broker.js.map +1 -0
  310. package/dist/src/utils/socks-forward.d.ts +40 -0
  311. package/dist/src/utils/socks-forward.d.ts.map +1 -0
  312. package/dist/src/utils/socks-forward.js +97 -0
  313. package/dist/src/utils/socks-forward.js.map +1 -0
  314. package/dist/src/utils/stack-flag.d.ts +23 -0
  315. package/dist/src/utils/stack-flag.d.ts.map +1 -0
  316. package/dist/src/utils/stack-flag.js +41 -0
  317. package/dist/src/utils/stack-flag.js.map +1 -0
  318. package/dist/src/utils/tailscale-targets.d.ts +52 -0
  319. package/dist/src/utils/tailscale-targets.d.ts.map +1 -0
  320. package/dist/src/utils/tailscale-targets.js +93 -0
  321. package/dist/src/utils/tailscale-targets.js.map +1 -0
  322. package/dist/src/utils/tailscale.d.ts +277 -0
  323. package/dist/src/utils/tailscale.d.ts.map +1 -0
  324. package/dist/src/utils/tailscale.js +1007 -0
  325. package/dist/src/utils/tailscale.js.map +1 -0
  326. package/dist/src/utils/temporal-auth.d.ts +43 -0
  327. package/dist/src/utils/temporal-auth.d.ts.map +1 -0
  328. package/dist/src/utils/temporal-auth.js +176 -0
  329. package/dist/src/utils/temporal-auth.js.map +1 -0
  330. package/dist/src/utils/temporal-codec.d.ts +101 -0
  331. package/dist/src/utils/temporal-codec.d.ts.map +1 -0
  332. package/dist/src/utils/temporal-codec.js +319 -0
  333. package/dist/src/utils/temporal-codec.js.map +1 -0
  334. package/dist/src/utils/tunnel-ownership.d.ts +130 -0
  335. package/dist/src/utils/tunnel-ownership.d.ts.map +1 -0
  336. package/dist/src/utils/tunnel-ownership.js +274 -0
  337. package/dist/src/utils/tunnel-ownership.js.map +1 -0
  338. package/dist/src/utils/vpn-join.d.ts +32 -0
  339. package/dist/src/utils/vpn-join.d.ts.map +1 -0
  340. package/dist/src/utils/vpn-join.js +62 -0
  341. package/dist/src/utils/vpn-join.js.map +1 -0
  342. package/dist/src/utils/vpn.d.ts +62 -0
  343. package/dist/src/utils/vpn.d.ts.map +1 -0
  344. package/dist/src/utils/vpn.js +183 -0
  345. package/dist/src/utils/vpn.js.map +1 -0
  346. package/dist/src/utils/workflow-fingerprint.d.ts +49 -0
  347. package/dist/src/utils/workflow-fingerprint.d.ts.map +1 -0
  348. package/dist/src/utils/workflow-fingerprint.js +135 -0
  349. package/dist/src/utils/workflow-fingerprint.js.map +1 -0
  350. package/dist/src/utils/worktree-identity.d.ts +86 -0
  351. package/dist/src/utils/worktree-identity.d.ts.map +1 -0
  352. package/dist/src/utils/worktree-identity.js +164 -0
  353. package/dist/src/utils/worktree-identity.js.map +1 -0
  354. package/fragments/agents/AGENTS.md.hbs +92 -0
  355. package/fragments/agents/CLAUDE.md.hbs +8 -0
  356. package/fragments/base/Pulumi.dev.yaml.hbs +10 -0
  357. package/fragments/base/Pulumi.yaml.hbs +9 -0
  358. package/fragments/base/index.ts.hbs +107 -0
  359. package/fragments/base/package.json.hbs +22 -0
  360. package/{templates/api-web-db/api → fragments/base}/tsconfig.json +3 -4
  361. package/fragments/bucket/api/src/storage.ts.hbs +81 -0
  362. package/fragments/database/api/src/db.ts.hbs +23 -0
  363. package/fragments/database/prisma/schema.prisma.hbs +18 -0
  364. package/{templates/api-web-db → fragments/service}/api/.dockerignore +2 -0
  365. package/fragments/service/api/package.json.hbs +40 -0
  366. package/fragments/service/api/src/index.ts.hbs +58 -0
  367. package/{templates/api-web-db → fragments/service/api}/tsconfig.json +5 -3
  368. package/fragments/temporal/worker/.dockerignore +4 -0
  369. package/fragments/temporal/worker/Dockerfile +15 -0
  370. package/{templates/temporal-api-worker → fragments/temporal}/worker/package.json.hbs +3 -2
  371. package/fragments/temporal/worker/src/activities.ts.hbs +14 -0
  372. package/fragments/temporal/worker/src/worker.ts.hbs +27 -0
  373. package/fragments/temporal/worker/src/workflows.ts.hbs +24 -0
  374. package/fragments/temporal/worker/tsconfig.json +13 -0
  375. package/package.json +36 -22
  376. package/skills/core/SKILL.md +365 -0
  377. package/skills/pull-remote-agent-context/SKILL.md +194 -0
  378. package/stack/docker-compose.hub.yml +134 -0
  379. package/stack/docker-compose.yml +447 -0
  380. package/stack/hub/Dockerfile.api +18 -0
  381. package/stack/hub/Dockerfile.auth +10 -0
  382. package/stack/hub/Dockerfile.ui +10 -0
  383. package/stack/init/01-databases.sql +12 -0
  384. package/stack/observability/blackbox.yml +20 -0
  385. package/stack/observability/otel-collector.yaml +73 -0
  386. package/stack/observability/prometheus.yml +36 -0
  387. package/stack/observability/tempo.yaml +25 -0
  388. package/stack/temporal/local.yaml +44 -0
  389. package/templates/api-auth/AGENTS.md.hbs +16 -0
  390. package/templates/api-auth/Pulumi.dev.yaml.hbs +8 -0
  391. package/templates/api-auth/Pulumi.yaml.hbs +8 -0
  392. package/templates/api-auth/README.md.hbs +67 -0
  393. package/templates/api-auth/api/package.json.hbs +28 -0
  394. package/templates/api-auth/api/src/index.ts.hbs +96 -0
  395. package/templates/api-auth/api/src/schema.ts.hbs +35 -0
  396. package/templates/api-auth/api/src/seed-authz.ts.hbs +48 -0
  397. package/templates/api-auth/api/src/spicedb-http-provider.ts.hbs +89 -0
  398. package/templates/api-auth/index.ts.hbs +65 -0
  399. package/templates/api-auth/package.json.hbs +20 -0
  400. package/templates/api-auth/skills/develop/SKILL.md.hbs +32 -0
  401. package/templates/api-role-gating/AGENTS.md.hbs +20 -0
  402. package/templates/api-role-gating/Pulumi.dev.yaml.hbs +8 -0
  403. package/templates/api-role-gating/Pulumi.yaml.hbs +8 -0
  404. package/templates/api-role-gating/README.md.hbs +64 -0
  405. package/templates/api-role-gating/api/Dockerfile +17 -0
  406. package/templates/api-role-gating/api/package.json.hbs +28 -0
  407. package/templates/api-role-gating/api/src/authn.ts.hbs +29 -0
  408. package/templates/api-role-gating/api/src/authz.ts.hbs +12 -0
  409. package/templates/api-role-gating/api/src/main.ts.hbs +58 -0
  410. package/templates/api-role-gating/api/src/schema.ts.hbs +22 -0
  411. package/templates/api-role-gating/api/tsconfig.json +13 -0
  412. package/templates/api-role-gating/index.ts.hbs +107 -0
  413. package/templates/api-role-gating/package.json.hbs +21 -0
  414. package/templates/api-role-gating/skills/develop/SKILL.md.hbs +60 -0
  415. package/templates/api-role-gating/tsconfig.json +10 -0
  416. package/templates/apps-repo/README.md.hbs +24 -0
  417. package/templates/apps-repo/gitignore +41 -0
  418. package/templates/apps-repo/npmrc.hbs +7 -0
  419. package/templates/apps-repo/package.json.hbs +15 -0
  420. package/templates/apps-repo/pnpm-workspace.yaml +3 -0
  421. package/templates/apps-repo/tsconfig.json +18 -0
  422. package/templates/external-service/AGENTS.md.hbs +20 -0
  423. package/templates/external-service/Pulumi.dev.yaml.hbs +8 -0
  424. package/templates/external-service/Pulumi.yaml.hbs +8 -0
  425. package/templates/external-service/README.md.hbs +56 -0
  426. package/templates/external-service/api/Dockerfile +15 -0
  427. package/templates/external-service/api/package.json.hbs +25 -0
  428. package/templates/external-service/api/src/index.ts.hbs +81 -0
  429. package/templates/external-service/index.ts.hbs +82 -0
  430. package/templates/external-service/mocks/vendorpay/package.json.hbs +9 -0
  431. package/templates/external-service/mocks/vendorpay/server.mjs.hbs +61 -0
  432. package/templates/external-service/package.json.hbs +34 -0
  433. package/templates/external-service/skills/develop/SKILL.md.hbs +55 -0
  434. package/templates/external-service/tsconfig.json +10 -0
  435. package/templates/platform-repo/AGENTS.md.hbs +18 -0
  436. package/templates/platform-repo/README.md.hbs +38 -0
  437. package/templates/platform-repo/core/Pulumi.yaml.hbs +12 -0
  438. package/templates/platform-repo/core/Pulumi.{{tenant}}-{{env}}.yaml.hbs +57 -0
  439. package/templates/platform-repo/core/index.ts +62 -0
  440. package/templates/platform-repo/core/package.json.hbs +22 -0
  441. package/templates/platform-repo/core/tsconfig.json +8 -0
  442. package/templates/platform-repo/package.json.hbs +15 -0
  443. package/templates/platform-repo/platform/Pulumi.yaml.hbs +12 -0
  444. package/templates/platform-repo/platform/Pulumi.{{tenant}}-{{env}}.yaml.hbs +59 -0
  445. package/templates/platform-repo/platform/index.ts +95 -0
  446. package/templates/platform-repo/platform/package.json.hbs +26 -0
  447. package/templates/platform-repo/platform/tsconfig.json +8 -0
  448. package/templates/platform-repo/pnpm-workspace.yaml +3 -0
  449. package/templates/workflow/AGENTS.md.hbs +15 -0
  450. package/templates/workflow/Pulumi.dev.yaml.hbs +8 -0
  451. package/templates/workflow/Pulumi.yaml.hbs +8 -0
  452. package/templates/workflow/README.md.hbs +45 -0
  453. package/templates/workflow/api/.dockerignore +4 -0
  454. package/templates/workflow/api/Dockerfile +15 -0
  455. package/templates/{temporal-api-worker → workflow}/api/package.json.hbs +8 -6
  456. package/templates/workflow/api/src/index.ts.hbs +130 -0
  457. package/templates/workflow/api/tsconfig.json +14 -0
  458. package/templates/workflow/index.ts.hbs +67 -0
  459. package/templates/workflow/package.json.hbs +20 -0
  460. package/templates/workflow/skills/develop/SKILL.md.hbs +32 -0
  461. package/templates/workflow/tsconfig.json +10 -0
  462. package/templates/workflow/worker/.dockerignore +4 -0
  463. package/templates/workflow/worker/Dockerfile +13 -0
  464. package/templates/workflow/worker/package.json.hbs +25 -0
  465. package/templates/workflow/worker/src/worker.ts.hbs +24 -0
  466. package/templates/workflow/worker/tsconfig.json +14 -0
  467. package/dist/src/commands/devbox.d.ts +0 -22
  468. package/dist/src/commands/devbox.d.ts.map +0 -1
  469. package/dist/src/commands/devbox.js +0 -463
  470. package/dist/src/commands/devbox.js.map +0 -1
  471. package/templates/api-web-db/api/Dockerfile +0 -16
  472. package/templates/api-web-db/api/package.json.hbs +0 -21
  473. package/templates/api-web-db/api/src/index.ts.hbs +0 -123
  474. package/templates/api-web-db/package.json.hbs +0 -27
  475. package/templates/api-web-db/sst.config.ts.hbs +0 -151
  476. package/templates/api-web-db/web/.dockerignore +0 -3
  477. package/templates/api-web-db/web/Dockerfile +0 -17
  478. package/templates/api-web-db/web/app/lib/db.server.ts +0 -36
  479. package/templates/api-web-db/web/app/root.tsx +0 -29
  480. package/templates/api-web-db/web/app/routes/home.tsx.hbs +0 -114
  481. package/templates/api-web-db/web/app/routes.ts +0 -3
  482. package/templates/api-web-db/web/package.json.hbs +0 -30
  483. package/templates/api-web-db/web/prisma/schema.prisma +0 -25
  484. package/templates/api-web-db/web/prisma.config.ts +0 -18
  485. package/templates/api-web-db/web/react-router.config.ts +0 -5
  486. package/templates/api-web-db/web/tsconfig.json +0 -19
  487. package/templates/api-web-db/web/vite.config.ts +0 -9
  488. package/templates/temporal-api-worker/README.md.hbs +0 -133
  489. package/templates/temporal-api-worker/api/src/index.ts.hbs +0 -145
  490. package/templates/temporal-api-worker/package.json.hbs +0 -29
  491. package/templates/temporal-api-worker/sst.config.ts.hbs +0 -161
  492. package/templates/temporal-api-worker/worker/Dockerfile +0 -11
  493. package/templates/temporal-api-worker/worker/src/bundle-workflows.ts +0 -38
  494. package/templates/temporal-api-worker/worker/src/worker.ts.hbs +0 -93
  495. /package/templates/{temporal-api-worker → api-auth}/api/.dockerignore +0 -0
  496. /package/templates/{temporal-api-worker → api-auth}/api/Dockerfile +0 -0
  497. /package/templates/{temporal-api-worker → api-auth}/api/tsconfig.json +0 -0
  498. /package/templates/{temporal-api-worker → api-auth}/tsconfig.json +0 -0
  499. /package/templates/{temporal-api-worker/worker → api-role-gating/api}/.dockerignore +0 -0
  500. /package/templates/{temporal-api-worker/worker → external-service/api}/tsconfig.json +0 -0
  501. /package/templates/{temporal-api-worker → workflow}/api/src/encryption-codec.ts +0 -0
  502. /package/templates/{temporal-api-worker → workflow}/worker/src/activities.ts.hbs +0 -0
  503. /package/templates/{temporal-api-worker → workflow}/worker/src/encryption-codec.ts +0 -0
  504. /package/templates/{temporal-api-worker → workflow}/worker/src/workflows.ts.hbs +0 -0
@@ -4,22 +4,33 @@
4
4
  * Handles CodeArtifact token refresh and project .npmrc setup so that
5
5
  * `pnpm install` can resolve @mesh-tech/* packages from the private registry.
6
6
  *
7
- * Credential resolution (same as mesh deploy):
7
+ * Credential resolution, in order:
8
+ * 0. The Zitadel-gated registry-auth BROKER — needs no AWS anything on this
9
+ * machine. This is the path a brand-new developer takes.
8
10
  * 1. Existing AWS credentials in environment (CI/CD) → use directly
9
11
  * 2. Zitadel JWT from `mesh login` → AssumeRoleWithWebIdentity
10
12
  * 3. AWS SSO / current profile → use directly
11
13
  *
14
+ * Paths 1–3 all shell out to the AWS CLI, so they require it to be installed
15
+ * and credentialed. Path 0 requires only a Mesh account, which is the whole
16
+ * point (design: registry-access-without-aws-sso).
17
+ *
12
18
  * Usage:
13
19
  * mesh registry login — refresh token, ensure .npmrc
14
- * mesh registry login mesh.dev — use Zitadel JWT for role assumption
20
+ * mesh registry login mesh.dev — broker first, then the AWS paths
15
21
  * mesh registry login --ci — CI mode (skip .npmrc creation)
22
+ * mesh registry login --no-broker — skip the broker, force the AWS paths
16
23
  * mesh registry status — show current auth state
17
24
  */
18
25
  import { execFileSync } from "child_process";
19
26
  import * as fs from "fs";
20
27
  import * as path from "path";
21
28
  import { logError, logInfo, logSuccess, logWarn } from "../utils/log.js";
29
+ import { MeshCliError } from "../utils/errors.js";
30
+ import { awsConfigHasProfile, findUnscopedCodeArtifactRegistry, homeNpmrcPath, npmrcAuthKeyForEndpoint, probeRegistryToken, readAwsConfig, REGISTRY_CONTEXT, SSO_SESSION_SNIPPET, stripUnscopedCodeArtifactRegistry, upsertNpmrcLines, } from "../utils/auth-preflight.js";
31
+ import { fetchRegistryGrant, realGrantDeps, DERIVED_BROKER_TIMEOUT_MS, PUBLISHED_BROKER_TIMEOUT_MS, resolveDefaultBrokerContext, resolveRegistryBrokerSource, } from "../utils/registry-broker.js";
22
32
  import { readCredentials } from "./login.js";
33
+ import { registerRegistryPublish } from "./registry-publish.js";
23
34
  // =============================================================================
24
35
  // Constants — platform CodeArtifact registry
25
36
  // =============================================================================
@@ -60,7 +71,7 @@ function getEndpoint(env) {
60
71
  /**
61
72
  * Run `aws codeartifact login` to set the auth token in ~/.npmrc.
62
73
  */
63
- function codeartifactLogin(env) {
74
+ export function codeartifactLogin(env) {
64
75
  try {
65
76
  execFileSync("aws", [
66
77
  "codeartifact", "login",
@@ -80,6 +91,57 @@ function codeartifactLogin(env) {
80
91
  return false;
81
92
  }
82
93
  }
94
+ /**
95
+ * Parse a mesh context like "mesh.dev" into tenant + env.
96
+ * Returns null if the context doesn't match the expected {tenant}.{env} pattern.
97
+ *
98
+ * (Mirrors login.ts's parseTenantEnv — kept local/minimal here to avoid
99
+ * expanding login.ts's export surface for a single caller.)
100
+ */
101
+ function parseTenantEnv(context) {
102
+ const parts = context.split(".");
103
+ if (parts.length !== 2 || !parts[0] || !parts[1])
104
+ return null;
105
+ return { tenant: parts[0], env: parts[1] };
106
+ }
107
+ /**
108
+ * Read the registry's SSM export (published by PackageRegistry, Task 2 of
109
+ * MESH-2168) for a given tenant/env, e.g. /mesh-platform/mesh/dev/registry.
110
+ *
111
+ * Returns null on any failure (missing param, no AWS creds, malformed JSON) —
112
+ * callers treat a null publisherRoleArn as "not configured" and surface an
113
+ * actionable error via resolvePublisherRoleArn.
114
+ */
115
+ async function getRegistrySsmExport(tenant, env) {
116
+ try {
117
+ const { SSMClient, GetParameterCommand } = await import("@aws-sdk/client-ssm");
118
+ const region = process.env.AWS_REGION ?? process.env.AWS_DEFAULT_REGION ?? CA_REGION;
119
+ const ssm = new SSMClient({ region });
120
+ const ssmPath = `/mesh-platform/${tenant}/${env}/registry`;
121
+ const response = await ssm.send(new GetParameterCommand({ Name: ssmPath }));
122
+ if (!response.Parameter?.Value)
123
+ return null;
124
+ return JSON.parse(response.Parameter.Value);
125
+ }
126
+ catch {
127
+ return null;
128
+ }
129
+ }
130
+ /**
131
+ * Resolve the publisher role ARN to assume for `--publish`.
132
+ *
133
+ * Precedence: explicit --role-arn flag wins, then the registry's SSM export
134
+ * (publisherRoleArn, Task 2 of MESH-2168). Throws an actionable error if
135
+ * neither is available — there's no safe default to fall back to since
136
+ * publishing is an opt-in privileged path (DEFAULT_REGISTRY_ROLE stays null).
137
+ */
138
+ export function resolvePublisherRoleArn({ roleArnFlag, ssmArn, }) {
139
+ const resolved = roleArnFlag || ssmArn;
140
+ if (!resolved) {
141
+ throw new Error("No publisher role: pass --role or ensure the registry stack exported publisherRoleArn (MESH-2168).");
142
+ }
143
+ return resolved;
144
+ }
83
145
  /**
84
146
  * Assume an IAM role, return credential env vars.
85
147
  */
@@ -130,7 +192,7 @@ function assumeRoleWithWebIdentity(roleArn, idToken, sessionName) {
130
192
  *
131
193
  * Returns env var overrides (or empty object if current env is fine).
132
194
  */
133
- function resolveCredentials(context, roleArn) {
195
+ export function resolveCredentials(context, roleArn) {
134
196
  // Path 1: Existing AWS credentials in environment
135
197
  if (process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SESSION_TOKEN) {
136
198
  logInfo("Using existing AWS credentials from environment");
@@ -229,26 +291,476 @@ function ensureProjectNpmrc(endpoint) {
229
291
  return { created: false, updated: true, path: npmrcPath };
230
292
  }
231
293
  /**
232
- * Check if the current ~/.npmrc has a valid CodeArtifact token for our registry.
294
+ * Write a broker-issued grant into ~/.npmrc: the scoped registry line and the
295
+ * endpoint's auth token, in exactly the shape `aws codeartifact login
296
+ * --namespace @mesh-tech` would have written.
297
+ *
298
+ * Byte-compatibility with the AWS CLI's output is the requirement, not a nicety:
299
+ * `mesh registry status`, the `mesh start` preflight and the dev doctor all
300
+ * parse ~/.npmrc for that pair, and a machine that gets its token from the
301
+ * broker has to look identical to one that got it from AWS.
302
+ */
303
+ export function applyGrantToUserNpmrc(grant, npmrcPath = homeNpmrcPath()) {
304
+ let existing = "";
305
+ try {
306
+ existing = fs.readFileSync(npmrcPath, "utf-8");
307
+ }
308
+ catch {
309
+ // no ~/.npmrc yet — a clean laptop, which is the case this exists for
310
+ }
311
+ const content = upsertNpmrcLines(existing, [
312
+ { key: `${grant.scope}:registry`, value: grant.endpoint },
313
+ { key: `${npmrcAuthKeyForEndpoint(grant.endpoint)}:_authToken`, value: grant.authorizationToken },
314
+ ]);
315
+ fs.mkdirSync(path.dirname(npmrcPath), { recursive: true });
316
+ fs.writeFileSync(npmrcPath, content, { mode: 0o600 });
317
+ // `mode` only applies when writeFileSync CREATES the file, so an existing
318
+ // 0644 ~/.npmrc would keep world-readable permissions on a 12h bearer token.
319
+ // Parity with `aws codeartifact login` either way, but one line buys better.
320
+ try {
321
+ fs.chmodSync(npmrcPath, 0o600);
322
+ }
323
+ catch {
324
+ // A read-only home or an exotic filesystem must not fail an otherwise-good login.
325
+ }
326
+ return { path: npmrcPath };
327
+ }
328
+ /**
329
+ * Human-facing explanation of a failed broker attempt, plus whether the AWS
330
+ * fallback chain is worth running.
331
+ *
332
+ * `not-authorized` is the one case we do NOT fall through on: the caller has a
333
+ * working Mesh account that simply lacks the grant, and quietly trying AWS next
334
+ * would either succeed (masking a missing grant with an AWS account we're
335
+ * trying to stop requiring) or fail with an unrelated AWS error that buries the
336
+ * real answer.
337
+ */
338
+ export function describeBrokerFailure(failure, context) {
339
+ switch (failure.kind) {
340
+ case "no-broker":
341
+ return {
342
+ message: "No registry broker published for this context — using the AWS paths.",
343
+ fatal: false,
344
+ };
345
+ case "no-session":
346
+ return {
347
+ message: `No valid Mesh session${context ? ` for ${context}` : ""} — using the AWS paths.`,
348
+ hint: context ? `mesh login ${context}` : "mesh login <context>",
349
+ fatal: false,
350
+ };
351
+ case "unauthenticated":
352
+ return {
353
+ message: "The registry broker rejected your Mesh session (expired or wrong audience).",
354
+ hint: context ? `mesh login ${context}` : "mesh login <context>",
355
+ fatal: false,
356
+ };
357
+ case "not-authorized":
358
+ return {
359
+ // The whole message lives in the body, not in a `remediation.command`:
360
+ // the answer here is "ask a human for a role", which is not a command
361
+ // anyone can run, and rendering a URL behind "→ run:" reads as one.
362
+ message: `Your Mesh account${failure.email ? ` (${failure.email})` : ""} is not authorized to read ` +
363
+ `${CA_NAMESPACE} packages.` +
364
+ (failure.requiredRoles?.length
365
+ ? `\n Needs one of these Zitadel roles: ${failure.requiredRoles.join(", ")}`
366
+ : "") +
367
+ (failure.requestUrl
368
+ ? `\n Request access: ${failure.requestUrl}`
369
+ : "\n Ask a Mesh platform admin to grant your account registry access."),
370
+ fatal: true,
371
+ };
372
+ case "unavailable":
373
+ return {
374
+ message: `Registry broker unavailable (${failure.detail}) — falling back to the AWS paths.`,
375
+ fatal: false,
376
+ };
377
+ }
378
+ }
379
+ /**
380
+ * Try the broker. Returns true when it produced a working ~/.npmrc, false when
381
+ * the caller should continue to the AWS credential chain.
382
+ *
383
+ * Throws `MeshCliError` only for `not-authorized` — see describeBrokerFailure.
384
+ */
385
+ async function tryBrokerLogin(contextArg, opts) {
386
+ if (opts.broker === false)
387
+ return null;
388
+ let context = contextArg;
389
+ if (!context) {
390
+ // A context-less invocation used to skip the broker silently — which sent
391
+ // anyone following a remediation that omits the context straight back to
392
+ // the AWS chain. Resolve one when it is unambiguous; say so when it isn't.
393
+ const resolved = resolveDefaultBrokerContext();
394
+ if ("context" in resolved) {
395
+ context = resolved.context;
396
+ logInfo(`No context given — using the only one with a registry broker: ${context}`);
397
+ }
398
+ else if (resolved.reason === "ambiguous") {
399
+ logInfo(`Skipping the registry broker: several contexts publish one (${resolved.candidates.join(", ")}). ` +
400
+ `Name it — e.g. \`mesh registry login ${resolved.candidates[0]}\`.`);
401
+ return null;
402
+ }
403
+ else {
404
+ logInfo("Skipping the registry broker: no signed-in context publishes one. " +
405
+ `To use it: \`mesh login ${REGISTRY_CONTEXT}\`, then \`mesh registry login ${REGISTRY_CONTEXT}\`.`);
406
+ return null;
407
+ }
408
+ }
409
+ const { url: brokerUrl, source } = resolveRegistryBrokerSource(context);
410
+ if (!brokerUrl) {
411
+ logInfo("No registry broker published for this context — using the AWS paths.");
412
+ return null;
413
+ }
414
+ logInfo(`Requesting a registry token from ${brokerUrl} (no AWS credentials needed)…`);
415
+ const result = await fetchRegistryGrant(context, brokerUrl, {
416
+ ...realGrantDeps(),
417
+ // A DERIVED url is a guess at a host that, for every platform not yet
418
+ // redeployed, does not exist — and this wait also sits on the `mesh login`
419
+ // path. Don't make everyone pay the published-broker timeout for a guess.
420
+ timeoutMs: source === "published" ? PUBLISHED_BROKER_TIMEOUT_MS : DERIVED_BROKER_TIMEOUT_MS,
421
+ });
422
+ if (result.ok)
423
+ return result.grant;
424
+ const { message, hint, fatal } = describeBrokerFailure(result.failure, context);
425
+ if (fatal) {
426
+ throw new MeshCliError(message, hint ? { remediation: { command: hint } } : undefined);
427
+ }
428
+ logWarn(message);
429
+ if (hint)
430
+ logInfo(` Try: ${hint}`);
431
+ return null;
432
+ }
433
+ /**
434
+ * Whether this `mesh registry login` invocation may rewrite ~/.npmrc.
435
+ *
436
+ * The self-heal is a **laptop** fix. CI pipelines run the unscoped
437
+ * `aws codeartifact login` DELIBERATELY — a host-scoped token is what lets
438
+ * pnpm pull upstream-cached public packages through CodeArtifact — so in a
439
+ * runner the "hijack" line is load-bearing and deleting it would break the
440
+ * install we were asked not to touch. `--ci` is the one signal that says so.
441
+ *
442
+ * Extracted (and tested) rather than left inline because "this changes no CI
443
+ * behaviour" is a promise about the code, not about the workflow files we
444
+ * happen not to have edited.
445
+ */
446
+ export function shouldRepairUserNpmrc(opts) {
447
+ return !opts.ci;
448
+ }
449
+ /**
450
+ * Repair a hijacked ~/.npmrc: remove an unscoped `registry=<codeartifact>`
451
+ * line if one is present, after taking a timestamped backup.
452
+ *
453
+ * `aws codeartifact login` run WITHOUT `--namespace @mesh-tech` writes that
454
+ * line, and nothing in this CLI used to remove it — so one bare login made
455
+ * CodeArtifact the default registry forever, and every public `npm install`
456
+ * started failing with E401 12 hours later when the token expired. We write
457
+ * the correct (scoped) state; this is the missing repair of the wrong state.
458
+ *
459
+ * Never throws — a repair failure must not fail an otherwise-good login.
233
460
  */
234
- function checkExistingToken() {
235
- const homeNpmrc = path.join(process.env.HOME ?? "~", ".npmrc");
236
- if (!fs.existsSync(homeNpmrc))
237
- return { valid: false };
238
- const content = fs.readFileSync(homeNpmrc, "utf-8");
239
- // Look for a CodeArtifact token line for our domain
240
- const hasToken = content.includes("mesh-platform") && content.includes("_authToken=");
241
- if (!hasToken)
242
- return { valid: false };
243
- // Try a quick endpoint lookup to verify the token works
244
- const endpoint = getEndpoint();
245
- if (!endpoint)
246
- return { valid: false };
247
- return { valid: true, endpoint };
461
+ export function repairUnscopedRegistry(npmrcPath = homeNpmrcPath()) {
462
+ let original;
463
+ try {
464
+ original = fs.readFileSync(npmrcPath, "utf-8");
465
+ }
466
+ catch {
467
+ return { removed: null }; // no ~/.npmrc → nothing to repair
468
+ }
469
+ const { content, removed } = stripUnscopedCodeArtifactRegistry(original);
470
+ if (!removed)
471
+ return { removed: null };
472
+ const backupPath = `${npmrcPath}.bak-${new Date().toISOString().replace(/[:.]/g, "-")}`;
473
+ try {
474
+ fs.writeFileSync(backupPath, original, "utf-8");
475
+ fs.writeFileSync(npmrcPath, content, "utf-8");
476
+ }
477
+ catch (err) {
478
+ return { removed: null, error: err instanceof Error ? err.message : String(err) };
479
+ }
480
+ return { removed, backupPath };
481
+ }
482
+ export async function checkExistingToken() {
483
+ const npmrcPath = homeNpmrcPath();
484
+ if (!fs.existsSync(npmrcPath))
485
+ return { valid: false, state: "missing", reason: "no ~/.npmrc" };
486
+ const hijackLine = findUnscopedCodeArtifactRegistry(fs.readFileSync(npmrcPath, "utf-8")) ?? undefined;
487
+ const probe = await probeRegistryToken({ npmrcPath });
488
+ if (probe.state === "missing") {
489
+ return { valid: false, state: probe.state, reason: "no CodeArtifact token in ~/.npmrc", hijackLine };
490
+ }
491
+ if (probe.state === "expired") {
492
+ return {
493
+ valid: false,
494
+ state: probe.state,
495
+ reason: probe.detail ?? "the CodeArtifact token is expired",
496
+ hijackLine,
497
+ };
498
+ }
499
+ if (probe.state === "unreachable") {
500
+ return {
501
+ valid: false,
502
+ state: probe.state,
503
+ reason: `could not reach the registry to verify the token (${probe.detail ?? "unknown error"})`,
504
+ hijackLine,
505
+ };
506
+ }
507
+ // Token works — a hijacked default registry still breaks public installs.
508
+ if (hijackLine) {
509
+ return { valid: false, state: probe.state, reason: "unscoped CodeArtifact registry", hijackLine };
510
+ }
511
+ return { valid: true, state: probe.state, endpoint: getEndpoint() ?? undefined };
512
+ }
513
+ /**
514
+ * `mesh registry status` — returns the process exit code instead of calling
515
+ * `process.exit`, so the "broken" vs "unverifiable" distinction is testable.
516
+ *
517
+ * Exit 1 is for faults the user can act on right now: a missing or expired
518
+ * token, or an unscoped CodeArtifact `registry=` line (locally detectable, and
519
+ * broken regardless of the network). An **unreachable** registry is neither —
520
+ * it warns and exits 0, because the remediation we'd print (`mesh registry
521
+ * login`) cannot work offline either, and the same rule already governs the
522
+ * `mesh init` doctor.
523
+ */
524
+ export async function runRegistryStatus(opts) {
525
+ const { valid, state, endpoint, reason, hijackLine } = await (opts?.check ?? checkExistingToken)();
526
+ if (hijackLine) {
527
+ logWarn("~/.npmrc sets CodeArtifact as your DEFAULT registry — every public npm install goes " +
528
+ "through it and will 401 when the 12h token expires:");
529
+ logInfo(` ${hijackLine.trim()}`);
530
+ logInfo("Fix: mesh registry login # removes it (backup taken) and keeps @mesh-tech scoped");
531
+ }
532
+ // A network fault is not an auth fault. Any *other* invalid state is.
533
+ const unverifiable = state === "unreachable" && !hijackLine;
534
+ if (!valid && !unverifiable) {
535
+ logWarn(`Registry auth is not usable${reason ? ` — ${reason}` : ""}. Run: mesh registry login`);
536
+ return 1;
537
+ }
538
+ if (unverifiable) {
539
+ logWarn(`Could not verify the CodeArtifact token in ~/.npmrc — ${reason}.`);
540
+ logInfo("Nothing to fix from here; retry when the registry is reachable.");
541
+ }
542
+ else {
543
+ logSuccess("CodeArtifact token in ~/.npmrc is valid");
544
+ if (endpoint) {
545
+ logInfo(`Endpoint: ${endpoint}`);
546
+ }
547
+ }
548
+ // Project .npmrc — worth reporting even when the token couldn't be verified.
549
+ const projectRoot = findProjectRoot();
550
+ if (projectRoot) {
551
+ const npmrcPath = path.join(projectRoot, ".npmrc");
552
+ if (fs.existsSync(npmrcPath)) {
553
+ const content = fs.readFileSync(npmrcPath, "utf-8");
554
+ if (content.includes(`${CA_NAMESPACE}:registry=`)) {
555
+ logSuccess(`Project .npmrc configured (${npmrcPath})`);
556
+ }
557
+ else {
558
+ logWarn(`Project .npmrc exists but missing ${CA_NAMESPACE} scope (${npmrcPath})`);
559
+ logInfo("Run: mesh registry login");
560
+ }
561
+ }
562
+ else {
563
+ logWarn(`No .npmrc in project root (${projectRoot})`);
564
+ logInfo("Run: mesh registry login");
565
+ }
566
+ }
567
+ return 0;
248
568
  }
249
569
  // =============================================================================
250
570
  // Commands
251
571
  // =============================================================================
572
+ /**
573
+ * Ensure the named AWS SSO profile has a live session — trigger the
574
+ * interactive `aws sso login` (browser) when it's stale.
575
+ *
576
+ * Guardrails (MESH-2479): a missing profile fails fast with the exact
577
+ * `aws configure` setup instead of an opaque CLI error, and the identity
578
+ * probes are time-bounded so a wedged AWS CLI can't hang this silently.
579
+ */
580
+ function ensureSsoProfile(profile) {
581
+ const awsConfig = readAwsConfig();
582
+ if (awsConfig && !awsConfigHasProfile(awsConfig, profile)) {
583
+ throw new MeshCliError(`AWS profile '${profile}' is not defined in ~/.aws/config — \`aws sso login --profile ${profile}\` cannot work until it exists.\n\n` +
584
+ "If you only need to INSTALL @mesh-tech packages, drop --profile: `mesh login <context>` then\n" +
585
+ "`mesh registry login <context>` uses the Zitadel-gated broker and needs no AWS account at all.\n\n" +
586
+ `If you DEPLOY and genuinely need this profile — one-time setup: \`aws configure sso --profile ${profile}\`,\n` +
587
+ `or add the session + profile by hand:\n` +
588
+ `${SSO_SESSION_SNIPPET}\n[profile ${profile}]\nsso_session = mesh\nsso_account_id = <account id>\nsso_role_name = <role>\nregion = us-east-2`, { remediation: { command: `aws configure sso --profile ${profile}` } });
589
+ }
590
+ const probe = () => execFileSync("aws", ["sts", "get-caller-identity", "--profile", profile], {
591
+ stdio: ["ignore", "pipe", "pipe"],
592
+ timeout: 20_000,
593
+ });
594
+ try {
595
+ probe();
596
+ logInfo(`AWS SSO session for profile '${profile}' is live`);
597
+ return;
598
+ }
599
+ catch {
600
+ logInfo(`AWS SSO session for profile '${profile}' is stale — opening browser login…`);
601
+ }
602
+ execFileSync("aws", ["sso", "login", "--profile", profile], { stdio: "inherit" });
603
+ try {
604
+ probe();
605
+ }
606
+ catch (err) {
607
+ throw new MeshCliError(`AWS SSO login for profile '${profile}' completed but the session still fails an identity check.`, {
608
+ remediation: { command: `aws sts get-caller-identity --profile ${profile} # see the underlying error` },
609
+ cause: err,
610
+ });
611
+ }
612
+ logSuccess(`AWS SSO session refreshed (profile '${profile}')`);
613
+ }
614
+ /**
615
+ * The full registry-auth sequence (CodeArtifact token → ~/.npmrc → project
616
+ * .npmrc). Shared by `mesh registry login` and `mesh login <context>` (F2:
617
+ * login absorbs registry auth).
618
+ */
619
+ export async function runRegistryLogin(context, opts) {
620
+ // --publish is the opt-in privileged path: resolve the publisher role
621
+ // (explicit --role flag wins, else the registry's SSM export) and feed
622
+ // it through the same Zitadel role-assumption path as the reader flow.
623
+ let roleArn = opts.role;
624
+ if (opts.publish) {
625
+ let ssmArn;
626
+ if (!opts.role) {
627
+ if (!context) {
628
+ logError('`--publish` requires a platform context, e.g. "mesh registry login mesh.dev --publish".');
629
+ process.exit(1);
630
+ }
631
+ const parsed = parseTenantEnv(context);
632
+ if (!parsed) {
633
+ logError(`Could not parse tenant/env from context "${context}" (expected "<tenant>.<env>").`);
634
+ process.exit(1);
635
+ }
636
+ const registryExport = await getRegistrySsmExport(parsed.tenant, parsed.env);
637
+ ssmArn = registryExport?.publisherRoleArn;
638
+ }
639
+ try {
640
+ roleArn = resolvePublisherRoleArn({ roleArnFlag: opts.role, ssmArn });
641
+ }
642
+ catch (err) {
643
+ logError(err.message);
644
+ process.exit(1);
645
+ }
646
+ logInfo(`Publisher role resolved: ${roleArn}`);
647
+ }
648
+ // Step 0: the broker. Tried FIRST for the read path, because it is the only
649
+ // one that works on a machine with no AWS account, no AWS CLI and no
650
+ // ~/.aws/config — the machine this whole feature exists for.
651
+ //
652
+ // Skipped for --publish (a privileged write path that deliberately goes
653
+ // through an assumed IAM role) and for --profile (an explicit "use this AWS
654
+ // profile" instruction we must not silently override).
655
+ if (!opts.publish && !opts.profile) {
656
+ const grant = await tryBrokerLogin(context, opts);
657
+ if (grant) {
658
+ const { path: npmrcPath } = applyGrantToUserNpmrc(grant);
659
+ logSuccess(`Registry token issued by the Mesh broker → ${npmrcPath}` +
660
+ (grant.expiresAt ? ` (expires ${grant.expiresAt})` : ""));
661
+ // Same hijack repair as the AWS path — an unscoped `registry=` line left
662
+ // by a past bare `aws codeartifact login` breaks public installs
663
+ // regardless of where today's token came from.
664
+ if (shouldRepairUserNpmrc(opts)) {
665
+ const repair = repairUnscopedRegistry();
666
+ if (repair.removed) {
667
+ logWarn("Removed an unscoped CodeArtifact `registry=` from ~/.npmrc — it routed ALL npm traffic " +
668
+ "(public packages included) through CodeArtifact.");
669
+ logInfo(` removed: ${repair.removed.trim()}`);
670
+ if (repair.backupPath)
671
+ logInfo(` backup: ${repair.backupPath}`);
672
+ }
673
+ }
674
+ if (!opts.ci && !opts.skipNpmrc) {
675
+ const result = ensureProjectNpmrc(grant.endpoint);
676
+ if (result.created) {
677
+ logSuccess(`Created ${result.path} with ${CA_NAMESPACE} registry scope`);
678
+ }
679
+ else if (result.updated) {
680
+ logSuccess(`Updated ${CA_NAMESPACE} registry in ${result.path}`);
681
+ }
682
+ else {
683
+ logInfo(`${result.path} already configured`);
684
+ }
685
+ }
686
+ logSuccess(`Ready — run pnpm install to fetch ${CA_NAMESPACE} packages`);
687
+ return;
688
+ }
689
+ }
690
+ let env;
691
+ if (opts.profile) {
692
+ // Jawad's flow, one command: live SSO session + profile-scoped token.
693
+ // Static creds in the environment would override the profile — drop them.
694
+ ensureSsoProfile(opts.profile);
695
+ env = { ...process.env, AWS_PROFILE: opts.profile };
696
+ for (const key of ["AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "AWS_SESSION_TOKEN"]) {
697
+ delete env[key];
698
+ }
699
+ }
700
+ else {
701
+ const awsCreds = resolveCredentials(context, roleArn);
702
+ env = Object.keys(awsCreds).length > 0
703
+ ? { ...process.env, ...awsCreds }
704
+ : undefined;
705
+ }
706
+ // Step 1: Run `aws codeartifact login` (sets token in ~/.npmrc)
707
+ logInfo("Authenticating with CodeArtifact...");
708
+ if (!codeartifactLogin(env)) {
709
+ logError("CodeArtifact login failed.\n\n" +
710
+ "You do NOT need an AWS account to install @mesh-tech packages. The supported path is:\n" +
711
+ ` mesh login ${context ?? "<context>"} # browser → Zitadel; then re-run this command\n\n` +
712
+ "This machine fell through to the AWS path, which means one of: the platform publishes no\n" +
713
+ "registry broker yet, your Mesh account is not signed in, or the broker was unreachable —\n" +
714
+ "the warning above says which.\n\n" +
715
+ "AWS SSO is only needed if you DEPLOY (mesh deploy):\n" +
716
+ " mesh registry login --profile mesh-dev # auto-runs `aws sso login`");
717
+ process.exit(1);
718
+ }
719
+ logSuccess("CodeArtifact token refreshed (valid for 12 hours)");
720
+ // Step 1b: Repair a hijacked ~/.npmrc. We always write the SCOPED form
721
+ // above (--namespace @mesh-tech), but a bare `aws codeartifact login` run
722
+ // at any point in the past leaves an unscoped `registry=` line that we
723
+ // never removed — so it survived every subsequent correct login.
724
+ //
725
+ // Laptops only — see shouldRepairUserNpmrc: in `--ci` the unscoped line is
726
+ // doing its job and a "repair" would break the runner's install.
727
+ if (shouldRepairUserNpmrc(opts)) {
728
+ const repair = repairUnscopedRegistry();
729
+ if (repair.removed) {
730
+ logWarn("Removed an unscoped CodeArtifact `registry=` from ~/.npmrc — it routed ALL npm traffic " +
731
+ "(public packages included) through CodeArtifact, so every install broke when the 12h token expired. " +
732
+ `${CA_NAMESPACE} stays scoped; public packages now go to npmjs.`);
733
+ logInfo(` removed: ${repair.removed.trim()}`);
734
+ if (repair.backupPath)
735
+ logInfo(` backup: ${repair.backupPath}`);
736
+ }
737
+ else if (repair.error) {
738
+ logWarn(`Could not repair ~/.npmrc (${repair.error}) — remove any unscoped \`registry=\` line by hand.`);
739
+ }
740
+ }
741
+ // Step 2: Get endpoint URL
742
+ const endpoint = getEndpoint(env);
743
+ if (!endpoint) {
744
+ logWarn("Could not retrieve registry endpoint — .npmrc scope not configured");
745
+ logInfo("You may need to manually add to .npmrc:");
746
+ logInfo(` ${CA_NAMESPACE}:registry=https://mesh-platform-<ACCOUNT>.d.codeartifact.${CA_REGION}.amazonaws.com/npm/${CA_REPOSITORY}/`);
747
+ return;
748
+ }
749
+ // Step 3: Ensure project .npmrc (unless --ci or --skip-npmrc)
750
+ if (!opts.ci && !opts.skipNpmrc) {
751
+ const result = ensureProjectNpmrc(endpoint);
752
+ if (result.created) {
753
+ logSuccess(`Created ${result.path} with ${CA_NAMESPACE} registry scope`);
754
+ }
755
+ else if (result.updated) {
756
+ logSuccess(`Updated ${CA_NAMESPACE} registry in ${result.path}`);
757
+ }
758
+ else {
759
+ logInfo(`${result.path} already configured`);
760
+ }
761
+ }
762
+ logSuccess(`Ready — run pnpm install to fetch ${CA_NAMESPACE} packages`);
763
+ }
252
764
  export function registerRegistryCommands(program) {
253
765
  const registry = program
254
766
  .command("registry")
@@ -260,77 +772,21 @@ export function registerRegistryCommands(program) {
260
772
  .option("--role <arn>", "IAM role ARN for registry access")
261
773
  .option("--ci", "CI mode — refresh token only, skip project .npmrc setup")
262
774
  .option("--skip-npmrc", "Skip project .npmrc setup")
775
+ .option("--profile <name>", "AWS SSO profile (e.g. mesh-dev) — auto-runs `aws sso login` when the session is stale")
776
+ .option("--no-broker", "Skip the Zitadel-gated registry broker and go straight to the AWS credential chain")
777
+ .option("--publish", "Assume the registry's publisher role for CodeArtifact publish access " +
778
+ "(opt-in privileged path — resolves publisherRoleArn from the registry's SSM export unless --role is given)")
263
779
  .action(async (context, opts) => {
264
- // Resolve AWS credentials
265
- const awsCreds = resolveCredentials(context, opts.role);
266
- const env = Object.keys(awsCreds).length > 0
267
- ? { ...process.env, ...awsCreds }
268
- : undefined;
269
- // Step 1: Run `aws codeartifact login` (sets token in ~/.npmrc)
270
- logInfo("Authenticating with CodeArtifact...");
271
- if (!codeartifactLogin(env)) {
272
- logError("CodeArtifact login failed.\n\n" +
273
- "Check that your AWS credentials have codeartifact:GetAuthorizationToken permission.\n" +
274
- "If using AWS SSO, run: aws sso login\n" +
275
- "If using Zitadel: mesh login <context>");
276
- process.exit(1);
277
- }
278
- logSuccess("CodeArtifact token refreshed (valid for 12 hours)");
279
- // Step 2: Get endpoint URL
280
- const endpoint = getEndpoint(env);
281
- if (!endpoint) {
282
- logWarn("Could not retrieve registry endpoint — .npmrc scope not configured");
283
- logInfo("You may need to manually add to .npmrc:");
284
- logInfo(` ${CA_NAMESPACE}:registry=https://mesh-platform-<ACCOUNT>.d.codeartifact.${CA_REGION}.amazonaws.com/npm/${CA_REPOSITORY}/`);
285
- process.exit(0);
286
- }
287
- // Step 3: Ensure project .npmrc (unless --ci or --skip-npmrc)
288
- if (!opts.ci && !opts.skipNpmrc) {
289
- const result = ensureProjectNpmrc(endpoint);
290
- if (result.created) {
291
- logSuccess(`Created ${result.path} with ${CA_NAMESPACE} registry scope`);
292
- }
293
- else if (result.updated) {
294
- logSuccess(`Updated ${CA_NAMESPACE} registry in ${result.path}`);
295
- }
296
- else {
297
- logInfo(`${result.path} already configured`);
298
- }
299
- }
300
- logSuccess(`Ready — run pnpm install to fetch ${CA_NAMESPACE} packages`);
780
+ await runRegistryLogin(context, opts);
301
781
  });
302
782
  registry
303
783
  .command("status")
304
784
  .description("Check current registry authentication status")
305
- .action(() => {
306
- const { valid, endpoint } = checkExistingToken();
307
- if (!valid) {
308
- logWarn("No valid CodeArtifact token found. Run: mesh registry login");
309
- process.exit(1);
310
- }
311
- logSuccess("CodeArtifact token found in ~/.npmrc");
312
- if (endpoint) {
313
- logInfo(`Endpoint: ${endpoint}`);
314
- }
315
- // Check project .npmrc
316
- const projectRoot = findProjectRoot();
317
- if (projectRoot) {
318
- const npmrcPath = path.join(projectRoot, ".npmrc");
319
- if (fs.existsSync(npmrcPath)) {
320
- const content = fs.readFileSync(npmrcPath, "utf-8");
321
- if (content.includes(`${CA_NAMESPACE}:registry=`)) {
322
- logSuccess(`Project .npmrc configured (${npmrcPath})`);
323
- }
324
- else {
325
- logWarn(`Project .npmrc exists but missing ${CA_NAMESPACE} scope (${npmrcPath})`);
326
- logInfo("Run: mesh registry login");
327
- }
328
- }
329
- else {
330
- logWarn(`No .npmrc in project root (${projectRoot})`);
331
- logInfo("Run: mesh registry login");
332
- }
333
- }
785
+ .action(async () => {
786
+ const code = await runRegistryStatus();
787
+ if (code !== 0)
788
+ process.exit(code);
334
789
  });
790
+ registerRegistryPublish(registry);
335
791
  }
336
792
  //# sourceMappingURL=registry.js.map