@mesh-tech/mesh-cli 0.1.0 → 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 +4 -0
  134. package/dist/src/commands/secrets/set.d.ts.map +1 -1
  135. package/dist/src/commands/secrets/set.js +243 -64
  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 +35 -21
  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
@@ -1 +1,7 @@
1
- {"version":3,"file":"mesh.js","sourceRoot":"","sources":["../../bin/mesh.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EAAE,uBAAuB,EAAE,MAAM,kCAAkC,CAAC;AAE3E,OAAO;KACJ,IAAI,CAAC,MAAM,CAAC;KACZ,WAAW,CAAC,wCAAwC,CAAC;KACrD,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,0BAA0B;AAC1B,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAC9B,wBAAwB,CAAC,OAAO,CAAC,CAAC;AAClC,kBAAkB,CAAC,OAAO,CAAC,CAAC;AAC5B,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAC/B,kBAAkB,CAAC,OAAO,CAAC,CAAC;AAC5B,wBAAwB,CAAC,OAAO,CAAC,CAAC;AAClC,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAC9B,sBAAsB,CAAC,OAAO,CAAC,CAAC;AAChC,uBAAuB,CAAC,OAAO,CAAC,CAAC;AAEjC,OAAO,CAAC,KAAK,EAAE,CAAC"}
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/utils/log.ts", "../../../../packages/agent-targets/src/schema.ts", "../../../../packages/agent-targets/src/resolve.ts", "../../../../packages/agent-targets/src/load.ts", "../../../../packages/agent-targets/src/links.ts", "../../../../packages/agent-targets/src/pull/types.ts", "../../../../packages/agent-targets/src/pull/delegates.ts", "../../../../packages/agent-targets/src/pull/pull.ts", "../../../../packages/agent-targets/src/pull/write.ts", "../../../../packages/agent-targets/src/pull/vcs-reader.ts", "../../../../packages/agent-targets/src/pull/index.ts", "../../../../packages/agent-targets/src/index.ts", "../../src/utils/auth-preflight.ts", "../../src/utils/aws-auth.ts", "../../src/utils/first-party-contexts.ts", "../../src/utils/errors.ts", "../../src/utils/context.ts", "../../src/utils/bastion.ts", "../../src/utils/credentials.ts", "../../src/utils/pulumi.ts", "../../src/utils/vpn.ts", "../../src/utils/index.ts", "../../src/utils/pid.ts", "../../src/utils/vpn-join.ts", "../../src/utils/pulumi-run.ts", "../../src/utils/kubeconfig.ts", "../../src/utils/temporal-auth.ts", "../../src/utils/reachability.ts", "../../src/utils/workflow-fingerprint.ts", "../../src/commands/dev-launch.ts", "../../src/commands/local/seed.ts", "../../src/commands/local/helpers.ts", "../../src/commands/local/stack.ts", "../../src/commands/local/mocks.ts", "../../../api-registry/src/hub-roles.ts", "../../../api-registry/src/index.ts", "../../src/commands/local/seed-zitadel.ts", "../../src/commands/local/auth-provision.ts", "../../src/commands/local/dev-local.ts", "../../src/commands/local/docker-runner.ts", "../../src/utils/stack-flag.ts", "../../src/commands/peer-addressing.ts", "../../src/commands/dev-doctor.ts", "../../src/utils/worktree-identity.ts", "../../src/commands/dev-token-server.ts", "../../src/commands/dev.ts", "../../src/utils/tailscale-targets.ts", "../../src/utils/socks-forward.ts", "../../src/utils/tunnel-ownership.ts", "../../src/utils/tailscale.ts", "../../src/commands/vpn/tunnel.ts", "../../src/commands/vpn/index.ts", "../../src/utils/registry-broker.ts", "../../src/commands/registry-publish.ts", "../../src/commands/registry.ts", "../../src/commands/login.ts", "../../src/commands/agent-api-client.ts", "../../src/commands/artifacts.ts", "../../src/commands/cluster.ts", "../../src/commands/vcs-enrich.ts", "../../src/commands/conversations.ts", "../../src/commands/skills.ts", "../../src/commands/create-app.ts", "../../src/commands/db/connect.ts", "../../src/commands/db/credentials.ts", "../../src/commands/db/env.ts", "../../src/commands/db/psql.ts", "../../src/commands/db/exec.ts", "../../src/commands/db/index.ts", "../../src/utils/deploy-preflight.ts", "../../src/commands/deploy.ts", "../../src/docs/schema.ts", "../../src/docs/discover.ts", "../../src/docs/assemble.ts", "../../src/docs/cli-reference.ts", "../../src/docs/portal.ts", "../../src/utils/build-info.ts", "../../src/docs/serve.ts", "../../src/docs/registry-docs.ts", "../../src/docs/start.ts", "../../src/commands/docs.ts", "../../src/commands/hub/index.ts", "../../src/commands/init.ts", "../../src/commands/install-shim.ts", "../../src/commands/local/hub-local.ts", "../../src/commands/local/index.ts", "../../src/commands/secrets/exec.ts", "../../src/commands/secrets/set.ts", "../../src/commands/secrets/migrate-config.ts", "../../src/commands/secrets/index.ts", "../../src/commands/stack.ts", "../../src/utils/recover-conversation.ts", "../../src/utils/temporal-codec.ts", "../../src/utils/capture-history.ts", "../../src/commands/temporal.ts", "../../src/commands/tenant.ts", "../../src/commands/tunnel/index.ts", "../../src/commands/vcs/common.ts", "../../src/commands/vcs/clone.ts", "../../src/commands/vcs/get.ts", "../../src/commands/vcs/drafts.ts", "../../src/commands/vcs/propose.ts", "../../src/commands/vcs/review.ts", "../../src/commands/vcs/index.ts", "../../../workflow-model/src/workflow-ir.ts", "../../../workflow-model/src/workflow-ir-validate.ts", "../../../workflow-model/src/apply-preview-patch.ts", "../../../workflow-model/src/process-artifact.ts", "../../../workflow-model/src/process-lint.ts", "../../../workflow-model/src/index.ts", "../../src/commands/workflow.ts", "../../src/program.ts", "../../bin/mesh.ts"],
4
+ "sourcesContent": ["/**\n * Logging utilities with colored output.\n *\n * Non-TTY streams (CI, agent runs, piped output) get an [HH:MM:SS] prefix on\n * every line so long quiet stretches are attributable after the fact\n * (MESH-2479); interactive terminals stay clean. Override with\n * MESH_LOG_TIMESTAMPS=1 (force on) / =0 (force off).\n */\n\nimport chalk from \"chalk\";\n\n/**\n * Pure prefix decision, exported for tests: timestamps when the env flag says\n * so, else whenever stderr is not a TTY.\n */\nexport function logPrefix(opts: {\n isTTY: boolean;\n envFlag: string | undefined;\n now: Date;\n}): string {\n const enabled = opts.envFlag === \"1\" || (opts.envFlag !== \"0\" && !opts.isTTY);\n return enabled ? `[${opts.now.toISOString().slice(11, 19)}] ` : \"\";\n}\n\nfunction prefix(): string {\n return chalk.dim(\n logPrefix({\n isTTY: !!process.stderr.isTTY,\n envFlag: process.env.MESH_LOG_TIMESTAMPS,\n now: new Date(),\n }),\n );\n}\n\nexport function logInfo(message: string): void {\n console.error(prefix() + chalk.blue(\"\u2139\"), message);\n}\n\nexport function logSuccess(message: string): void {\n console.error(prefix() + chalk.green(\"\u2713\"), message);\n}\n\nexport function logWarn(message: string): void {\n console.error(prefix() + chalk.yellow(\"\u26A0\"), message);\n}\n\nexport function logError(message: string): void {\n console.error(prefix() + chalk.red(\"\u2717\"), message);\n}\n\n/** Render elapsed milliseconds compactly: \"45s\", \"2m 30s\", \"1h 5m\". */\nexport function formatElapsed(ms: number): string {\n const totalSec = Math.max(0, Math.round(ms / 1000));\n const h = Math.floor(totalSec / 3600);\n const m = Math.floor((totalSec % 3600) / 60);\n const s = totalSec % 60;\n if (h > 0) return `${h}h ${m}m`;\n if (m > 0) return `${m}m ${s}s`;\n return `${s}s`;\n}\n\n/**\n * Periodic \"still working\" line during a long silent operation (registry\n * fetches, image builds) so a non-TTY first run never sits at 0 bytes of\n * output for minutes (MESH-2479). `touch()` marks recent real output, which\n * suppresses the next beat \u2014 the heartbeat only fills silence.\n */\nexport function startHeartbeat(\n label: string,\n intervalMs = 15_000,\n): { stop: () => void; touch: () => void } {\n const startedAt = Date.now();\n let lastOutputAt = startedAt;\n const timer = setInterval(() => {\n if (Date.now() - lastOutputAt < intervalMs) return;\n logInfo(`\u2026 still working: ${label} (${formatElapsed(Date.now() - startedAt)} elapsed)`);\n }, intervalMs);\n timer.unref?.();\n return {\n stop: () => clearInterval(timer),\n touch: () => {\n lastOutputAt = Date.now();\n },\n };\n}\n", "import { z } from \"zod\";\n\nexport const TargetEntrySchema = z.object({\n apiBaseUrl: z.string().url(),\n hubBaseUrl: z.string().url().optional(),\n conversationPathPrefix: z.string().optional(),\n approvalPathPrefix: z.string().optional(),\n tenant: z.string().min(1),\n env: z.string().min(1),\n loginContext: z.string().optional(),\n token: z.string().optional(),\n});\nexport type TargetEntry = z.infer<typeof TargetEntrySchema>;\n\nexport const RegistrySchema = z\n .object({ defaultTarget: z.string().min(1), targets: z.record(z.string(), TargetEntrySchema) })\n .refine((r) => r.defaultTarget in r.targets, { message: \"defaultTarget must be one of the configured targets\" });\nexport type Registry = z.infer<typeof RegistrySchema>;\n", "import type { TargetEntry } from \"./schema.js\";\n\nexport const DEFAULT_CONVERSATION_PATH_PREFIX = \"/assistant/c\";\nexport const DEFAULT_APPROVAL_PATH_PREFIX = \"/approvals\";\n\nexport function stripSlash(url: string): string {\n // Linear trailing-slash trim \u2014 avoids the polynomial backtracking CodeQL\n // flags on `/\\/+$/` for strings with many repeated slashes.\n let end = url.length;\n while (end > 0 && url.charCodeAt(end - 1) === 47 /* \"/\" */) end--;\n return url.slice(0, end);\n}\nexport function normalizePathPrefix(prefix: string): string {\n return stripSlash(prefix.startsWith(\"/\") ? prefix : `/${prefix}`);\n}\n\nexport interface ResolvedTarget {\n apiBaseUrl: string;\n hubBaseUrl: string;\n conversationPathPrefix: string;\n approvalPathPrefix: string;\n token?: string;\n loginContext?: string;\n tenant: string;\n environment: string;\n}\n\nexport function resolveEntry(entry: TargetEntry): ResolvedTarget {\n const apiBaseUrl = stripSlash(entry.apiBaseUrl);\n return {\n apiBaseUrl,\n hubBaseUrl: stripSlash(entry.hubBaseUrl || apiBaseUrl),\n conversationPathPrefix: normalizePathPrefix(entry.conversationPathPrefix || DEFAULT_CONVERSATION_PATH_PREFIX),\n approvalPathPrefix: normalizePathPrefix(entry.approvalPathPrefix || DEFAULT_APPROVAL_PATH_PREFIX),\n token: entry.token || undefined,\n loginContext: entry.loginContext || undefined,\n tenant: entry.tenant,\n environment: entry.env,\n };\n}\n", "import { readFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport path from \"node:path\";\nimport { RegistrySchema } from \"./schema.js\";\nimport { resolveEntry, type ResolvedTarget } from \"./resolve.js\";\n\nexport const DEFAULT_REGISTRY_PATH = path.join(homedir(), \".config\", \"mesh\", \"agent-targets.json\");\n\nexport type LoadTargetsResult =\n | { status: \"loaded\"; targets: Record<string, ResolvedTarget>; defaultTarget: string; path: string }\n | { status: \"absent\"; path: string }\n | { status: \"invalid\"; path: string; message: string };\n\n/**\n * Read + validate the agent-targets registry file. Pure: never throws, never\n * writes to stdout/stderr \u2014 returns a discriminated result the caller\n * interprets (the MCP \u2192 env-fallback + stderr warn; the CLI \u2192 actionable error).\n */\nexport function loadTargetsFile(env: NodeJS.ProcessEnv = process.env): LoadTargetsResult {\n const file = env.MESH_AGENT_TARGETS || DEFAULT_REGISTRY_PATH;\n let raw: string;\n try {\n raw = readFileSync(file, \"utf8\");\n } catch {\n return { status: \"absent\", path: file };\n }\n try {\n const parsed = RegistrySchema.parse(JSON.parse(raw));\n const targets: Record<string, ResolvedTarget> = {};\n for (const [name, entry] of Object.entries(parsed.targets)) targets[name] = resolveEntry(entry);\n return { status: \"loaded\", targets, defaultTarget: parsed.defaultTarget, path: file };\n } catch (err) {\n return { status: \"invalid\", path: file, message: err instanceof Error ? err.message : String(err) };\n }\n}\n", "import type { ResolvedTarget } from \"./resolve.js\";\nexport function conversationUrl(t: ResolvedTarget, conversationId: string): string {\n return `${t.hubBaseUrl}${t.conversationPathPrefix}/${conversationId}`;\n}\nexport function approvalUrl(t: ResolvedTarget, dispatchId: string): string {\n return `${t.hubBaseUrl}${t.approvalPathPrefix}/${dispatchId}`;\n}\n", "/**\n * An artifact the conversation referenced that the bundle did NOT materialize\n * \u2014 a repo drive-ref (any tenant's knowledge-base / context repo the agent\n * read) or any other artifact kind. Surfaced so the consuming agent/user can\n * decide whether to pull it; referenced repos are never auto-cloned regardless\n * of name (only a design's OWN saveLocation repo is materialized). `pullHint`\n * is a ready-to-run suggestion.\n */\nexport interface Reference {\n resource: string; // the artifact's resource kind (\"vcs\", \"doc\", \u2026)\n id?: string; // artifact id (for non-vcs kinds)\n title?: string;\n repo?: string; // vcs drive-ref repo\n ref?: string; // vcs drive-ref branch/commit\n path?: string; // vcs drive-ref path (may be \"\" = repo root)\n pullHint: string;\n}\n\n/** A file read verbatim from a design's vcs folder (path is relative to the folder). */\nexport interface VcsFolderFile {\n path: string;\n contents: string;\n}\n\n/** The verbatim contents of a design's own vcs folder at a resolved ref. */\nexport interface VcsFolder {\n ref: string; // the git ref the folder was read from (e.g. \"origin/drafts/d-\u2026\")\n files: VcsFolderFile[];\n}\n\nexport interface PulledDesign {\n wf: string; // \"workflow-builder:<id>\"\n slug: string; // filename-safe folder name\n title?: string;\n ir: unknown; // LIVE design IR from /workflow-design (authoritative)\n degraded: boolean;\n saveLocation: { repo: string; folder: string } | null;\n saveStatus: string;\n savedAt: number | null;\n // Phase 2 (vcs enrichment): the design's own folder, pulled verbatim.\n folderRef?: string; // provenance: which ref the folder came from\n // Drift-adjusted folder files: an identical saved design-ir.json is dropped\n // (the live IR is authoritative); a differing one is kept as design-ir.saved.json.\n folderFiles?: VcsFolderFile[];\n}\n\nexport interface PulledUi {\n wf: string; // \"ui-builder:<id>\"\n slug: string;\n title?: string;\n spec: unknown;\n}\n\nexport interface PulledSubagent {\n childId: string;\n parentId: string;\n depth: number; // 0 = direct delegate of the root conversation\n messages: unknown[];\n}\n\nexport interface PullWarning {\n stage: \"transcript\" | \"artifacts\" | \"design\" | \"ui\" | \"subagent\" | \"vcs\";\n ref?: string; // wf id / childId / repo \u2014 whatever identifies the failed unit\n detail: string;\n}\n\nexport interface ConversationBundle {\n conversationId: string;\n title?: string;\n transcript: { messages: unknown[] } | null;\n artifacts: unknown[]; // raw artifact index entries\n designs: PulledDesign[];\n uiSpecs: PulledUi[];\n subagents: PulledSubagent[];\n references: Reference[];\n warnings: PullWarning[];\n}\n", "function escapeRegExp(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\n/**\n * Find delegate/subagent child ids that are DIRECT children of `parentId`,\n * scanning the serialized messages. A direct child is `${parentId}/delegate-<token>`;\n * grandchildren are discovered by re-scanning a child's own messages with the\n * child as `parentId` (see pull.ts recursion). Robust to message-shape drift\n * because it matches the id string wherever it appears.\n */\nexport function extractDelegateIds(messages: unknown[], parentId: string): string[] {\n const hay = JSON.stringify(messages ?? []);\n const re = new RegExp(escapeRegExp(parentId) + \"\\\\/delegate-[A-Za-z0-9_-]+\", \"g\");\n return [...new Set(hay.match(re) ?? [])];\n}\n", "import { extractDelegateIds } from \"./delegates.js\";\nimport type {\n ConversationBundle,\n PulledDesign,\n PulledUi,\n PulledSubagent,\n PullWarning,\n Reference,\n VcsFolder,\n} from \"./types.js\";\n\nexport type ApiFetcher = (apiPath: string) => Promise<Response>;\n\nexport interface PullDeps {\n fetchApi: ApiFetcher;\n /**\n * Phase 2: read a design's own vcs folder verbatim (whole folder, so ad-hoc\n * docs beyond the IR come too). Given `saveLocation.{repo,folder}`, returns\n * the folder's files + the ref they were read from.\n */\n enrichVcs?: (repo: string, folder: string) => Promise<VcsFolder>;\n}\n\n/** Recursively sort object keys so serialization is key-order independent. */\nfunction sortKeys(v: unknown): unknown {\n if (Array.isArray(v)) return v.map(sortKeys);\n if (v && typeof v === \"object\") {\n const src = v as Record<string, unknown>;\n return Object.keys(src)\n .sort()\n .reduce<Record<string, unknown>>((acc, k) => {\n acc[k] = sortKeys(src[k]);\n return acc;\n }, {});\n }\n return v;\n}\n\n/** Canonical JSON for drift comparison \u2014 key-order independent (a re-serialized\n * saved IR with different key ordering must NOT read as drift). */\nfunction canonicalJson(v: unknown): string {\n return JSON.stringify(sortKeys(v));\n}\n\nexport interface PullOptions {\n recursive?: boolean; // default true\n maxDepth?: number; // default 8, cycle-guarded regardless\n /** Target name woven into `references[].pullHint` (e.g. \"--target fub\"); optional. */\n hintTarget?: string;\n}\n\nconst DEFAULT_MAX_DEPTH = 8;\n\n/** A ready-to-run suggestion for pulling a referenced artifact the bundle didn't materialize. */\nfunction pullHintFor(ref: { resource: string; repo?: string; path?: string; id?: string }, hintTarget?: string): string {\n const t = hintTarget ? ` --target ${hintTarget}` : \" --target <name>\";\n if (ref.resource === \"vcs\" && ref.repo) {\n return ref.path\n ? `mesh vcs get ${ref.repo} ${ref.path}${t} # one path, not the whole repo`\n : `mesh vcs get ${ref.repo} <path>${t} # browse conversation.md for the doc paths that matter`;\n }\n if (ref.id) return `mesh artifacts get <conversationId>:${ref.id}${t}`;\n return \"see conversation.md for context\";\n}\n\nfunction describeErr(e: unknown): string {\n return e instanceof Error ? e.message : String(e);\n}\n\nfunction slugify(s: string): string {\n // `[^a-z0-9]+` already collapses runs to a single \"-\", so single-char anchored\n // trims suffice \u2014 and avoid the polynomial `-+$` backtracking CodeQL flags.\n return s.toLowerCase().replace(/[^a-z0-9]+/g, \"-\").replace(/^-|-$/g, \"\").slice(0, 80);\n}\n\n/**\n * Neutralize a server-supplied folder name before it becomes an on-disk bundle\n * directory: collapse path separators and drop `..` so a design's `slug` can\n * never escape the output dir (defense-in-depth \u2014 the value is server-controlled\n * today). Keeps the readable name otherwise.\n */\nfunction safeSlug(s: string): string {\n return (\n s\n .replace(/[/\\\\]+/g, \"-\")\n .replace(/\\.\\.+/g, \"\")\n .replace(/^[.\\-]+/, \"\")\n .slice(0, 120) || \"design\"\n );\n}\n\n/** Prefer the design's saved folder (sanitized); else slugify the title; else the wf id tail. */\nfunction slugForDesign(saveFolder: string | undefined, title: string | undefined, wf: string): string {\n if (saveFolder) return safeSlug(saveFolder);\n if (title && slugify(title)) return slugify(title);\n return slugify(wf.split(\":\").pop() ?? wf) || \"design\";\n}\n\ninterface ArtifactEntry {\n id?: string;\n resource?: string;\n title?: string;\n content?: { attachment?: { ref?: Record<string, unknown> } };\n}\n\nfunction refOf(a: ArtifactEntry): Record<string, unknown> | undefined {\n return a.content?.attachment?.ref;\n}\n\nexport async function pullConversation(\n deps: PullDeps,\n conversationId: string,\n opts: PullOptions = {},\n): Promise<ConversationBundle> {\n const recursive = opts.recursive ?? true;\n const maxDepth = opts.maxDepth ?? DEFAULT_MAX_DEPTH;\n const warnings: PullWarning[] = [];\n\n const getJson = async <T>(apiPath: string): Promise<T> => {\n const res = await deps.fetchApi(apiPath);\n if (!res.ok) throw new Error(`${res.status} ${apiPath}`);\n return (await res.json()) as T;\n };\n\n // 1. transcript\n let transcript: { messages: unknown[] } | null = null;\n let title: string | undefined;\n // Map of delegate tool-call id \u2192 spawned child workflow id. This \u2014 NOT the\n // transcript text \u2014 is the authoritative source of a conversation's direct\n // delegates (the decoded transcript is role+content only). Values look like\n // `${conversationId}/delegate-N`.\n let delegateChildIds: Record<string, string> = {};\n try {\n const body = await getJson<{ messages?: unknown[]; title?: string; delegateChildIds?: Record<string, string> }>(\n `/v1/conversations/${encodeURIComponent(conversationId)}`,\n );\n transcript = { messages: body.messages ?? [] };\n title = body.title;\n delegateChildIds = body.delegateChildIds ?? {};\n } catch (e) {\n warnings.push({ stage: \"transcript\", ref: conversationId, detail: describeErr(e) });\n transcript = { messages: [] };\n }\n\n // 2. artifacts\n let artifacts: ArtifactEntry[] = [];\n try {\n const body = await getJson<{ artifacts?: ArtifactEntry[] }>(\n `/v1/conversations/${encodeURIComponent(conversationId)}/artifacts`,\n );\n artifacts = body.artifacts ?? [];\n } catch (e) {\n warnings.push({ stage: \"artifacts\", ref: conversationId, detail: describeErr(e) });\n }\n\n const designs: PulledDesign[] = [];\n const uiSpecs: PulledUi[] = [];\n const references: Reference[] = [];\n\n for (const a of artifacts) {\n const ref = refOf(a);\n if (a.resource === \"workflow\" && typeof ref?.wf === \"string\") {\n const wf = ref.wf;\n try {\n const d = await getJson<{\n wf: string;\n ir: unknown;\n degraded: boolean;\n saveLocation: { repo: string; folder: string } | null;\n saveStatus: string;\n savedAt: number | null;\n }>(`/v1/conversations/${encodeURIComponent(conversationId)}/workflow-design?wf=${encodeURIComponent(wf)}`);\n const design: PulledDesign = {\n wf,\n slug: slugForDesign(d.saveLocation?.folder, a.title, wf),\n title: a.title,\n ir: d.ir,\n degraded: d.degraded,\n saveLocation: d.saveLocation,\n saveStatus: d.saveStatus,\n savedAt: d.savedAt,\n };\n // Phase 2 enrichment (no-op until enrichVcs is provided): pull the\n // design's own folder verbatim, keeping the LIVE IR authoritative.\n if (deps.enrichVcs && design.saveLocation) {\n const loc = `${design.saveLocation.repo}/${design.saveLocation.folder}`;\n try {\n const folder = await deps.enrichVcs(design.saveLocation.repo, design.saveLocation.folder);\n design.folderRef = folder.ref;\n const liveIr = canonicalJson(design.ir);\n const kept: typeof folder.files = [];\n for (const f of folder.files) {\n if (f.path === \"design-ir.json\") {\n let savedMatches = false;\n try {\n savedMatches = canonicalJson(JSON.parse(f.contents)) === liveIr;\n } catch {\n savedMatches = false; // unparseable saved IR \u2192 treat as drift\n }\n if (!savedMatches) {\n kept.push({ path: \"design-ir.saved.json\", contents: f.contents });\n warnings.push({\n stage: \"vcs\",\n ref: loc,\n detail: \"saved design-ir.json differs from the live IR \u2014 kept as design-ir.saved.json\",\n });\n }\n // identical \u2192 drop; the live IR is written as design-ir.json\n } else {\n kept.push(f);\n }\n }\n design.folderFiles = kept;\n } catch (e) {\n warnings.push({ stage: \"vcs\", ref: loc, detail: describeErr(e) });\n }\n }\n designs.push(design);\n } catch (e) {\n warnings.push({ stage: \"design\", ref: wf, detail: describeErr(e) });\n }\n } else if (a.resource === \"ui\" && typeof ref?.wf === \"string\") {\n const wf = ref.wf;\n try {\n const u = await getJson<{ wf: string; spec: unknown }>(\n `/v1/conversations/${encodeURIComponent(conversationId)}/ui-design?wf=${encodeURIComponent(wf)}`,\n );\n uiSpecs.push({ wf, slug: slugForDesign(undefined, a.title, wf), title: a.title, spec: u.spec });\n } catch (e) {\n warnings.push({ stage: \"ui\", ref: wf, detail: describeErr(e) });\n }\n } else if (a.resource === \"vcs\" && ref && typeof ref.repo === \"string\") {\n // A referenced repo (any tenant's KB/context repo) \u2014 cataloged, NEVER\n // auto-cloned; the consuming agent/user pulls specific docs on demand.\n const entry = {\n resource: \"vcs\",\n id: a.id,\n title: a.title,\n repo: ref.repo,\n ref: ref.ref as string | undefined,\n path: ref.path as string | undefined,\n };\n references.push({ ...entry, pullHint: pullHintFor(entry, opts.hintTarget) });\n } else if (a.resource && a.resource !== \"workflow\" && a.resource !== \"ui\") {\n // Any other artifact kind we don't materialize \u2014 surfaced so the agent\n // can decide whether to fetch it.\n const entry = { resource: a.resource, id: a.id, title: a.title };\n references.push({ ...entry, pullHint: pullHintFor(entry, opts.hintTarget) });\n }\n }\n\n // subagents (recursive, cycle-guarded). Direct children come from the\n // authoritative `delegateChildIds` map; the transcript text is also scanned\n // (belt-and-suspenders + the only signal for deeper grandchildren, since the\n // child-messages route does not expose a child's own delegate map). Every\n // child is fetched under the ROOT conversation id \u2014 the route guard accepts\n // any `${root}/delegate-\u2026` id at any nesting depth.\n const parentOf = (childId: string): string => childId.replace(/\\/delegate-[^/]*$/, \"\");\n const subagents: PulledSubagent[] = [];\n const seen = new Set<string>();\n const queue: Array<{ childId: string; depth: number }> = [];\n const enqueue = (childId: string, depth: number): void => {\n if (!seen.has(childId) && !queue.some((q) => q.childId === childId)) queue.push({ childId, depth });\n };\n for (const childId of Object.values(delegateChildIds)) if (typeof childId === \"string\") enqueue(childId, 0);\n for (const childId of extractDelegateIds(transcript.messages, conversationId)) enqueue(childId, 0);\n\n while (queue.length > 0) {\n const { childId, depth } = queue.shift()!;\n if (seen.has(childId)) continue;\n seen.add(childId);\n let childMessages: unknown[] = [];\n try {\n const body = await getJson<{ messages?: unknown[] }>(\n `/v1/conversations/${encodeURIComponent(conversationId)}/children/${encodeURIComponent(childId)}/messages`,\n );\n childMessages = body.messages ?? [];\n subagents.push({ childId, parentId: parentOf(childId), depth, messages: childMessages });\n } catch (e) {\n warnings.push({ stage: \"subagent\", ref: childId, detail: describeErr(e) });\n continue;\n }\n if (recursive && depth + 1 <= maxDepth) {\n for (const grandchild of extractDelegateIds(childMessages, childId)) enqueue(grandchild, depth + 1);\n }\n }\n\n return { conversationId, title, transcript, artifacts, designs, uiSpecs, subagents, references, warnings };\n}\n\nexport { slugForDesign };\n", "import { mkdir, writeFile } from \"node:fs/promises\";\nimport { join, dirname } from \"node:path\";\nimport type { ConversationBundle } from \"./types.js\";\n\nconst enc = (v: unknown): string => JSON.stringify(v, null, 2) + \"\\n\";\n\nasync function put(dir: string, rel: string, contents: string, written: string[]): Promise<void> {\n const abs = join(dir, rel);\n await mkdir(dirname(abs), { recursive: true });\n await writeFile(abs, contents);\n written.push(rel);\n}\n\n// Keep tool payloads from bloating the transcript; matches the 400-char spirit\n// of the SSE `summarize()` but leaves room for a readable snippet.\nconst CLIP = 4000;\nconst clip = (s: string): string => (s.length > CLIP ? `${s.slice(0, CLIP)}\\n\u2026 (${s.length} chars total, clipped)` : s);\n\nconst fence = (lang: string, body: string): string => `\\`\\`\\`${lang}\\n${clip(body)}\\n\\`\\`\\``;\n\n/** Render the `output` of an AI SDK tool-result part (LanguageModelV2ToolResultOutput). */\nfunction renderToolOutput(output: unknown): string {\n const o = output as { type?: string; value?: unknown };\n if (o?.type === \"text\" || o?.type === \"error-text\") return clip(String(o.value ?? \"\"));\n if (o?.type === \"json\" || o?.type === \"error-json\") return fence(\"json\", JSON.stringify(o.value, null, 2));\n if (o?.type === \"content\" && Array.isArray(o.value)) {\n return o.value\n .map((part) => {\n const p = part as { type?: string; text?: string; mediaType?: string };\n if (p?.type === \"text\") return p.text ?? \"\";\n if (p?.type === \"media\") return `_[media: ${p.mediaType ?? \"unknown\"}]_`;\n return fence(\"json\", JSON.stringify(part, null, 2));\n })\n .join(\"\\n\\n\");\n }\n return fence(\"json\", JSON.stringify(output, null, 2));\n}\n\n/** Render one content part of an AI SDK ModelMessage (text/reasoning/tool-call/tool-result/file). */\nfunction renderPart(part: unknown): string {\n const p = part as {\n type?: string;\n text?: string;\n toolName?: string;\n input?: unknown;\n output?: unknown;\n mediaType?: string;\n };\n switch (p?.type) {\n case \"text\":\n return p.text ?? \"\";\n case \"reasoning\":\n return p.text ? `> _(reasoning)_ ${p.text.replace(/\\n/g, \"\\n> \")}` : \"\";\n case \"tool-call\":\n return `**\u2192 \\`${p.toolName ?? \"tool\"}\\`**\\n\\n${fence(\"json\", JSON.stringify(p.input ?? {}, null, 2))}`;\n case \"tool-result\":\n return `**\u2190 \\`${p.toolName ?? \"tool\"}\\`**\\n\\n${renderToolOutput(p.output)}`;\n case \"file\":\n case \"image\":\n return `_[${p.type}: ${p.mediaType ?? \"attachment\"}]_`;\n default:\n // Never fall through to Array/Object stringification (the \"[object Object]\" bug).\n return fence(\"json\", JSON.stringify(part, null, 2));\n }\n}\n\n/**\n * Render an AI SDK ModelMessage's `content` \u2014 either a plain string or an array\n * of content parts (text/reasoning/tool-call/tool-result/file) \u2014 to readable\n * markdown. Exported so CLI/other transcript renderers share one implementation\n * and never fall back to `String(array)` \u2192 \"[object Object],\u2026\".\n */\nexport function renderMessageContent(content: unknown): string {\n if (typeof content === \"string\") return content;\n if (Array.isArray(content)) return content.map(renderPart).filter(Boolean).join(\"\\n\\n\");\n if (content == null) return \"\";\n return fence(\"json\", JSON.stringify(content, null, 2));\n}\n\n/** Render a minimal markdown transcript from message objects. */\nfunction transcriptMd(messages: unknown[]): string {\n return messages\n .map((m) => {\n const r = m as { role?: string; content?: unknown };\n return `### ${r.role ?? \"?\"}\\n\\n${renderMessageContent(r.content)}`;\n })\n .join(\"\\n\\n\");\n}\n\nconst slugChildId = (id: string): string => id.replace(/\\//g, \"__\");\n\n/** Materialize a ConversationBundle into the documented on-disk layout. Returns written relative paths. */\nexport async function writeBundle(bundle: ConversationBundle, dir: string): Promise<string[]> {\n const written: string[] = [];\n\n await put(\n dir,\n \"index.json\",\n enc({\n conversationId: bundle.conversationId,\n title: bundle.title,\n artifacts: bundle.artifacts,\n designs: bundle.designs.map((d) => ({\n wf: d.wf,\n slug: d.slug,\n title: d.title,\n degraded: d.degraded,\n saveLocation: d.saveLocation,\n saveStatus: d.saveStatus,\n savedAt: d.savedAt,\n folderRef: d.folderRef,\n folderFiles: (d.folderFiles ?? []).map((f) => f.path),\n hasManifest: (d.folderFiles ?? []).some((f) => f.path === \"manifest.json\"),\n })),\n uiSpecs: bundle.uiSpecs.map((u) => ({ wf: u.wf, slug: u.slug, title: u.title })),\n subagents: bundle.subagents.map((s) => ({ childId: s.childId, parentId: s.parentId, depth: s.depth })),\n references: bundle.references,\n warnings: bundle.warnings,\n }),\n written,\n );\n\n await put(\n dir,\n \"conversation.md\",\n `# ${bundle.title ?? bundle.conversationId}\\n\\n${transcriptMd(bundle.transcript?.messages ?? [])}\\n`,\n written,\n );\n\n for (const d of bundle.designs) {\n // Live IR is authoritative.\n await put(dir, `designs/${d.slug}/design-ir.json`, enc(d.ir), written);\n // The design's own folder, verbatim (docs, manifest, README, subfolders,\n // and design-ir.saved.json when it drifted from live).\n for (const f of d.folderFiles ?? []) {\n await put(dir, `designs/${d.slug}/${f.path}`, f.contents, written);\n }\n }\n for (const u of bundle.uiSpecs) await put(dir, `ui/${u.slug}.json`, enc(u.spec), written);\n for (const s of bundle.subagents) {\n await put(dir, `subagents/${slugChildId(s.childId)}.md`, `# ${s.childId}\\n\\n${transcriptMd(s.messages)}\\n`, written);\n }\n return written;\n}\n", "/**\n * Reads a design's OWN vcs folder verbatim for `pullConversation`'s enrichVcs\n * dep. The vcs service is git smart-HTTP only, so this shallow-clones the\n * design's repo (never a referenced repo), resolves the ref that carries the\n * folder (a saved design lives on a `drafts/*` branch; `main` is the verified\n * base and is often empty), and reads every file under it. Shared by the CLI\n * (`mesh conversations pull`) and the MCP (`agent_pull_conversation`) so the\n * folder logic lives in exactly one place.\n */\nimport { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport { mkdtemp, rm } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { VcsFolder, VcsFolderFile } from \"./types.js\";\n\nconst execFileAsync = promisify(execFile);\n\n/** `https://demo-agent.fub-dev.dev\u2026` \u2192 `https://vcs.fub-dev.dev\u2026` (drop the first host label, prefix `vcs`). */\nexport function deriveVcsBaseUrl(apiBaseUrl: string): string | null {\n try {\n const u = new URL(apiBaseUrl);\n const labels = u.hostname.split(\".\");\n if (labels.length < 2) return null;\n return `https://vcs.${labels.slice(1).join(\".\")}`;\n } catch {\n return null;\n }\n}\n\nasync function refHasFolder(cwd: string, ref: string, folder: string): Promise<boolean> {\n try {\n const { stdout } = await execFileAsync(\"git\", [\"-C\", cwd, \"ls-tree\", \"--name-only\", ref, \"--\", folder]);\n return stdout.trim().length > 0;\n } catch {\n return false;\n }\n}\n\n/** Prefer `origin/main`; else the newest `origin/drafts/*` ref that carries the folder. */\nasync function resolveFolderRef(cwd: string, folder: string): Promise<string | null> {\n if (await refHasFolder(cwd, \"origin/main\", folder)) return \"origin/main\";\n const { stdout } = await execFileAsync(\"git\", [\n \"-C\", cwd, \"for-each-ref\", \"--sort=-committerdate\", \"--format=%(refname)\", \"refs/remotes/origin/drafts\",\n ]);\n for (const ref of stdout.split(\"\\n\").map((s) => s.trim()).filter(Boolean)) {\n if (await refHasFolder(cwd, ref, folder)) return ref;\n }\n return null;\n}\n\nasync function readFolderAtRef(cwd: string, ref: string, folder: string): Promise<VcsFolderFile[]> {\n const { stdout } = await execFileAsync(\"git\", [\"-C\", cwd, \"ls-tree\", \"-r\", \"--name-only\", ref, \"--\", folder]);\n const paths = stdout.split(\"\\n\").map((s) => s.trim()).filter(Boolean);\n const files: VcsFolderFile[] = [];\n for (const p of paths) {\n const { stdout: contents } = await execFileAsync(\"git\", [\"-C\", cwd, \"show\", `${ref}:${p}`], {\n maxBuffer: 32 * 1024 * 1024,\n });\n const rel = p.startsWith(`${folder}/`) ? p.slice(folder.length + 1) : p;\n files.push({ path: rel, contents });\n }\n return files;\n}\n\nexport interface VcsFolderReader {\n /** Read a design's own folder verbatim (the `pullConversation` enrichVcs dep). */\n enrichVcs: (repo: string, folder: string) => Promise<VcsFolder>;\n /**\n * Read a SPECIFIC path (a file or a subtree) from a repo at its resolved ref\n * \u2014 the `mesh vcs get` / `agent_get_repo_doc` discretionary doc pull. Never\n * materializes the whole repo; only the requested path.\n */\n readPath: (repo: string, path: string) => Promise<VcsFolder>;\n /** Remove the temp clones this reader created. */\n cleanup: () => Promise<void>;\n}\n\n/**\n * A folder reader bound to a vcs base URL + bearer token. Shallow-clones each\n * repo once (memoized) and reads the requested folder at its resolved ref.\n */\n/** Repo names are simple slugs. Reject anything that could act as a git flag or\n * break out of the clone URL before it reaches `git` (severs the second-order\n * command-injection data flow \u2014 the values come from config/artifact refs). */\nconst SAFE_REPO_RE = /^[A-Za-z0-9._-]+$/;\n\nexport function createVcsFolderReader(opts: { vcsBaseUrl: string; token: string }): VcsFolderReader {\n const { token } = opts;\n // Validate the base URL up front \u2014 `new URL` throws on malformed input, and we\n // clone only from its normalized https/http origin (never a raw string).\n const base = new URL(opts.vcsBaseUrl);\n if (base.protocol !== \"https:\" && base.protocol !== \"http:\") {\n throw new Error(`unsafe vcs base URL protocol: ${opts.vcsBaseUrl}`);\n }\n const clones = new Map<string, Promise<string>>();\n\n const cloneRepo = (repo: string): Promise<string> => {\n if (!SAFE_REPO_RE.test(repo)) throw new Error(`unsafe repo name: ${JSON.stringify(repo)}`);\n let p = clones.get(repo);\n if (!p) {\n p = (async () => {\n const dir = await mkdtemp(join(tmpdir(), \"mesh-vcs-\"));\n await execFileAsync(\"git\", [\n \"clone\", \"--filter=blob:none\", \"--no-checkout\",\n \"-c\", `http.extraHeader=Authorization: Bearer ${token}`,\n `${base.origin}/git/${repo}`, dir,\n ]);\n return dir;\n })();\n clones.set(repo, p);\n }\n return p;\n };\n\n const readPath = async (repo: string, path: string): Promise<VcsFolder> => {\n const dir = await cloneRepo(repo);\n const ref = await resolveFolderRef(dir, path);\n if (!ref) throw new Error(`path \"${path}\" not found on any ref of ${repo}`);\n const files = await readFolderAtRef(dir, ref, path);\n return { ref, files };\n };\n\n const cleanup = async (): Promise<void> => {\n await Promise.all(\n [...clones.values()].map(async (p) => {\n try {\n await rm(await p, { recursive: true, force: true });\n } catch {\n /* best-effort */\n }\n }),\n );\n };\n\n return { enrichVcs: readPath, readPath, cleanup };\n}\n", "export * from \"./types.js\";\nexport * from \"./delegates.js\";\nexport * from \"./pull.js\";\nexport * from \"./write.js\";\nexport * from \"./vcs-reader.js\";\n", "export * from \"./schema.js\";\nexport * from \"./resolve.js\";\nexport * from \"./load.js\";\nexport * from \"./links.js\";\nexport * from \"./pull/index.js\";\n", "/**\n * First-run auth preflight helpers (MESH-2479).\n *\n * `mesh start`/`mesh dev` do long work (registry tarball fetches, docker\n * builds, pnpm installs) that fails minutes in \u2014 with npm's generic advice \u2014\n * when the CodeArtifact token or AWS SSO session is stale. These helpers\n * verify auth BEFORE the long work and name the exact fixing command.\n *\n * Pure parsers/classifiers are exported separately from the impure probes so\n * the branch logic is unit-testable without network or a home directory.\n */\n\nimport * as fs from \"fs\";\nimport * as os from \"os\";\nimport * as path from \"path\";\n\n/**\n * The context that owns the `@mesh-tech` registry. There is exactly one \u2014 the\n * `mesh-platform` CodeArtifact domain every tenant pulls from \u2014 so this is the\n * context whose broker can mint a read token for anybody, and it is what a\n * printed remediation should name.\n *\n * Safe to hardcode for the same reason `--profile mesh-dev` already was: it\n * identifies the registry, not the reader's own platform. It also resolves on a\n * machine with no AWS at all, via the pinned first-party alias.\n */\nexport const REGISTRY_CONTEXT = \"mesh.dev\";\n\n/**\n * The command that fixes a stale/missing CodeArtifact token \u2014 **broker-first**,\n * so it works for someone with no AWS account at all.\n *\n * Prefer `registryLoginFix(context)` at any call site that knows a better\n * context than the registry's own.\n */\nexport const REGISTRY_LOGIN_FIX = `mesh registry login ${REGISTRY_CONTEXT}`;\n\n/**\n * The AWS-profile form. Only correct for people who **deploy**, or when the\n * platform publishes no registry broker.\n *\n * Kept as a separate named constant rather than the default: `--profile`\n * deliberately skips the broker, so printing it as the generic fix sends a\n * developer with no AWS account to a command that cannot work for them.\n */\nexport const REGISTRY_LOGIN_FIX_AWS = \"mesh registry login --profile mesh-dev\";\n\n/**\n * Render the registry fix for a known context, falling back to the registry's\n * own context when the caller has none. Always returns a command that can be\n * run as printed \u2014 a remediation the reader has to edit first is half a\n * remediation.\n */\nexport function registryLoginFix(context?: string): string {\n return `mesh registry login ${context ?? REGISTRY_CONTEXT}`;\n}\n\n/** The documented AWS SSO login form (root package.json `sso` script). */\nexport const SSO_LOGIN_FIX = \"aws sso login --sso-session=mesh # or: pnpm sso\";\n\n/**\n * The `aws configure sso-session` snippet `pnpm sso` depends on. Printed\n * verbatim when ~/.aws/config has no [sso-session mesh] section \u2014 kept here\n * so the CLI and scripts/sso-login.sh describe the same setup.\n */\nexport const SSO_SESSION_SNIPPET = `[sso-session mesh]\nsso_start_url = https://trabian.awsapps.com/start\nsso_region = us-east-1\nsso_registration_scopes = sso:account:access`;\n\n// ============================================================================\n// ~/.npmrc parsing (pure)\n// ============================================================================\n\n/**\n * The user-level npmrc `aws codeartifact login` writes into \u2014 the token line\n * and, when the namespace flag is omitted, the unscoped `registry=` line.\n *\n * One definition for the whole CLI: the doctor, the probe, and the repair have\n * to be looking at the same file or they disagree about the same machine.\n * `os.homedir()` reads `$HOME` on POSIX, so a scratch-`HOME` test still works.\n */\nexport function homeNpmrcPath(): string {\n return path.join(os.homedir(), \".npmrc\");\n}\n\nexport interface NpmrcRegistryAuth {\n /** Registry base URL, e.g. https://mesh-platform-\u2026codeartifact\u2026/npm/mesh-packages/ */\n endpoint: string;\n token: string;\n}\n\n/**\n * Extract the CodeArtifact registry endpoint + auth token from npmrc content.\n * `aws codeartifact login` writes a line shaped like:\n * //mesh-platform-\u2026d.codeartifact.<region>.amazonaws.com/npm/<repo>/:_authToken=<tok>\n * Returns null when no CodeArtifact token line is present.\n */\nexport function parseNpmrcRegistryAuth(content: string): NpmrcRegistryAuth | null {\n for (const line of content.split(\"\\n\")) {\n const match = line.trim().match(/^\\/\\/([^:]*\\.codeartifact\\.[^:]*):_authToken=(.+)$/);\n if (match && match[1] && match[2]) {\n const endpoint = `https://${match[1]}${match[1].endsWith(\"/\") ? \"\" : \"/\"}`;\n return { endpoint, token: match[2].trim() };\n }\n }\n return null;\n}\n\n/**\n * Find an **unscoped** `registry=` line in npmrc content that points at\n * CodeArtifact \u2014 the line `aws codeartifact login` writes when it is run\n * WITHOUT `--namespace @mesh-tech`.\n *\n * That line makes CodeArtifact the *default* registry, so every public package\n * (lodash, react, \u2026) is fetched through it with the CodeArtifact token. When\n * the token expires 12 hours later, `npm install` of anything at all fails\n * with E401 \u2014 the private-scope breakage everyone expects, plus a total public\n * npm outage nobody does.\n *\n * Deliberately narrow \u2014 it must only match a line that is BOTH unscoped AND a\n * CodeArtifact host, so it never touches:\n * - `@mesh-tech:registry=\u2026` (scoped: the line we WANT)\n * - `//\u2026:_authToken=\u2026` (auth, unaffected by the default registry)\n * - `registry=https://npm.acme.internal/` (a team's legitimate private mirror)\n *\n * Returns the offending line verbatim (as it appears in the file), or null.\n */\nexport function findUnscopedCodeArtifactRegistry(content: string): string | null {\n for (const line of content.split(\"\\n\")) {\n const trimmed = line.trim();\n // npmrc comments start with ; or #\n if (!trimmed || trimmed.startsWith(\";\") || trimmed.startsWith(\"#\")) continue;\n // Anchored at `registry` \u2014 a scoped line starts with `@scope:`, so it can't match.\n const match = trimmed.match(/^registry\\s*=\\s*(\\S+)$/);\n if (!match || !match[1]) continue;\n if (isCodeArtifactRegistryUrl(match[1])) return line;\n }\n return null;\n}\n\n/** True when a registry URL's *host* is a CodeArtifact endpoint. */\nfunction isCodeArtifactRegistryUrl(value: string): boolean {\n try {\n return new URL(value).hostname.includes(\".codeartifact.\");\n } catch {\n // Not a parseable URL (env-var interpolation, protocol-relative, \u2026) \u2014\n // fall back to a substring test so we don't miss an obvious hijack.\n return value.includes(\".codeartifact.\");\n }\n}\n\n/**\n * Remove every unscoped CodeArtifact `registry=` line from npmrc content.\n * Pure: returns the rewritten content plus the first line removed (null when\n * the content was already clean, in which case `content` is returned\n * unchanged and callers should skip the write entirely).\n */\nexport function stripUnscopedCodeArtifactRegistry(content: string): {\n content: string;\n removed: string | null;\n} {\n const offender = findUnscopedCodeArtifactRegistry(content);\n if (offender === null) return { content, removed: null };\n\n const kept = content\n .split(\"\\n\")\n .filter((line) => findUnscopedCodeArtifactRegistry(line) === null);\n // split/join round-trips the file's trailing-newline state exactly.\n return { content: kept.join(\"\\n\"), removed: offender };\n}\n\n/**\n * The `//host/path/:_authToken=` key `aws codeartifact login` writes for a\n * registry endpoint \u2014 the endpoint with its scheme stripped and a leading `//`.\n *\n * Pure and shared so the broker path writes byte-identical lines to the AWS CLI\n * path. Two spellings of the same key would leave a stale token line behind\n * that npm might prefer, and the symptom (E401 hours later) points nowhere\n * near the cause.\n */\nexport function npmrcAuthKeyForEndpoint(endpoint: string): string {\n const withoutScheme = endpoint.replace(/^https?:\\/\\//, \"\");\n return `//${withoutScheme.endsWith(\"/\") ? withoutScheme : `${withoutScheme}/`}`;\n}\n\n/**\n * Upsert `key=value` lines into npmrc content: replace the existing line for a\n * key when present, append it otherwise, and leave every other line untouched.\n *\n * Pure. Always emits a trailing newline, and never reorders lines a\n * user put there themselves \u2014 an npmrc is a config file people hand-edit, and\n * a token refresh that rewrites the whole thing is how unrelated settings\n * silently disappear.\n */\nexport function upsertNpmrcLines(\n content: string,\n entries: ReadonlyArray<{ key: string; value: string }>,\n): string {\n let lines = content.length ? content.split(\"\\n\") : [];\n const trailingNewline = content.endsWith(\"\\n\");\n if (trailingNewline) lines = lines.slice(0, -1);\n\n for (const { key, value } of entries) {\n const line = `${key}=${value}`;\n const idx = lines.findIndex((l) => {\n const trimmed = l.trim();\n if (!trimmed || trimmed.startsWith(\";\") || trimmed.startsWith(\"#\")) return false;\n const eq = trimmed.indexOf(\"=\");\n return eq > 0 && trimmed.slice(0, eq).trim() === key;\n });\n if (idx >= 0) lines[idx] = line;\n else lines.push(line);\n }\n\n return lines.join(\"\\n\") + \"\\n\";\n}\n\n// ============================================================================\n// Registry token probe\n// ============================================================================\n\nexport type RegistryTokenState = \"fresh\" | \"expired\" | \"missing\" | \"unreachable\";\n\n/** Map an HTTP status from an authenticated registry request to a token state. */\nexport function classifyRegistryStatus(status: number): \"fresh\" | \"expired\" {\n // 401/403 mean the token itself was rejected. Anything else (200, 404, \u2026)\n // means auth was accepted \u2014 the token is usable.\n return status === 401 || status === 403 ? \"expired\" : \"fresh\";\n}\n\nexport interface RegistryProbe {\n state: RegistryTokenState;\n detail?: string;\n}\n\n/**\n * Verify the CodeArtifact token in ~/.npmrc actually works, with one small\n * authenticated metadata request (bounded by `timeoutMs`). Never throws.\n */\nexport async function probeRegistryToken(opts?: {\n npmrcPath?: string;\n timeoutMs?: number;\n fetchFn?: typeof fetch;\n}): Promise<RegistryProbe> {\n const npmrcPath = opts?.npmrcPath ?? homeNpmrcPath();\n const timeoutMs = opts?.timeoutMs ?? 8_000;\n const fetchFn = opts?.fetchFn ?? fetch;\n\n let auth: NpmrcRegistryAuth | null = null;\n try {\n auth = parseNpmrcRegistryAuth(fs.readFileSync(npmrcPath, \"utf-8\"));\n } catch {\n // unreadable/missing ~/.npmrc \u2014 same as no auth configured\n }\n if (!auth) return { state: \"missing\" };\n\n try {\n const res = await fetchFn(`${auth.endpoint}${encodeURIComponent(\"@mesh-tech/hub\")}`, {\n method: \"GET\",\n headers: { authorization: `Bearer ${auth.token}` },\n signal: AbortSignal.timeout(timeoutMs),\n });\n const state = classifyRegistryStatus(res.status);\n return state === \"expired\"\n ? { state, detail: `registry answered HTTP ${res.status} for an authenticated request` }\n : { state };\n } catch (err) {\n return {\n state: \"unreachable\",\n detail: err instanceof Error ? err.message : String(err),\n };\n }\n}\n\n// ============================================================================\n// npm / AWS error classification (pure)\n// ============================================================================\n\n/** True when npm output/an error message is an auth failure (E401/E403). */\nexport function isNpmAuthErrorText(text: string): boolean {\n return /\\bE?40[13]\\b|unauthenticated|unable to authenticate|authentication (required|failed)/i.test(\n text,\n );\n}\n\n/** True when an npm exec error (with stderr/message) is an auth failure. */\nexport function isNpmAuthError(err: unknown): boolean {\n const e = err as { stderr?: unknown; message?: unknown };\n const text = [e?.stderr, e?.message]\n .map((v) => (v === null || v === undefined ? \"\" : String(v)))\n .join(\"\\n\");\n return isNpmAuthErrorText(text);\n}\n\n/** True when an AWS SDK/CLI error message means the ambient session expired. */\nexport function isExpiredAwsTokenMessage(message: string): boolean {\n return /expired|invalid.*(security )?token|token.*(is )?invalid|no credential|could not load credentials|could not be found|sso session/i.test(\n message,\n );\n}\n\n// ============================================================================\n// ~/.aws/config parsing (pure) \u2014 `pnpm sso` / --profile prerequisites\n// ============================================================================\n\n/** Names of `[sso-session <name>]` sections in an AWS config file. */\nexport function parseSsoSessionNames(content: string): string[] {\n const names: string[] = [];\n for (const line of content.split(\"\\n\")) {\n const match = line.trim().match(/^\\[sso-session\\s+([^\\]]+)\\]$/);\n if (match && match[1]) names.push(match[1].trim());\n }\n return names;\n}\n\n/** True when the AWS config file declares the named profile. */\nexport function awsConfigHasProfile(content: string, profile: string): boolean {\n const pattern = new RegExp(\n `^\\\\[(?:profile\\\\s+)?${profile.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\")}\\\\]$`,\n );\n return content.split(\"\\n\").some((line) => pattern.test(line.trim()));\n}\n\n/** Read ~/.aws/config (honoring AWS_CONFIG_FILE); \"\" when unreadable. */\nexport function readAwsConfig(): string {\n const file = process.env.AWS_CONFIG_FILE ?? path.join(os.homedir(), \".aws\", \"config\");\n try {\n return fs.readFileSync(file, \"utf-8\");\n } catch {\n return \"\";\n }\n}\n\n// ============================================================================\n// App dependency scan (for the dev doctor's registry check)\n// ============================================================================\n\n/** True when the app's package.json depends on any @mesh-tech/* package. */\nexport function appUsesMeshPackages(appRoot: string): boolean {\n try {\n const pkg = JSON.parse(fs.readFileSync(path.join(appRoot, \"package.json\"), \"utf-8\")) as {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n optionalDependencies?: Record<string, string>;\n };\n return [pkg.dependencies, pkg.devDependencies, pkg.optionalDependencies].some(\n (deps) => deps && Object.keys(deps).some((name) => name.startsWith(\"@mesh-tech/\")),\n );\n } catch {\n return false;\n }\n}\n", "/**\n * Shared AWS credential resolution for mesh CLI commands.\n *\n * Three-tier resolution:\n * 1. Existing AWS credentials in environment (CI/CD) \u2192 use directly\n * 2. Zitadel JWT via `mesh login` \u2192 AssumeRoleWithWebIdentity\n * 3. Fallback \u2192 AssumeRole via current AWS session (SSO)\n *\n * Uses @aws-sdk/client-sts directly \u2014 does NOT shell out to the `aws` CLI\n * binary, so the binary is not a runtime requirement.\n */\n\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport {\n AssumeRoleCommand,\n AssumeRoleWithWebIdentityCommand,\n GetCallerIdentityCommand,\n STSClient,\n} from \"@aws-sdk/client-sts\";\nimport { logInfo, logSuccess, logWarn } from \"./log.js\";\nimport { isExpiredAwsTokenMessage, SSO_LOGIN_FIX } from \"./auth-preflight.js\";\nimport { ensureLogin } from \"../commands/login.js\";\n\nconst DEFAULT_REGION =\n process.env.AWS_REGION ?? process.env.AWS_DEFAULT_REGION ?? \"us-east-2\";\n\n/**\n * Derive the platform context key (e.g., \"mesh.dev\") from a Pulumi stack config.\n *\n * Reads `mesh:platform` from Pulumi.<stack>.yaml. Supports both formats:\n * mesh:platform: '{\"env\":\"dev\",\"name\":\"mesh\"}' \u2192 \"mesh.dev\"\n * mesh:platform:\n * name: mesh\n * env: dev \u2192 \"mesh.dev\"\n */\nexport function derivePlatformContext(appRoot: string, stack: string): string | null {\n const configFile = path.join(appRoot, `Pulumi.${stack}.yaml`);\n if (!fs.existsSync(configFile)) return null;\n\n const content = fs.readFileSync(configFile, \"utf-8\");\n\n // Try JSON-encoded string first\n const jsonMatch = content.match(/mesh:platform:\\s*'(\\{[^']+\\})'/);\n if (jsonMatch) {\n try {\n const parsed = JSON.parse(jsonMatch[1]!);\n if (parsed.name && parsed.env) return `${parsed.name}.${parsed.env}`;\n } catch {\n // fall through\n }\n }\n\n // Try YAML block format\n const nameMatch = content.match(/mesh:platform:[\\s\\S]*?name:\\s*(\\S+)/);\n const envMatch = content.match(/mesh:platform:[\\s\\S]*?env:\\s*(\\S+)/);\n if (nameMatch && envMatch) {\n return `${nameMatch[1]}.${envMatch[1]}`;\n }\n\n return null;\n}\n\n/**\n * Quote a `credential_process` command token for AWS config-file syntax: the\n * AWS SDK/CLI split the value on spaces, honoring double quotes \u2014 so any\n * token containing whitespace (e.g. a mesh binary under \"Application\n * Support\") must be wrapped in double quotes or the command is mis-split.\n * Tokens without whitespace are left bare (byte-identical to the historic\n * output).\n */\nfunction quoteCredProcessToken(token: string): string {\n return /\\s/.test(token) ? `\"${token}\"` : token;\n}\n\n/**\n * Resolve a STABLE absolute path to the running `mesh` entrypoint for\n * embedding in a `credential_process` line \u2014 or fall back to plain `mesh`\n * (PATH lookup) when `argv1` is missing, doesn't exist on disk, or lives in\n * a transient location (`npx` cache / OS temp dir): a profile pointing at a\n * path that evaporates breaks every later AWS call with a cryptic\n * credential_process error. The fallback is announced via `logWarn` so the\n * user knows to install mesh-cli globally.\n */\nexport function resolveStableMeshBin(\n argv1: string | undefined,\n deps: { exists?: (p: string) => boolean; warn?: (msg: string) => void } = {},\n): string {\n const exists = deps.exists ?? fs.existsSync;\n const warn = deps.warn ?? logWarn;\n let resolved = argv1 ? path.resolve(argv1) : undefined;\n // Under the source launcher the CLI process's argv[1] is a TypeScript entry\n // (bin/mesh.ts), which plain node cannot execute (type-stripped .js-suffixed\n // imports fail with ERR_MODULE_NOT_FOUND). Point the profile at the sibling\n // .mjs launcher instead \u2014 it bootstraps tsx itself, from any cwd/env. Keyed on\n // the `.ts` extension + a derived sibling (not the literal `mesh.ts`), so a\n // rename of the source entry doesn't silently revert to a broken value. Assign\n // unconditionally: if the sibling is absent the existing !exists guard below\n // reports it by name (rather than collapsing into the \"argv1 missing\" branch).\n if (resolved && /\\.ts$/.test(resolved)) {\n resolved = path.join(path.dirname(resolved), path.basename(resolved, \".ts\") + \".mjs\");\n }\n const transient =\n resolved !== undefined &&\n (/[\\\\/]_npx[\\\\/]/.test(resolved) || /^\\/(?:private\\/)?(?:tmp|var\\/folders)\\//.test(resolved));\n if (!resolved || !exists(resolved) || transient) {\n warn(\n `credential_process cannot reference a stable mesh binary` +\n (resolved ? ` (${resolved} is transient or missing)` : \"\") +\n ` \u2014 falling back to \\`mesh\\` on PATH. Install mesh-cli globally so the profile keeps refreshing.`,\n );\n return \"mesh\";\n }\n return resolved;\n}\n\n/**\n * Render an AWS config-file `[profile \u2026]` block whose `credential_process`\n * re-invokes `mesh login \u2026 --credential-process`, so the AWS SDK's default\n * provider chain auto-refreshes the underlying STS triple (the `mesh login`\n * process re-issues the Zitadel token as needed).\n *\n * Shared by `mesh dev` (child services) and `mesh login --export` so both\n * produce byte-identical profiles. Pure \u2014 no I/O. The `region` line is\n * emitted only when `region` is a non-empty string. Includes a trailing\n * newline. The binary path and role ARN are double-quoted when they contain\n * whitespace (AWS config command-splitting rules).\n */\nexport function renderCredentialProcessProfile(args: {\n profileName: string;\n context: string;\n roleArn: string;\n region?: string;\n meshBin: string;\n}): string {\n const lines = [\n `[profile ${args.profileName}]`,\n `credential_process = ${quoteCredProcessToken(args.meshBin)} login ${quoteCredProcessToken(args.context)} --credential-process --role ${quoteCredProcessToken(args.roleArn)}`,\n ];\n if (args.region) lines.push(`region = ${args.region}`);\n return lines.join(\"\\n\") + \"\\n\";\n}\n\n// Marker lines delimiting the mesh-managed section of the user's AWS config\n// file. Follows the `conda init` / `nvm` managed-block convention so the\n// section is discoverable and safely re-writable. The START marker carries\n// the context (one managed section per context); the END marker is shared.\nconst MANAGED_START_PREFIX = `# >>> mesh-cli managed profile `;\nconst MANAGED_START = (context: string) => `${MANAGED_START_PREFIX}${context} >>>`;\nconst MANAGED_END = `# <<< mesh-cli managed <<<`;\n\n/**\n * Given a managed START marker for OUR context whose matching END is missing\n * (orphaned \u2014 e.g. the user deleted the END line), find the index of the first\n * character we should NOT reclaim. Conservative by construction: because\n * `MANAGED_END` is a shared literal across contexts, an END found further down\n * may belong to ANOTHER context's healthy section \u2014 so we never scan to a\n * distant END or to EOF. We only reclaim the lines the mesh CLI provably\n * wrote (see `renderCredentialProcessProfile`): one `[profile \u2026]` header\n * followed by contiguous `key = value` lines, stopping at the first blank\n * line, comment/marker, second profile header, or `boundIdx` (the next\n * managed START of any context), whichever comes first.\n *\n * @param afterStart index just past OUR START marker text (before its newline)\n * @param boundIdx index of the next managed START marker after ours, or -1\n */\nfunction orphanedSectionTail(existing: string, afterStart: number, boundIdx: number): number {\n const limit = boundIdx === -1 ? existing.length : boundIdx;\n let idx = afterStart;\n if (idx >= limit || existing[idx] !== \"\\n\") return Math.min(idx, limit);\n idx++; // consume the newline terminating our START marker line\n let claimedHeader = false;\n while (idx < limit) {\n const nl = existing.indexOf(\"\\n\", idx);\n const lineEnd = nl === -1 || nl > limit ? limit : nl;\n const line = existing.slice(idx, lineEnd);\n const ours = claimedHeader\n ? /^[A-Za-z_][A-Za-z0-9_]*\\s*=/.test(line) // key = value continuation\n : /^\\[profile [^\\]]+\\]\\s*$/.test(line); // exactly one profile header\n if (!ours) return idx;\n claimedHeader = true;\n idx = lineEnd >= limit ? limit : lineEnd + 1;\n }\n return limit;\n}\n\n/**\n * Insert or replace the mesh-managed `[profile \u2026]` section for `context` in\n * the user's AWS config content, preserving ALL other content byte-for-byte\n * (this is the user's real ~/.aws/config \u2014 clobbering it breaks their other\n * profiles). Pure \u2014 no I/O; exported for unit testing.\n *\n * - Existing managed section for this context \u2192 replaced in place.\n * - Orphaned START (matching END lost) \u2192 only the contiguous profile block\n * that is provably ours is reclaimed; other contexts' sections and user\n * content below are preserved (see `orphanedSectionTail`).\n * - No section \u2192 appended, separated by a single blank line (and a trailing\n * newline is added to the existing content if it lacks one).\n */\nexport function upsertManagedAwsConfigSection(\n existing: string,\n context: string,\n profileBlock: string,\n): string {\n const body = profileBlock.endsWith(\"\\n\") ? profileBlock : profileBlock + \"\\n\";\n const section = `${MANAGED_START(context)}\\n${body}${MANAGED_END}\\n`;\n\n const startIdx = existing.indexOf(MANAGED_START(context));\n if (startIdx !== -1) {\n const afterStart = startIdx + MANAGED_START(context).length;\n const endIdx = existing.indexOf(MANAGED_END, afterStart);\n // MANAGED_END is a shared literal across contexts, so the first END below\n // our START is only OURS if no other context's START sits in between \u2014\n // otherwise that END closes the OTHER section and scanning to it would\n // swallow that section whole.\n const foreignIdx = existing.indexOf(MANAGED_START_PREFIX, afterStart);\n let tail: number;\n if (endIdx !== -1 && (foreignIdx === -1 || endIdx < foreignIdx)) {\n // Healthy section: replace START..END. Swallow a single trailing\n // newline of the old section so replacement is idempotent (the new\n // section brings its own).\n const tailIdx = endIdx + MANAGED_END.length;\n tail = existing[tailIdx] === \"\\n\" ? tailIdx + 1 : tailIdx;\n } else {\n // Orphaned START (our END missing). Reclaim only the contiguous\n // profile block that is provably ours \u2014 never foreign sections, user\n // profiles below, or everything to EOF.\n tail = orphanedSectionTail(existing, afterStart, foreignIdx);\n }\n return existing.slice(0, startIdx) + section + existing.slice(tail);\n }\n\n if (existing.length === 0) return section;\n const sep = existing.endsWith(\"\\n\\n\") ? \"\" : existing.endsWith(\"\\n\") ? \"\\n\" : \"\\n\\n\";\n return existing + sep + section;\n}\n\nfunction newStsClient(): STSClient {\n return new STSClient({ region: DEFAULT_REGION });\n}\n\n/** Pull AWS env vars out of an STS Credentials struct; null if any field is missing. */\nfunction toEnv(credentials: {\n AccessKeyId?: string;\n SecretAccessKey?: string;\n SessionToken?: string;\n}): Record<string, string> | null {\n const { AccessKeyId, SecretAccessKey, SessionToken } = credentials;\n if (!AccessKeyId || !SecretAccessKey || !SessionToken) return null;\n return {\n AWS_ACCESS_KEY_ID: AccessKeyId,\n AWS_SECRET_ACCESS_KEY: SecretAccessKey,\n AWS_SESSION_TOKEN: SessionToken,\n };\n}\n\n/**\n * IAM rejects a DurationSeconds higher than the role's MaxSessionDuration with\n * a ValidationError. We detect that and fall back to a one-hour session.\n */\nfunction isMaxSessionDurationError(err: unknown): boolean {\n if (!(err instanceof Error)) return false;\n const message = err.message ?? \"\";\n return (\n message.includes(\"MaxSessionDuration\") ||\n message.includes(\"DurationSeconds\")\n );\n}\n\n/** Assume an IAM role via current AWS session and return credentials as env vars. */\nexport async function assumeRole(\n roleArn: string,\n sessionName: string = \"mesh-cli\",\n durationSeconds: number = 43200,\n): Promise<Record<string, string> | null> {\n const sts = newStsClient();\n for (const duration of [durationSeconds, 3600]) {\n try {\n const resp = await sts.send(\n new AssumeRoleCommand({\n RoleArn: roleArn,\n RoleSessionName: sessionName,\n DurationSeconds: duration,\n }),\n );\n if (!resp.Credentials) return null;\n return toEnv(resp.Credentials);\n } catch (err) {\n if (!isMaxSessionDurationError(err) || duration === 3600) {\n const message = err instanceof Error ? err.message : String(err);\n logWarn(`AssumeRole failed: ${message}`);\n // Name the SSO fix when the ambient session is the problem \u2014 the raw\n // STS error never mentions `aws sso login` (MESH-2479).\n if (isExpiredAwsTokenMessage(message)) {\n logWarn(` Your AWS SSO session looks expired or missing \u2014 refresh with: ${SSO_LOGIN_FIX}`);\n }\n return null;\n }\n // Retry with shorter duration\n }\n }\n return null;\n}\n\n/** STS credentials for a Zitadel-JWT-assumed role, including expiry. */\nexport interface StsCreds {\n AccessKeyId: string;\n SecretAccessKey: string;\n SessionToken: string;\n /** ISO-8601 expiration timestamp. */\n Expiration: string;\n}\n\n/**\n * Assume role using a Zitadel JWT via AssumeRoleWithWebIdentity, returning\n * the full STS credential struct (including `Expiration`) rather than the\n * env-var shape. Used by callers that need to track/refresh expiry (e.g.\n * `credential_process`).\n */\nexport async function assumeRoleCredentials(\n roleArn: string,\n idToken: string,\n sessionName: string,\n durationSeconds: number = 43200,\n): Promise<StsCreds | null> {\n // STS WebIdentity does not require ambient AWS credentials \u2014 the JWT proves identity.\n const sts = newStsClient();\n for (const duration of [durationSeconds, 3600]) {\n try {\n const resp = await sts.send(\n new AssumeRoleWithWebIdentityCommand({\n RoleArn: roleArn,\n RoleSessionName: sessionName,\n WebIdentityToken: idToken,\n DurationSeconds: duration,\n }),\n );\n if (!resp.Credentials) return null;\n const env = toEnv(resp.Credentials);\n if (!env) return null;\n return {\n // `env` is a `Record<string, string>` (index-signature typed), so\n // `noUncheckedIndexedAccess` widens these to `string | undefined`\n // even though `toEnv` guarantees they're set \u2014 assert accordingly.\n AccessKeyId: env.AWS_ACCESS_KEY_ID!,\n SecretAccessKey: env.AWS_SECRET_ACCESS_KEY!,\n SessionToken: env.AWS_SESSION_TOKEN!,\n Expiration: resp.Credentials.Expiration!.toISOString(),\n };\n } catch (err) {\n if (!isMaxSessionDurationError(err) || duration === 3600) {\n logWarn(\n `AssumeRoleWithWebIdentity failed: ${err instanceof Error ? err.message : String(err)}`,\n );\n return null;\n }\n // Retry with shorter duration\n }\n }\n return null;\n}\n\n/** Assume role using a Zitadel JWT via AssumeRoleWithWebIdentity. */\nexport async function assumeRoleWithWebIdentity(\n roleArn: string,\n idToken: string,\n sessionName: string,\n durationSeconds: number = 43200,\n): Promise<Record<string, string> | null> {\n const creds = await assumeRoleCredentials(roleArn, idToken, sessionName, durationSeconds);\n if (!creds) return null;\n return toEnv(creds);\n}\n\n/**\n * Extract the `iss` claim from a JWT without ever throwing \u2014 malformed or\n * corrupt tokens (e.g. a damaged `~/.config/mesh/credentials.json`) yield\n * `undefined`. The failure-diagnostic paths use this; a decode that throws\n * there would crash before the diagnostic prints, which is exactly the\n * failure class MESH-2515 removes.\n */\nexport function tokenIssuer(token: string): string | undefined {\n const iss = decodeJwtPayload(token)?.iss;\n return typeof iss === \"string\" && iss ? iss : undefined;\n}\n\n/**\n * Explain an AssumeRoleWithWebIdentity failure in platform terms: which login\n * session (context + token issuer) tried to assume which role, in which AWS\n * account. STS's \"web identity token could not be validated\" reads like an\n * IAM/expiry problem, but the usual cause is a context whose issuer the role's\n * account simply doesn't trust \u2014 e.g. a `mesh.dev` session against a role in a\n * `trabian`-platform account (MESH-2515). stderr only \u2014 callers in\n * `--credential-process` mode must keep stdout JSON-clean.\n *\n * `format: \"inline\"` renders the same facts as one line, for detail fields\n * that get interpolated mid-sentence (the doctor/preflight cred probe). Both\n * forms keep the `AssumeRoleWithWebIdentity failed` prefix the doctor plan\n * documents as the detail capture.\n */\nexport function describeAssumeFailure(\n opts: {\n roleArn: string;\n context?: string;\n issuer?: string;\n },\n format: \"block\" | \"inline\" = \"block\",\n): string {\n const account = /^arn:aws:iam::(\\d+):/.exec(opts.roleArn)?.[1];\n const head =\n `AssumeRoleWithWebIdentity failed for ${opts.roleArn}` +\n (account ? ` (account ${account})` : \"\");\n const session = opts.context\n ? `mesh login context '${opts.context}'` + (opts.issuer ? ` (issuer ${opts.issuer})` : \"\")\n : opts.issuer\n ? `issuer ${opts.issuer}`\n : undefined;\n if (format === \"inline\") {\n return (\n head +\n (session ? ` via ${session}` : \"\") +\n \" \u2014 if the role's account doesn't trust this issuer, this is a context mismatch\" +\n \" (wrong `mesh:platform`), not an IAM permission problem\"\n );\n }\n const lines = [head];\n if (session) lines.push(` Session: ${session}`);\n lines.push(\n \" If the role's account does not trust this issuer, you are logged into the\",\n \" wrong context for this stack \u2014 check `mesh:platform` in the app's Pulumi\",\n \" config and `mesh login <platform>.<env>` accordingly. (This is a context\",\n \" mismatch, not an IAM permission problem.)\",\n );\n return lines.join(\"\\n\");\n}\n\n/** Format STS credentials as AWS `credential_process` JSON (Version 1). */\nexport function toCredentialProcessJson(creds: StsCreds): string {\n return JSON.stringify({\n Version: 1,\n AccessKeyId: creds.AccessKeyId,\n SecretAccessKey: creds.SecretAccessKey,\n SessionToken: creds.SessionToken,\n Expiration: creds.Expiration,\n });\n}\n\nexport interface ResolvedAwsCreds {\n /** AWS credential env vars (ACCESS_KEY_ID, SECRET_ACCESS_KEY, SESSION_TOKEN) */\n env: Record<string, string>;\n /** How the credentials were obtained */\n method: \"environment\" | \"zitadel\" | \"sso\";\n}\n\nexport interface AwsIdentity {\n /** Full caller ARN, e.g. arn:aws:iam::159923586610:user/CI-CD_User */\n arn: string;\n accountId: string;\n /** Where the SDK's default chain found the credentials, for the human reading it. */\n source: \"environment\" | \"profile\";\n}\n\n/**\n * Ask \"is there a working AWS connection right now?\" \u2014 nothing more.\n *\n * Deliberately NOT `resolveAwsCredentials`: that one answers \"get me credentials\n * for role X\" and has an opinion about how they were obtained. This one runs\n * GetCallerIdentity through the SDK's default provider chain and reports whatever\n * it finds, so a static key/secret pair in `~/.aws/credentials` counts exactly as\n * much as an SSO session or a Zitadel-minted role. Returns null when the chain\n * yields nothing usable.\n */\nexport async function probeAwsIdentity(): Promise<AwsIdentity | null> {\n try {\n const out = await newStsClient().send(new GetCallerIdentityCommand({}));\n if (!out.Arn || !out.Account) return null;\n return {\n arn: out.Arn,\n accountId: out.Account,\n source: process.env.AWS_ACCESS_KEY_ID ? \"environment\" : \"profile\",\n };\n } catch {\n return null;\n }\n}\n\n/**\n * Decode a Zitadel-issued JWT payload (no signature check \u2014 we only\n * use it for role-selection hints in mesh-cli; the actual STS calls\n * still verify against the OIDC provider). Returns null on malformed\n * input.\n */\nfunction decodeJwtPayload(token: string): Record<string, unknown> | null {\n const parts = token.split(\".\");\n if (parts.length !== 3 || !parts[1]) return null;\n try {\n return JSON.parse(Buffer.from(parts[1], \"base64url\").toString());\n } catch {\n return null;\n }\n}\n\n/**\n * Pick the AWS role ARN to assume based on Zitadel claims.\n *\n * Zitadel emits project roles under\n * `urn:zitadel:iam:org:project:<projectId>:roles` as a nested object\n * keyed by role name. We treat the presence of `mesh.platform:admin`\n * (or any role listed in `meshcli.adminRoles` in config) as the\n * signal to assume the broader admin role when the caller has\n * configured one.\n *\n * Returns `defaultRole` when no admin role is configured, no admin\n * claim is present, or the JWT can't be parsed. This keeps existing\n * deployments working without a config change.\n *\n * The admin AWS role's IAM trust policy is expected to gate\n * assumption on the same Zitadel claim in production (so the CLI\n * preference can't be spoofed). That setup is its own change \u2014 see\n * TODO(mesh-zitadel-aws-role-mapping).\n */\nexport function selectRoleForCaller(\n idToken: string | null,\n options: {\n defaultRole: string;\n adminRole?: string;\n /**\n * Zitadel role names that should map to `adminRole`. Defaults to\n * a single `mesh.platform:admin` role; callers can override via\n * config to introduce role tiers later.\n */\n adminClaimRoles?: string[];\n },\n): string {\n if (!options.adminRole || !idToken) return options.defaultRole;\n const adminRoles = options.adminClaimRoles ?? [\"mesh.platform:admin\"];\n const claims = decodeJwtPayload(idToken);\n if (!claims) return options.defaultRole;\n\n // Find the project-roles claim \u2014 key shape:\n // urn:zitadel:iam:org:project:<projectId>:roles\n // Multiple projects can emit roles; we walk all matching keys.\n for (const [key, value] of Object.entries(claims)) {\n if (!key.startsWith(\"urn:zitadel:iam:org:project:\")) continue;\n if (!key.endsWith(\":roles\")) continue;\n if (!value || typeof value !== \"object\") continue;\n const claimedRoles = Object.keys(value as Record<string, unknown>);\n for (const target of adminRoles) {\n if (claimedRoles.includes(target)) return options.adminRole;\n }\n }\n return options.defaultRole;\n}\n\n/**\n * Resolve AWS credentials using the three-tier strategy.\n *\n * @param roleArn The IAM role to assume (from mesh:deployerRole)\n * @param appRoot Pulumi app root directory\n * @param stack Pulumi stack name\n * @returns Resolved credentials, or null if all methods fail\n *\n * To inherit a broader role based on Zitadel claims, call\n * `selectRoleForCaller` first and pass the result as `roleArn`.\n */\nexport async function resolveAwsCredentials(\n roleArn: string,\n appRoot: string,\n stack: string,\n): Promise<ResolvedAwsCreds | null> {\n const roleName = roleArn.split(\"/\").pop() ?? roleArn;\n\n // Path 1: Existing AWS credentials in environment (CI/CD)\n if (process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SESSION_TOKEN) {\n logInfo(\"Using existing AWS credentials from environment\");\n return {\n env: {\n AWS_ACCESS_KEY_ID: process.env.AWS_ACCESS_KEY_ID,\n AWS_SECRET_ACCESS_KEY: process.env.AWS_SECRET_ACCESS_KEY ?? \"\",\n AWS_SESSION_TOKEN: process.env.AWS_SESSION_TOKEN,\n },\n method: \"environment\",\n };\n }\n\n // Path 2: Zitadel JWT via mesh login \u2192 AssumeRoleWithWebIdentity.\n // Non-interactive here: only a valid CACHED session is used. An interactive\n // device-flow before the SSO fallback would stall headless runs (CI,\n // `mesh dev` with a working AWS_PROFILE) for minutes polling device codes\n // nobody sees \u2014 SSO gets its chance first; interactive login is Path 4.\n const platformContext = derivePlatformContext(appRoot, stack);\n if (platformContext) {\n const meshCreds = await ensureLogin(platformContext, { interactive: false });\n if (meshCreds) {\n const sessionName = (meshCreds.email ?? \"mesh-cli\")\n .replace(/[^a-zA-Z0-9=,.@-]/g, \"_\")\n .slice(0, 64);\n logInfo(`Assuming ${roleName} via Zitadel (${meshCreds.email ?? platformContext})`);\n\n const creds = await assumeRoleWithWebIdentity(roleArn, meshCreds.idToken, sessionName);\n if (creds) {\n logSuccess(`Assumed ${roleName} via Zitadel`);\n return { env: creds, method: \"zitadel\" };\n }\n\n logWarn(\n \"Zitadel JWT auth failed \u2014 falling back to AWS SSO.\\n\" +\n ` (Try: mesh login ${platformContext})`,\n );\n }\n }\n\n // Path 3: Fallback \u2014 AssumeRole via current AWS session (SSO)\n logInfo(`Assuming ${roleName} via AWS SSO`);\n const creds = await assumeRole(roleArn, \"mesh-cli\");\n if (creds) {\n logSuccess(`Assumed ${roleName}`);\n return { env: creds, method: \"sso\" };\n }\n\n // Path 4: Last resort \u2014 interactive Zitadel login (device/browser). Only\n // reached when there's no env cred, no cached session, and no working SSO,\n // i.e. a human at a terminal who genuinely needs to log in.\n if (platformContext && process.stdout.isTTY) {\n const meshCreds = await ensureLogin(platformContext);\n if (meshCreds) {\n const sessionName = (meshCreds.email ?? \"mesh-cli\")\n .replace(/[^a-zA-Z0-9=,.@-]/g, \"_\")\n .slice(0, 64);\n logInfo(`Assuming ${roleName} via Zitadel (${meshCreds.email ?? platformContext})`);\n const zCreds = await assumeRoleWithWebIdentity(roleArn, meshCreds.idToken, sessionName);\n if (zCreds) {\n logSuccess(`Assumed ${roleName} via Zitadel`);\n return { env: zCreds, method: \"zitadel\" };\n }\n }\n }\n\n return null;\n}\n", "/**\n * Pinned short-name \u2192 FQDN map for FIRST-PARTY Mesh platforms.\n *\n * ## Why this file exists\n *\n * `mesh login mesh.dev` on a clean laptop used to be unresolvable. Discovery\n * has two paths: SSM (needs AWS credentials \u2014 the thing we are removing) and\n * the anonymous `https://cli.<domain>/.well-known/mesh.json` endpoint. The\n * HTTPS path is deliberately gated to contexts with \u22652 dots, because hitting\n * `https://cli.<short-name>/\u2026` for an arbitrary short context would let whoever\n * registers that domain seed our cached issuer/clientId \u2014 login phishing.\n *\n * So the short context every internal doc tells a new developer to use was\n * exactly the one that could not resolve without AWS.\n *\n * ## Why a compiled-in map is the safe fix\n *\n * The alias is resolved from THIS table, which ships inside the CLI and is\n * changed only by a reviewed commit. It is not read from the network, from\n * `~/.config/mesh`, or from an environment variable, so it cannot be seeded by\n * an attacker \u2014 which is the property the \u22652-dot guard protects and the reason\n * that guard must NOT be loosened instead.\n *\n * ## Adding an entry\n *\n * Only add a domain Trabian controls and has verified serves\n * `/.well-known/mesh.json`. The map is the trust anchor; a typo here is a\n * phishing vector, so treat additions as a security review, not a config edit.\n */\nexport const FIRST_PARTY_CONTEXTS: Readonly<Record<string, string>> = Object.freeze({\n // Verified 2026-08-14: https://cli.dev.platform.meshtech.io/.well-known/mesh.json\n // answers with the platform's issuer + CLI client id + registryBroker,\n // anonymously. (Repointed from dev.trabian.meshtech.io \u2014 the trabian tenant\n // platform lives in a different AWS account with no registry; the\n // platform-dev stack in the registry-owning account is the developer front\n // door. mesh-sandbox#32 / #3587.)\n \"mesh.dev\": \"dev.platform.meshtech.io\",\n});\n\n/**\n * The FQDN to run anonymous HTTPS discovery against for a short first-party\n * context, or null when the context is not a pinned alias.\n *\n * `Object.hasOwn` rather than a bare lookup: a plain-object index answers\n * `constructor` / `toString` from the prototype chain, and this function's\n * answer decides which host we trust with our issuer + client id.\n */\nexport function firstPartyDomainFor(context: string): string | null {\n if (!Object.hasOwn(FIRST_PARTY_CONTEXTS, context)) return null;\n const domain = FIRST_PARTY_CONTEXTS[context];\n return typeof domain === \"string\" && domain ? domain : null;\n}\n", "/**\n * Shared CLI error type with structured remediation.\n *\n * Every failure along the golden path should tell the user the exact `mesh`\n * command (or doc) that fixes it. Remediation strings must be commands or\n * docs \u2014 never \"ask <person>\".\n */\n\nimport chalk from \"chalk\";\n\nexport interface Remediation {\n /** Exact command that fixes the failure, e.g. \"mesh login trabian-dev\" */\n command?: string;\n /** Documentation URL or repo-relative doc path with more context */\n docs?: string;\n /** Whether the owning command can apply this fix itself via --fix */\n autoFixable?: boolean;\n}\n\nexport interface MeshCliErrorOptions {\n remediation?: Remediation;\n /** Process exit code (default 1) */\n exitCode?: number;\n cause?: unknown;\n}\n\nexport class MeshCliError extends Error {\n readonly remediation?: Remediation;\n readonly exitCode: number;\n\n constructor(message: string, options: MeshCliErrorOptions = {}) {\n super(message, options.cause !== undefined ? { cause: options.cause } : undefined);\n this.name = \"MeshCliError\";\n this.remediation = options.remediation;\n this.exitCode = options.exitCode ?? 1;\n }\n}\n\n/**\n * Render an error's BODY \u2014 the message plus its \"\u2192 run: <command>\" /\n * \"\u2192 see: <docs>\" remediation lines, with no leading severity glyph.\n *\n * Use this when the caller supplies its own glyph: a recovery path that logs a\n * refusal through `logWarn` (which prefixes \u26A0) and carries on would otherwise\n * print \"\u26A0 \u2717 \u2026\". The remediation lines are the part that must survive \u2014 they\n * name the corrupt file to delete.\n */\nexport function renderErrorBody(err: unknown): string {\n const message = err instanceof Error ? err.message : String(err);\n if (!(err instanceof MeshCliError)) return message;\n const lines = [message];\n if (err.remediation?.command) {\n lines.push(chalk.cyan(\" \u2192 run: \") + err.remediation.command);\n }\n if (err.remediation?.docs) {\n lines.push(chalk.cyan(\" \u2192 see: \") + err.remediation.docs);\n }\n return lines.join(\"\\n\");\n}\n\n/**\n * Render an error for humans. MeshCliError gets its remediation appended as\n * \"\u2192 run: <command>\" / \"\u2192 see: <docs>\" lines; anything else renders its message.\n */\nexport function renderError(err: unknown): string {\n return chalk.red(\"\u2717\") + \" \" + renderErrorBody(err);\n}\n\n/**\n * Render an error as JSON for agents. Same structure as the human output:\n * { error, remediation?: { command?, docs?, autoFixable? } }.\n */\nexport function renderErrorJson(err: unknown): string {\n if (err instanceof MeshCliError) {\n return JSON.stringify({\n error: err.message,\n ...(err.remediation ? { remediation: err.remediation } : {}),\n });\n }\n return JSON.stringify({ error: err instanceof Error ? err.message : String(err) });\n}\n\nlet jsonPayloadEmitted = false;\n\n/**\n * Print a command's `--json` payload \u2014 the single machine-readable document on\n * stdout \u2014 and record that it happened.\n *\n * A command that emits a payload and *then* throws (the `mesh init` doctor\n * throws by design whenever a check fails) used to produce TWO concatenated\n * JSON documents on stdout, because `handleCliError` appended `{\"error\":\u2026}`.\n * Two documents is not JSON: `mesh init app-tenant --json | jq` failed to parse\n * on exactly the failure path a script cares about. Routing every payload\n * through here lets the handler know stdout is already spoken for.\n */\nexport function emitJsonPayload(payload: unknown): void {\n console.log(JSON.stringify(payload, null, 2));\n jsonPayloadEmitted = true;\n}\n\n/** True once a command has written its `--json` payload to stdout. */\nexport function hasEmittedJsonPayload(): boolean {\n return jsonPayloadEmitted;\n}\n\n/** Test seam \u2014 the flag is module state, so specs have to be able to clear it. */\nexport function resetJsonPayloadEmitted(): void {\n jsonPayloadEmitted = false;\n}\n\n/**\n * Top-level handler for bin/mesh.ts. Prints the error (JSON when the\n * invocation asked for --json anywhere, since per-command flags aren't\n * parsed once dispatch has failed) and exits with the error's code.\n *\n * When the command already emitted a `--json` payload, that payload IS the\n * machine surface \u2014 and it says strictly more than this error would (the\n * doctor's payload carries `ok:false` plus a per-check `fix` command). So the\n * error goes to stderr as human diagnostics and stdout keeps exactly one\n * parseable document.\n */\nexport function handleCliError(err: unknown): never {\n const wantsJson = process.argv.includes(\"--json\");\n if (wantsJson && !hasEmittedJsonPayload()) {\n console.log(renderErrorJson(err));\n } else {\n console.error(renderError(err));\n }\n process.exit(err instanceof MeshCliError ? err.exitCode : 1);\n}\n", "/**\n * Context detection - determines tenant, stage, and platform environment\n * from the current directory and environment variables.\n */\n\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport { logInfo } from \"./log.js\";\n\nexport interface MeshContext {\n tenant: string;\n stage: string;\n platformEnv: string;\n}\n\n/**\n * Find a file by walking up directories from the starting directory.\n * Returns the full path to the file if found, undefined otherwise.\n */\nfunction findFileUpward(filename: string, startDir: string = process.cwd()): string | undefined {\n let currentDir = startDir;\n const root = path.parse(currentDir).root;\n\n while (currentDir !== root) {\n const filePath = path.join(currentDir, filename);\n if (fs.existsSync(filePath)) {\n return filePath;\n }\n currentDir = path.dirname(currentDir);\n }\n return undefined;\n}\n\n/**\n * Detect tenant and stage from current directory and environment.\n *\n * Priority for stage:\n * 1. --stage flag (passed as stageArg)\n * 2. MESH_STAGE env var\n * 3. SST_STAGE env var\n * 4. .sst/stage file\n * 5. Pulumi config file name\n * 6. Default: \"dev\"\n *\n * Priority for tenant:\n * 1. MESH_TENANT env var\n * 2. config.ts tenant field\n * 3. Pulumi config mesh:tenant\n * 4. Directory path (tenants/{tenant}/...)\n * 5. Default: \"mesh\"\n */\nexport function detectContext(stageArg?: string): MeshContext {\n let tenant: string | undefined;\n let stage: string | undefined;\n\n const cwd = process.cwd();\n\n // Try to detect from Pulumi.yaml\n if (fs.existsSync(\"Pulumi.yaml\")) {\n // Look for Pulumi.*.yaml config files\n const files = fs.readdirSync(\".\").filter(\n (f) => f.startsWith(\"Pulumi.\") && f.endsWith(\".yaml\") && f !== \"Pulumi.yaml\"\n );\n\n const configFile = files[0];\n if (configFile) {\n const content = fs.readFileSync(configFile, \"utf-8\");\n\n // Extract tenant from mesh:tenant config\n const tenantMatch = content.match(/^\\s*mesh:tenant:\\s*[\"']?([^\"'\\n]+)[\"']?/m);\n if (tenantMatch?.[1]) {\n tenant = tenantMatch[1].trim();\n }\n\n // Extract stage from filename: Pulumi.<stage>.yaml\n const stageMatch = configFile.match(/Pulumi\\.(.+)\\.yaml/);\n if (stageMatch?.[1]) {\n stage = stageMatch[1];\n }\n }\n }\n\n // Try to detect from SST config (walk up directories to find it)\n const sstConfigPath = findFileUpward(\"sst.config.ts\");\n let sstDir: string | undefined;\n\n if (sstConfigPath) {\n sstDir = path.dirname(sstConfigPath);\n\n // Check parent config.ts for tenant (relative to sst.config.ts location)\n const parentConfigPath = path.join(sstDir, \"..\", \"config.ts\");\n if (fs.existsSync(parentConfigPath)) {\n const configContent = fs.readFileSync(parentConfigPath, \"utf-8\");\n const tenantMatch = configContent.match(/tenant:\\s*[\"']([^\"']+)[\"']/);\n if (tenantMatch) {\n tenant = tenantMatch[1];\n }\n }\n\n // Check .sst/stage for current stage (relative to sst.config.ts location)\n const sstStagePath = path.join(sstDir, \".sst\", \"stage\");\n if (fs.existsSync(sstStagePath)) {\n stage = fs.readFileSync(sstStagePath, \"utf-8\").trim();\n }\n }\n\n // Fallback: infer tenant from directory path\n if (!tenant) {\n const pathMatch = cwd.match(/tenants\\/([^/]+)/);\n if (pathMatch) {\n tenant = pathMatch[1];\n }\n }\n\n // Apply priority: stageArg > MESH_STAGE > SST_STAGE > detected > default\n stage = stageArg || process.env.MESH_STAGE || process.env.SST_STAGE || stage || \"dev\";\n tenant = process.env.MESH_TENANT || tenant || \"mesh\";\n\n // Resolve platform environment from config.ts if available\n let platformEnv = stage;\n let platformEnvMap: Record<string, string> = {};\n let defaultPlatformEnv: string | undefined;\n\n // Try to read platformEnvMap and defaultPlatformEnv from config.ts (relative to sst.config.ts location)\n const configPath = sstDir ? path.join(sstDir, \"..\", \"config.ts\") : \"../config.ts\";\n if (fs.existsSync(configPath)) {\n const configContent = fs.readFileSync(configPath, \"utf-8\");\n\n // Parse platformEnvMap object\n const mapMatch = configContent.match(/platformEnvMap:\\s*\\{([^}]+)\\}/);\n if (mapMatch?.[1]) {\n const entries = mapMatch[1].matchAll(/(\\w+):\\s*[\"']([^\"']+)[\"']/g);\n for (const entry of entries) {\n const key = entry[1];\n const value = entry[2];\n if (key && value) {\n platformEnvMap[key] = value;\n }\n }\n }\n\n // Parse defaultPlatformEnv\n const defaultMatch = configContent.match(/defaultPlatformEnv:\\s*[\"']([^\"']+)[\"']/);\n if (defaultMatch?.[1]) {\n defaultPlatformEnv = defaultMatch[1];\n }\n }\n\n // Parse env from stage by stripping tenant prefix (matches Pulumi pattern)\n // e.g., \"mesh-dev-temporal\" \u2192 env \"dev-temporal\"\n const tenantPrefix = `${tenant}-`;\n const parsedEnv = stage.startsWith(tenantPrefix)\n ? stage.slice(tenantPrefix.length)\n : stage;\n\n // Use config mapping if available, then defaultPlatformEnv, otherwise use parsed env directly\n platformEnv = platformEnvMap[parsedEnv] ?? platformEnvMap[stage] ?? defaultPlatformEnv ?? parsedEnv;\n\n logInfo(`Stage: ${stage}, Platform: ${platformEnv}, Tenant: ${tenant}`);\n\n return { tenant, stage, platformEnv };\n}\n", "/**\n * Bastion utilities for SSM tunneling to platform services\n */\n\nimport { SSMClient, GetParameterCommand } from \"@aws-sdk/client-ssm\";\nimport { logInfo, logSuccess, logError } from \"./log.js\";\n\n/**\n * Service endpoint info\n */\nexport interface ServiceEndpoint {\n host: string;\n port: number;\n}\n\n/**\n * Platform bastion info from SSM\n */\nexport interface PlatformBastionInfo {\n instanceId: string;\n securityGroupId: string;\n services: Record<string, ServiceEndpoint>;\n}\n\n/**\n * Legacy bastion info (for backward compatibility with db commands)\n */\nexport interface BastionInfo {\n instanceId: string;\n rdsEndpoint: string;\n rdsPort: number;\n}\n\n/**\n * Get platform bastion info from SSM parameter store.\n *\n * Reads the platformBastion key from the platform export at\n * /mesh-platform/{tenant}/{platformEnv}/platform. Falls back to the legacy\n * separate parameter at /mesh-platform/{tenant}/{platformEnv}/platform-bastion\n * for backward compatibility.\n */\nexport async function getPlatformBastionInfo(\n tenant: string,\n platformEnv: string,\n region?: string\n): Promise<PlatformBastionInfo> {\n const ssm = new SSMClient(region ? { region } : {});\n\n // Captured so the final error can distinguish a CREDS failure (the common\n // case \u2014 stale/expired ambient AWS creds, or creds lacking cross-tenant read\n // on the hub param) from a genuinely missing bastion. Without this the read\n // error is swallowed and every failure looks like \"bastion not deployed\".\n let primaryError: unknown;\n\n // Primary: read from the platform export (platformBastion is a nested key)\n const platformPath = `/mesh-platform/${tenant}/${platformEnv}/platform`;\n logInfo(`Looking up platform bastion from ${platformPath}...`);\n\n try {\n const response = await ssm.send(\n new GetParameterCommand({ Name: platformPath })\n );\n\n if (response.Parameter?.Value) {\n const platform = JSON.parse(response.Parameter.Value);\n if (platform.platformBastion) {\n const info = platform.platformBastion as PlatformBastionInfo;\n logSuccess(`Found bastion: ${info.instanceId}`);\n\n const serviceNames = Object.keys(info.services);\n if (serviceNames.length > 0) {\n logInfo(`Available services: ${serviceNames.join(\", \")}`);\n }\n\n return info;\n }\n }\n } catch (err) {\n // Don't swallow: keep the real reason (AccessDenied / ExpiredToken / \u2026) so\n // the final error can be actionable. Then try the legacy path.\n primaryError = err;\n }\n\n // Fallback: legacy separate parameter\n const legacyPath = `/mesh-platform/${tenant}/${platformEnv}/platform-bastion`;\n logInfo(`Trying legacy path ${legacyPath}...`);\n\n try {\n const response = await ssm.send(\n new GetParameterCommand({ Name: legacyPath })\n );\n\n if (!response.Parameter?.Value) {\n throw new Error(`Platform bastion not found`);\n }\n\n const info = JSON.parse(response.Parameter.Value) as PlatformBastionInfo;\n logSuccess(`Found bastion: ${info.instanceId}`);\n\n const serviceNames = Object.keys(info.services);\n if (serviceNames.length > 0) {\n logInfo(`Available services: ${serviceNames.join(\", \")}`);\n }\n\n return info;\n } catch (legacyError) {\n // Classify on the PRIMARY read's error (the meaningful one) \u2014 the legacy\n // path is usually just ParameterNotFound and hides the real cause.\n const cause = primaryError ?? legacyError;\n const name = (cause as { name?: string })?.name ?? \"\";\n const credsProblem = /Expired|UnrecognizedClient|InvalidClientTokenId|InvalidSignature|CredentialsProviderError|AccessDenied/i.test(\n name\n );\n\n if (credsProblem) {\n logError(\n `Could not read the platform bastion from ${platformPath} \u2014 AWS error: ${name}.`\n );\n logInfo(\n \"This is almost always a CREDENTIALS problem, not a missing bastion.\"\n );\n logInfo(\n \" \u2022 The read uses the ambient AWS creds of this process; they must be valid AND able to read the HUB param above.\"\n );\n logInfo(\n \" \u2022 Check: `aws sts get-caller-identity` (ExpiredToken \u2192 refresh; AccessDenied \u2192 those creds lack hub read \u2014 use InfraAdmin-grade creds).\"\n );\n logInfo(\n \" \u2022 Stale creds often hide in the tmux GLOBAL env (`tmux show-environment -g | grep AWS_`); a per-shell `unset` won't clear them.\"\n );\n } else {\n logError(`Platform bastion not found in ${platformPath} or ${legacyPath}`);\n logInfo(\"Make sure platformBastion is enabled in your platform config and deployed.\");\n }\n throw cause;\n }\n}\n\n/**\n * Get bastion info from SSM parameter store (legacy format).\n * Reads from /mesh/{tenant}/{platformEnv}/platform-bastion and extracts RDS info.\n *\n * @deprecated Use getPlatformBastionInfo instead\n */\nexport async function getBastionInfo(\n tenant: string,\n platformEnv: string\n): Promise<BastionInfo> {\n const info = await getPlatformBastionInfo(tenant, platformEnv);\n\n const rdsService = info.services[\"rds\"];\n if (!rdsService) {\n throw new Error(\"RDS service not available in platform bastion. Is RDS enabled?\");\n }\n\n return {\n instanceId: info.instanceId,\n rdsEndpoint: rdsService.host,\n rdsPort: rdsService.port,\n };\n}\n", "/**\n * Database credential utilities\n */\n\nimport {\n SecretsManagerClient,\n GetSecretValueCommand,\n} from \"@aws-sdk/client-secrets-manager\";\nimport { logInfo, logSuccess } from \"./log.js\";\n\nexport interface DatabaseCredentials {\n username: string;\n password: string;\n host: string;\n port: number;\n database: string;\n}\n\n/**\n * Options for credential lookup\n */\nexport interface CredentialLookupOptions {\n /** App name (e.g., \"rdc\") - if provided, uses path mesh/{tenant}/{stage}/{app}/db-credentials */\n app?: string;\n}\n\n/**\n * Get DATABASE_URL from Secrets Manager.\n *\n * Credential path patterns:\n * - With app: mesh/{tenant}/{stage}/{app}/db-credentials\n * - Without app: mesh/{tenant}/{stage}/db-credentials\n *\n * Returns the DATABASE_URL string directly. Use rewriteDatabaseUrl() to\n * modify host/port for tunnel usage.\n */\nexport async function getDatabaseUrl(\n tenant: string,\n stage: string,\n options?: CredentialLookupOptions\n): Promise<string> {\n const secretsManager = new SecretsManagerClient({});\n\n // Build secret path - with or without app name\n const secretName = options?.app\n ? `mesh/${tenant}/${stage}/${options.app}/db-credentials`\n : `mesh/${tenant}/${stage}/db-credentials`;\n logInfo(`Looking up credentials at ${secretName}...`);\n\n try {\n const response = await secretsManager.send(\n new GetSecretValueCommand({ SecretId: secretName })\n );\n\n if (response.SecretString) {\n const secret = JSON.parse(response.SecretString);\n\n // Handle DATABASE_URL format (preferred)\n if (secret.DATABASE_URL) {\n const parsed = new URL(secret.DATABASE_URL);\n logSuccess(`Got credentials for user: ${parsed.username}`);\n return secret.DATABASE_URL;\n }\n\n // Handle individual fields format (legacy)\n if (secret.username && secret.password) {\n logSuccess(`Got credentials for user: ${secret.username}`);\n const database = secret.dbname ?? secret.database ?? \"postgres\";\n return `postgresql://${secret.username}:${encodeURIComponent(secret.password)}@${secret.host ?? \"localhost\"}:${secret.port ?? 5432}/${database}`;\n }\n\n throw new Error(`Secret ${secretName} has unexpected format (needs DATABASE_URL or username/password)`);\n }\n } catch (error) {\n if ((error as Error).message?.includes(\"unexpected format\")) {\n throw error;\n }\n // Secret not found - will be caught by caller\n }\n\n throw new Error(`Could not find credentials at ${secretName}`);\n}\n\n/**\n * @deprecated Use getDatabaseUrl instead - returns DATABASE_URL directly\n */\nexport async function getDbCredentials(\n tenant: string,\n stage: string,\n _platformEnv: string,\n rdsHost: string,\n rdsPort: number,\n options?: CredentialLookupOptions\n): Promise<DatabaseCredentials> {\n const databaseUrl = await getDatabaseUrl(tenant, stage, options);\n const parsed = new URL(databaseUrl);\n\n return {\n username: parsed.username,\n password: decodeURIComponent(parsed.password),\n host: rdsHost,\n port: rdsPort,\n database: parsed.pathname.slice(1),\n };\n}\n\n/**\n * Options for rewriting DATABASE_URL\n */\nexport interface DatabaseUrlRewriteOptions {\n /** New host:port endpoint (e.g., \"localhost:5432\") */\n endpoint?: string;\n /** SSL mode (require, no-verify, disable) */\n sslMode?: string;\n}\n\n/**\n * Rewrite DATABASE_URL with new endpoint and/or SSL mode.\n * Preserves username, password, database name, and other query params.\n *\n * Used by both mesh-env-exec (for sst dev) and mesh db exec (for ad-hoc commands).\n */\nexport function rewriteDatabaseUrl(\n url: string,\n options: DatabaseUrlRewriteOptions\n): string {\n try {\n const parsed = new URL(url);\n\n // Rewrite endpoint if provided\n if (options.endpoint) {\n if (options.endpoint.includes(\":\")) {\n const colonIndex = options.endpoint.lastIndexOf(\":\");\n parsed.hostname = options.endpoint.slice(0, colonIndex);\n parsed.port = options.endpoint.slice(colonIndex + 1);\n } else {\n parsed.hostname = options.endpoint;\n parsed.port = parsed.port || \"5432\";\n }\n }\n\n // Set SSL mode if provided\n if (options.sslMode) {\n parsed.searchParams.set(\"sslmode\", options.sslMode);\n // For Prisma: accept invalid/self-signed certificates through tunnels\n if (options.sslMode === \"require\" || options.sslMode === \"no-verify\") {\n parsed.searchParams.set(\"sslaccept\", \"accept_invalid_certs\");\n }\n }\n\n return parsed.toString();\n } catch {\n // If URL parsing fails, return original\n return url;\n }\n}\n\n/**\n * Build a DATABASE_URL from credentials.\n */\nexport function buildDatabaseUrl(\n creds: DatabaseCredentials,\n options?: DatabaseUrlRewriteOptions\n): string {\n const host = options?.endpoint?.split(\":\")[0] ?? creds.host;\n const port = options?.endpoint?.split(\":\")[1] ?? String(creds.port);\n\n let url = `postgresql://${creds.username}:${encodeURIComponent(creds.password)}@${host}:${port}/${creds.database}`;\n\n if (options?.sslMode) {\n url += `?sslmode=${options.sslMode}`;\n if (options.sslMode === \"require\" || options.sslMode === \"no-verify\") {\n url += \"&sslaccept=accept_invalid_certs\";\n }\n }\n\n return url;\n}\n\n/**\n * Try to read database info from SST outputs (when sst dev has run).\n */\nexport async function readSstOutputs(): Promise<{\n databaseUrl?: string;\n databaseName?: string;\n secretArn?: string;\n} | null> {\n const fs = await import(\"fs\");\n\n if (!fs.existsSync(\".sst/outputs.json\")) {\n return null;\n }\n\n try {\n const content = fs.readFileSync(\".sst/outputs.json\", \"utf-8\");\n const outputs = JSON.parse(content);\n\n if (outputs.databaseUrl) {\n logInfo(\"Found SST outputs with database config\");\n\n // Extract secret ARN from URL if present\n const secretArnMatch = outputs.databaseUrl.match(/secretArn=([^&]+)/);\n const secretArn = secretArnMatch\n ? decodeURIComponent(secretArnMatch[1])\n : undefined;\n\n return {\n databaseUrl: outputs.databaseUrl,\n databaseName: outputs.databaseName,\n secretArn,\n };\n }\n } catch {\n // Ignore parse errors\n }\n\n return null;\n}\n", "/**\n * Pulumi-related utilities shared across CLI commands.\n */\n\nimport { execFileSync } from \"child_process\";\nimport * as path from \"path\";\nimport * as fs from \"fs\";\n\n/**\n * Find the Pulumi app root by walking up from a starting directory.\n * Returns the first directory containing `Pulumi.yaml`, or null.\n */\nexport function findAppRoot(startDir: string): string | null {\n let dir = startDir;\n while (true) {\n if (fs.existsSync(path.join(dir, \"Pulumi.yaml\"))) return dir;\n const parent = path.dirname(dir);\n if (parent === dir) return null;\n dir = parent;\n }\n}\n\n/**\n * Find Pulumi.<stack>.yaml files in a directory.\n * Returns an array of stack names (without the Pulumi. prefix and .yaml suffix).\n */\nexport function findStackConfigs(appRoot: string): string[] {\n return fs.readdirSync(appRoot)\n .filter((f) => /^Pulumi\\..+\\.yaml$/.test(f) && f !== \"Pulumi.yaml\")\n .map((f) => f.replace(/^Pulumi\\./, \"\").replace(/\\.yaml$/, \"\"));\n}\n\n/**\n * Get the currently selected Pulumi stack name, or null.\n */\nexport function getCurrentStack(appRoot: string): string | null {\n try {\n const result = execFileSync(\"pulumi\", [\"stack\", \"--show-name\"], {\n encoding: \"utf-8\",\n cwd: appRoot,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n return result.trim() || null;\n } catch {\n return null;\n }\n}\n\n/**\n * Read a config value from Pulumi.<stack>.yaml.\n * Simple regex-based parser \u2014 handles single-line string values.\n * For complex values, use `pulumi config` CLI instead.\n */\nexport function readStackConfig(appRoot: string, stack: string, key: string): string | null {\n const configFile = path.join(appRoot, `Pulumi.${stack}.yaml`);\n if (!fs.existsSync(configFile)) return null;\n\n const content = fs.readFileSync(configFile, \"utf-8\");\n const pattern = new RegExp(`^\\\\s+${key.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\")}:\\\\s*(.+)$`, \"m\");\n const match = content.match(pattern);\n if (!match) return null;\n\n return match[1]!.trim().replace(/^[\"']|[\"']$/g, \"\");\n}\n\n/**\n * Run `pulumi stack output <key> --json` with the given extra args.\n *\n * Pulumi redacts secret-tainted outputs as the literal string `\"[secret]\"`.\n * Outputs like `env.register()`'s `dev` blob are tainted because they transitively\n * include secret values (e.g. `TEMPORAL_ENCODING_KEY`, DB passwords), even though\n * much of the blob (tunnels, namespace, service scaffolding) is non-secret.\n *\n * This helper tries without `--show-secrets` first \u2014 which avoids requiring\n * the local machine to have the stack's secrets provider configured (KMS access\n * etc.) \u2014 and retries with `--show-secrets` only if the first call returns a\n * `\"[secret]\"` placeholder. KMS/secrets-provider errors are not retried because\n * they will fail the same way with the flag set.\n */\nexport function pulumiStackOutput(\n appRoot: string,\n key: string,\n extraArgs: string[],\n env?: Record<string, string>,\n): string {\n const execEnv = env ? { ...process.env, ...env } : undefined;\n // First attempt: no --show-secrets (works without PULUMI_CONFIG_PASSPHRASE / KMS)\n try {\n const result = execFileSync(\n \"pulumi\",\n [\"stack\", \"output\", key, \"--json\", ...extraArgs],\n { cwd: appRoot, encoding: \"utf-8\", stdio: [\"ignore\", \"pipe\", \"pipe\"], env: execEnv }\n );\n // If the output contains \"[secret]\" placeholders, retry with --show-secrets\n if (result.includes('\"[secret]\"')) {\n return execFileSync(\n \"pulumi\",\n [\"stack\", \"output\", key, \"--json\", \"--show-secrets\", ...extraArgs],\n { cwd: appRoot, encoding: \"utf-8\", stdio: [\"ignore\", \"pipe\", \"pipe\"], env: execEnv }\n );\n }\n return result;\n } catch (err: unknown) {\n // If the error is a secrets/KMS issue, don't retry with --show-secrets\n // (it will fail the same way). Only retry for other Pulumi errors.\n const errMsg = (err as { stderr?: string })?.stderr ?? \"\";\n if (errMsg.includes(\"kms:\") || errMsg.includes(\"KMS\") || errMsg.includes(\"secrets manager\")) {\n throw err;\n }\n return execFileSync(\n \"pulumi\",\n [\"stack\", \"output\", key, \"--json\", \"--show-secrets\", ...extraArgs],\n { cwd: appRoot, encoding: \"utf-8\", stdio: [\"ignore\", \"pipe\", \"pipe\"], env: execEnv }\n );\n }\n}\n", "/**\n * VPN detection utilities\n */\n\nimport { execFile, execFileSync } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nconst TAILSCALE_PATHS = [\n \"tailscale\",\n \"/Applications/Tailscale.app/Contents/MacOS/Tailscale\",\n];\n\n/**\n * Detect whether a Tailscale VPN connection is active.\n *\n * Uses socket-aware `execTailscaleCmd` so it works in both kernel tun mode\n * (standard socket) and legacy userspace networking (/tmp/tailscale.sock).\n * Returns `true` only when BackendState is \"Running\" and Self.Online is true.\n * Returns `false` silently on any failure (binary missing, daemon stopped,\n * parse error, missing fields).\n */\nexport async function isVpnConnected(): Promise<boolean> {\n try {\n const stdout = await execTailscaleCmd([\"status\", \"--json\"]);\n const status: TailscaleDetailedStatus = JSON.parse(stdout);\n return status.BackendState === \"Running\" && status.Self?.Online === true;\n } catch {\n return false;\n }\n}\n\n// ---------------------------------------------------------------------------\n// DNS record management & Tailscale info\n// ---------------------------------------------------------------------------\n\n/** Standard socket (kernel tun mode), then legacy (userspace mode). */\nconst TAILSCALE_SOCKET_PATHS = [\"/var/run/tailscale/tailscaled.sock\", \"/tmp/tailscale.sock\"];\n\n/** Connection details for the Headscale DNS writer sidecar. */\nexport interface HeadscaleDnsConfig {\n namespace: string;\n pod: string;\n container: string;\n filePath: string;\n}\n\n/**\n * Build a HeadscaleDnsConfig from tenant/env, following the same naming\n * convention as `mesh vpn` (\u2060{tenant}-{env}-headscale).\n *\n * Pod name, container, and file path are infrastructure conventions that\n * rarely change \u2014 override via the optional parameter if they do.\n */\nexport function headscaleDnsConfig(\n tenant = \"mesh\",\n env = \"dev\",\n overrides?: Partial<HeadscaleDnsConfig>,\n): HeadscaleDnsConfig {\n return {\n namespace: `${tenant}-${env}-headscale`,\n pod: \"headscale-0\",\n container: \"dns-writer\",\n filePath: \"/var/lib/headscale/dns/extra-records.json\",\n ...overrides,\n };\n}\n\nexport interface DnsRecord {\n name: string;\n type: \"A\";\n value: string;\n}\n\ninterface TailscaleDetailedStatus {\n BackendState?: string;\n Self?: {\n Online?: boolean;\n HostName?: string;\n TailscaleIPs?: string[];\n };\n}\n\n/**\n * Execute a tailscale CLI command, trying each known binary path.\n * Automatically appends `--socket <path>` when a tailscale socket is found.\n */\nfunction execTailscaleCmd(args: string[]): Promise<string> {\n const socketPath = TAILSCALE_SOCKET_PATHS.find(existsSync);\n\n interface Attempt {\n binary: string;\n args: string[];\n }\n\n const attempts: Attempt[] = [];\n for (const binary of TAILSCALE_PATHS) {\n if (socketPath) {\n attempts.push({ binary, args: [\"--socket\", socketPath, ...args] });\n }\n attempts.push({ binary, args });\n }\n\n return new Promise((resolve, reject) => {\n let index = 0;\n\n function tryNext(): void {\n if (index >= attempts.length) {\n reject(new Error(\"All tailscale binary attempts failed\"));\n return;\n }\n\n const attempt = attempts[index++]!;\n execFile(attempt.binary, attempt.args, (error, stdout) => {\n if (error) {\n tryNext();\n } else {\n resolve(stdout);\n }\n });\n }\n\n tryNext();\n });\n}\n\n/**\n * Retrieve the current Tailscale hostname and IP address.\n *\n * Returns `null` when Tailscale is not installed, not running, or not online.\n */\nexport async function getTailscaleInfo(): Promise<{ hostname: string; ip: string } | null> {\n try {\n const stdout = await execTailscaleCmd([\"status\", \"--json\"]);\n const status: TailscaleDetailedStatus = JSON.parse(stdout);\n\n if (\n status.BackendState === \"Running\" &&\n status.Self?.Online === true &&\n status.Self.HostName &&\n status.Self.TailscaleIPs?.length\n ) {\n return {\n hostname: status.Self.HostName,\n ip: status.Self.TailscaleIPs[0]!,\n };\n }\n\n return null;\n } catch {\n return null;\n }\n}\n\n/** Helper: build kubectl exec args for the dns-writer sidecar. */\nfunction dnsWriterExec(cfg: HeadscaleDnsConfig, cmd: string[], interactive = false): string[] {\n return [\n \"exec\", ...(interactive ? [\"-i\"] : []),\n \"-n\", cfg.namespace, cfg.pod, \"-c\", cfg.container, \"--\", ...cmd,\n ];\n}\n\n/**\n * Read DNS records from the dns-writer sidecar in the Headscale pod.\n *\n * Throws with an actionable message if kubectl can't reach the pod.\n * Returns an empty array when the file is missing or contains invalid JSON.\n */\nexport function readDnsRecords(cfg: HeadscaleDnsConfig): DnsRecord[] {\n try {\n const raw = execFileSync(\"kubectl\", dnsWriterExec(cfg, [\"cat\", cfg.filePath]), {\n encoding: \"utf-8\",\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n const trimmed = raw.trim();\n if (!trimmed || trimmed === \"[]\") return [];\n try {\n return JSON.parse(trimmed);\n } catch {\n console.warn(`[vpn] DNS records file contains invalid JSON, treating as empty`);\n return [];\n }\n } catch (err) {\n const msg = (err as Error).message ?? String(err);\n if (msg.includes(\"not found\") || msg.includes(\"Unable to connect\")) {\n throw new Error(\n `Cannot reach Headscale DNS writer (namespace=${cfg.namespace}, pod=${cfg.pod}).\\n` +\n `Verify kubectl context and that the Headscale pod is running:\\n` +\n ` kubectl get pods -n ${cfg.namespace}`,\n );\n }\n if (msg.includes(\"No such file\")) {\n return [];\n }\n // Unexpected error \u2014 rethrow\n throw err;\n }\n}\n\n/**\n * Write DNS A records to the dns-writer sidecar in the Headscale pod.\n *\n * Pipes JSON via stdin to avoid shell-escaping issues.\n * Throws with an actionable message if kubectl can't reach the pod.\n */\nexport function registerDnsRecords(cfg: HeadscaleDnsConfig, records: DnsRecord[]): void {\n const json = JSON.stringify(records);\n try {\n execFileSync(\n \"kubectl\",\n dnsWriterExec(cfg, [\"sh\", \"-c\", `cat > '${cfg.filePath}'`], true),\n { input: json, stdio: [\"pipe\", \"pipe\", \"pipe\"] },\n );\n } catch (err) {\n const msg = (err as Error).message ?? String(err);\n throw new Error(\n `Failed to write DNS records to Headscale (namespace=${cfg.namespace}, pod=${cfg.pod}).\\n` +\n `${msg.includes(\"not found\") ? \"Pod not found. \" : \"\"}` +\n `Verify kubectl context: kubectl get pods -n ${cfg.namespace}`,\n );\n }\n}\n\n/**\n * Remove DNS records whose `name` ends with `suffix` from the Headscale pod.\n * Best-effort: logs a warning on failure instead of throwing.\n */\nexport function unregisterDnsRecords(cfg: HeadscaleDnsConfig, suffix: string): void {\n try {\n const records = readDnsRecords(cfg);\n const filtered = records.filter((r) => !r.name.endsWith(suffix));\n registerDnsRecords(cfg, filtered);\n } catch {\n // Best-effort cleanup \u2014 silent on failure\n }\n}\n", "/**\n * Utility exports\n */\n\nexport * from \"./errors.js\";\nexport * from \"./log.js\";\nexport * from \"./context.js\";\nexport * from \"./bastion.js\";\nexport * from \"./credentials.js\";\nexport * from \"./pulumi.js\";\nexport * from \"./vpn.js\";\n", "/**\n * Guard for pids the CLI reads back rather than constructs.\n *\n * Every teardown path in the CLI signals a pid it recovered from somewhere:\n * `tunnel-state.json`, `runner.json`, `daemon.json`, or a `ps` argv scan. None\n * of those are trustworthy \u2014 a truncated write, a stale file from an older\n * build, or a hand-edited state dir can put any integer there. POSIX `kill(2)`\n * overloads the pid argument, so the wrong integer is not a no-op:\n *\n * - `kill(0, sig)` \u2192 every process in the CALLER'S OWN process group.\n * - `kill(-1, sig)` \u2192 every process the caller is permitted to signal.\n * - `kill(1, sig)` \u2192 init. And teardown negates before signalling, so a `1`\n * on disk becomes `kill(-1)` \u2014 the broadcast.\n *\n * That is not hypothetical: a `pid: -1` written by a unit test SIGTERM'd the\n * author's entire login session (tmux server, every pane, an in-flight\n * `mesh login`) on 2026-08-01. Refuse the input instead of signalling it.\n *\n * The guard is intentionally strict about the LOW end (`pid >= 2`) so the\n * NEGATED form used for process-group teardown is safe by construction: if\n * `pid >= 2` then `-pid <= -2`, which is always a real process group and never\n * `0` (own group) or `-1` (broadcast). Callers signalling `-pid` need no\n * second check \u2014 see `killSupervisor`.\n */\n\nimport { MeshCliError } from \"./errors.js\";\n\n/** Where a recovered pid came from, for the refusal message + remediation. */\nexport interface PidSource {\n /** What the pid claims to be, e.g. \"tunnel supervisor pid\". */\n what: string;\n /**\n * Absolute path of the state file it was read from, when there is one.\n * Present \u21D2 the refusal tells the user the exact file to delete, so a corrupt\n * state dir does not brick `mesh tunnel down` (which is the command that\n * would otherwise clear it).\n */\n file?: string;\n}\n\n/**\n * Lowest pid the CLI will ever signal. 0 and 1 are the two overloaded values;\n * anything below 0 is already a process-group id, not a pid.\n */\nconst MIN_SIGNALABLE_PID = 2;\n\n/**\n * Why `pid` must not be handed to `process.kill`, or null if it is signalable.\n * Pure \u2014 every branch is unit-testable without spawning anything.\n */\nfunction unsignalableReason(pid: unknown): string | null {\n if (typeof pid !== \"number\") {\n return `expected an integer, got ${typeof pid} (${String(pid)})`;\n }\n if (!Number.isInteger(pid)) {\n // NaN, \u00B1Infinity, and fractions all land here. Number.isInteger is the one\n // predicate that rejects every non-pid a JSON.parse can produce.\n return `expected an integer, got ${String(pid)}`;\n }\n if (pid === 0) {\n return \"0 is not a pid \u2014 kill(0) signals every process in this shell's own process group\";\n }\n if (pid === 1) {\n return \"1 is init \u2014 and teardown negates first, so kill(-1) would signal every process you can signal\";\n }\n if (pid < MIN_SIGNALABLE_PID) {\n return `${pid} is negative \u2014 that is already a process-group id, not a pid`;\n }\n if (pid === process.pid) {\n return `${pid} is this CLI process itself \u2014 signalling it (or its group) would kill the command doing the teardown`;\n }\n if (pid === process.ppid) {\n return `${pid} is this CLI's parent (your shell) \u2014 signalling its group would kill your terminal session`;\n }\n return null;\n}\n\n/**\n * Throw unless `pid` is safe to pass to `process.kill` (directly or negated).\n *\n * Call this at the top of any function that signals a pid it did not construct\n * itself. Existence checks (`process.kill(pid, 0)`) do not need it \u2014 signal 0\n * delivers nothing \u2014 but they gain nothing from skipping it either.\n *\n * @throws {MeshCliError} with `rm <file>` remediation when `source.file` is set.\n */\nexport function assertSignalablePid(pid: unknown, source: PidSource): void {\n const reason = unsignalableReason(pid);\n if (reason === null) return;\n // \"Corrupt or stale\" is only true when the pid was read back from a state\n // file. Call sites without one (e.g. reclaimPort's lsof-derived holder) get a\n // pid that is CORRECT \u2014 that is exactly why it is refused \u2014 so the causal\n // clause is gated on the same condition as the `rm` remediation.\n throw new MeshCliError(\n `Refusing to signal ${source.what} \u2014 ${reason}. ` +\n (source.file\n ? `The recorded value is corrupt or stale; signalling it could terminate unrelated processes.`\n : `Signalling it could terminate unrelated processes.`),\n source.file ? { remediation: { command: `rm ${source.file}` } } : {},\n );\n}\n", "import { getContextConfig, getValidToken } from \"../commands/login.js\";\n\ntype CtxConfig = { issuer?: string; vpnJoinBroker?: string } | null;\n\n/**\n * Resolve the broker URL, preferring the platform-published value from\n * discovery (ContextConfig.vpnJoinBroker) and falling back to DNS-convention\n * derivation for platforms not yet redeployed with the payload field.\n */\nexport function resolveVpnJoinBroker(\n context: string,\n getCfg: (c: string) => CtxConfig = getContextConfig,\n): string | null {\n const cfg = getCfg(context);\n if (cfg?.vpnJoinBroker) return cfg.vpnJoinBroker;\n return deriveVpnJoinBroker(context, getCfg);\n}\n\n/**\n * FALLBACK ONLY. Derive by convention \u2014 issuer host `identity.<env>.<domain>`\n * \u2192 `vpn-join.<env>.<domain>` \u2014 mirroring deriveLoginServer (dev.ts:1479).\n * Prefer resolveVpnJoinBroker, which reads the platform-published URL first.\n */\nexport function deriveVpnJoinBroker(\n context: string,\n getCfg: (c: string) => CtxConfig = getContextConfig,\n): string | null {\n const cfg = getCfg(context);\n if (!cfg?.issuer) return null;\n try {\n const u = new URL(cfg.issuer);\n const parts = u.hostname.split(\".\");\n parts[0] = \"vpn-join\";\n return `https://${parts.join(\".\")}`;\n } catch {\n return null;\n }\n}\n\nexport interface MintDeps {\n getValidToken: (context: string) => Promise<string | null>;\n fetchFn?: typeof fetch;\n}\n\n/**\n * Fetch a single-use pre-auth key from the broker. Returns null on ANY failure\n * (no token, non-2xx, network error) so the caller falls back to the browser\n * relay join \u2014 the broker path is strictly additive.\n */\nexport async function mintPreAuthKey(\n context: string,\n brokerUrl: string,\n deps: MintDeps,\n): Promise<{ authKey: string; loginServer: string } | null> {\n const token = await deps.getValidToken(context);\n if (!token) return null;\n const doFetch = deps.fetchFn ?? fetch;\n try {\n const res = await doFetch(`${brokerUrl}/preauth`, {\n method: \"POST\",\n headers: { authorization: `Bearer ${token}` },\n });\n if (!res.ok) return null;\n const body = (await res.json()) as { authKey?: string; loginServer?: string };\n if (!body.authKey) return null;\n return { authKey: body.authKey, loginServer: body.loginServer ?? \"\" };\n } catch {\n return null;\n }\n}\n\n// Convenience for production callers that use the real login.ts token source.\nexport function realMintDeps(): MintDeps {\n return { getValidToken: (c) => getValidToken(c) };\n}\n", "/**\n * The single credentialed-Pulumi chokepoint (MESH-2085).\n *\n * Every mesh command that shells `pulumi` against the S3 state backend needs\n * AWS credentials from the stack's `mesh:deployerRole`. Historically each\n * command re-implemented that glue and `mesh stack init` skipped it entirely\n * (\u2192 `NoCredentialProviders`). This module centralizes it:\n *\n * 1. read `mesh:deployerRole` from the stack config (clear error if absent),\n * 2. run a LOGIN PREFLIGHT (`probeCredentials`) that names the real problem\n * (\"run `mesh login --device`\") BEFORE pulumi is invoked \u2014 and before\n * `resolveAwsCredentials`' interactive path can hang a browser login over\n * SSH,\n * 3. resolve the deployer creds and return them as env vars to merge into the\n * `pulumi` child process.\n *\n * Callers thread the returned env into their existing `execFileSync(\"pulumi\", \u2026)`\n * calls (deploy passes it once; stack init reuses it across init/select/config).\n */\nimport { logError, logWarn } from \"./log.js\";\nimport { readStackConfig } from \"./pulumi.js\";\nimport { derivePlatformContext, resolveAwsCredentials } from \"./aws-auth.js\";\nimport { probeCredentials, type CredProbe } from \"../commands/login.js\";\n\n/**\n * Map a credential probe to a preflight message. Pure \u2014 no I/O \u2014 so the\n * remediation wording is unit-testable. `null` means \"proceed\" (`ok`, or a\n * non-fatal warning already surfaced). `fatal` callers should stop before\n * touching pulumi; non-fatal is a warning that lets the run continue.\n */\nexport function credProbeToPreflightError(\n probe: CredProbe,\n context: string,\n): { message: string; fatal: boolean } | null {\n switch (probe.state) {\n case \"ok\":\n return null;\n case \"no-session\":\n return {\n fatal: true,\n message:\n `Not logged in for ${context}. Run:\\n` +\n ` mesh login ${context} --device`,\n };\n case \"expired-session\":\n return {\n fatal: true,\n message:\n `Your mesh login session for ${context} expired. Run:\\n` +\n ` mesh login ${context} --device`,\n };\n case \"assume-denied\":\n return {\n fatal: true,\n message:\n `Logged in, but couldn't assume the deployer role \u2014 ${probe.detail}\\n` +\n ` Check mesh:deployerRole in the stack config and your IAM access.`,\n };\n case \"stale-env-override\":\n return {\n fatal: false,\n message:\n `Stale AWS_* env vars are set and will override your mesh login.\\n` +\n ` If pulumi fails with an auth error, clear them first:\\n` +\n ` unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN`,\n };\n }\n}\n\n/**\n * Resolve deployer AWS credentials for a `pulumi` invocation against `stack`,\n * with an up-front login preflight. Returns env vars to merge into the pulumi\n * child (`AWS_ACCESS_KEY_ID`/`_SECRET_ACCESS_KEY`/`_SESSION_TOKEN`). Exits the\n * process with a clear, actionable message on any hard failure \u2014 callers can\n * treat a return as \"creds are ready\".\n */\nexport async function resolvePulumiEnv(opts: {\n appRoot: string;\n stack: string;\n}): Promise<Record<string, string>> {\n const { appRoot, stack } = opts;\n\n const roleArn = readStackConfig(appRoot, stack, \"mesh:deployerRole\");\n if (!roleArn) {\n // Platform stacks are deployed by operators with ambient credentials\n // (SSO/exported env) and typically carry no mesh:deployerRole \u2014 only app\n // stacks do. With ambient creds present, run Pulumi against them directly.\n if (process.env.AWS_ACCESS_KEY_ID) {\n return {};\n }\n logError(\n `No mesh:deployerRole in Pulumi.${stack}.yaml \u2014 mesh needs it to assume a ` +\n `role for the Pulumi backend.\\n` +\n ` Set it (copy the value from a base stack), e.g.:\\n` +\n ` mesh deploy config set mesh:deployerRole arn:aws:iam::<account>:role/<tenant>-<stage>-apps-deployer --stack ${stack}\\n` +\n ` (or provide operator AWS credentials in the environment for platform stacks).`,\n );\n process.exit(1);\n }\n\n // Skip the login preflight whenever explicit ambient AWS credentials are\n // present \u2014 both the CI/OIDC case (key + session token) AND long-lived static\n // keys (key, no session token). Requiring a session token here regressed\n // static-key users: with no cached mesh session the probe returns `no-session`\n // \u2192 fatal, even though `resolveAwsCredentials`' ambient-SDK AssumeRole path\n // (which accepts a bare static key) would have worked. (MESH-2085 review.)\n const hasAmbientCreds = !!process.env.AWS_ACCESS_KEY_ID;\n const context = derivePlatformContext(appRoot, stack);\n if (!hasAmbientCreds && context) {\n const probe = await probeCredentials(context, roleArn);\n const preflight = credProbeToPreflightError(probe, context);\n if (preflight?.fatal) {\n logError(preflight.message);\n process.exit(1);\n }\n if (preflight) logWarn(preflight.message);\n }\n\n const resolved = await resolveAwsCredentials(roleArn, appRoot, stack);\n if (!resolved) {\n logError(\n `Failed to obtain AWS credentials for ${roleArn}.\\n` +\n (context ? ` Try: mesh login ${context} --device\\n` : \"\") +\n ` (or provide AWS credentials in the environment).`,\n );\n process.exit(1);\n }\n return { ...resolved.env };\n}\n", "/**\n * Turnkey kubeconfig for `mesh dev`.\n *\n * `mesh dev` shells out to `kubectl` (Temporal encoding-key read, temporal-pod\n * env fallback). Rather than depend on the operator's ambient ~/.kube/config\n * (which may be unset/stale, and which the apps-deployer role can't populate via\n * `aws eks update-kubeconfig` \u2014 it lacks `eks:DescribeCluster`), we build a\n * kubeconfig from the platform EKS cluster data in SSM and authenticate via\n * `aws eks get-token` (STS-only \u2014 needs just the cluster name).\n *\n * Mirrors the kubeconfig the Pulumi k8s provider builds in\n * `@mesh-tech/infra-components` AppEnvironment.buildExecKubeconfig.\n */\nimport * as fs from 'fs';\nimport * as os from 'os';\nimport * as path from 'path';\n\ninterface EksClusterData {\n clusterEndpoint: string;\n clusterCaData: string;\n clusterName: string;\n}\n\n/**\n * Build a kubeconfig YAML that authenticates to `cluster` via `aws eks get-token`.\n * Pure \u2014 no I/O. The `region` is for the get-token exec args (the active AWS\n * identity is whatever the process runs as: deployer / SSO / CI).\n */\nexport function buildKubeconfig(cluster: EksClusterData, region: string): string {\n return `apiVersion: v1\nkind: Config\nclusters:\n- cluster:\n server: ${cluster.clusterEndpoint}\n certificate-authority-data: ${cluster.clusterCaData}\n name: eks-cluster\ncontexts:\n- context:\n cluster: eks-cluster\n user: eks-user\n name: eks-context\ncurrent-context: eks-context\nusers:\n- name: eks-user\n user:\n exec:\n apiVersion: client.authentication.k8s.io/v1beta1\n command: aws\n args:\n - eks\n - get-token\n - --cluster-name\n - ${cluster.clusterName}\n - --region\n - ${region}\n`;\n}\n\n/**\n * Deterministic path of the session-scoped kubeconfig written by\n * {@link ensureKubeconfig}. Exposed so callers can point `KUBECONFIG` at the\n * last-good file when a fresh SSM re-resolve isn't available (e.g. on\n * `mesh dev restart --refresh-env`), rather than letting kubectl fall back to\n * `~/.kube/config`.\n */\nexport function sessionKubeconfigPath(sessionName: string): string {\n return path.join(os.tmpdir(), 'mesh-dev-sessions', `${sessionName}.kubeconfig`);\n}\n\n/** Why {@link ensureKubeconfig} couldn't resolve the cluster. */\nexport interface EnsureKubeconfigFailure {\n /** The SSM parameter name that was read (or attempted). */\n parameter: string;\n /** The exception thrown, or a synthetic Error for empty/malformed data. */\n error: unknown;\n}\n\nexport interface EnsureKubeconfigDeps {\n /** SSM GetParameter (decrypted value or undefined) \u2014 injectable for tests. */\n getParameter?: (name: string) => Promise<string | undefined>;\n /**\n * Invoked when cluster resolution fails, with the parameter tried and the\n * underlying error \u2014 so callers can say WHAT failed instead of guessing\n * \"check your SSM read access\" at the user (MESH-2515).\n */\n onError?: (failure: EnsureKubeconfigFailure) => void;\n}\n\n/**\n * The HUB platform name for platform-level resource lookups (EKS export,\n * bastion). `platform.name` in the dev output is the hub (e.g. \"trabian\");\n * when absent \u2014 outputs predating the field \u2014 fall back to the default hub\n * \"mesh\", NEVER to the app tenant. This one definition pins the axis that\n * regressed in the original MESH-2515 bug.\n */\nexport function resolveHubPlatformName(\n platform: { name?: string; tenant?: string; env?: string } | undefined,\n): string {\n return platform?.name ?? 'mesh';\n}\n\nasync function ssmGetParameter(name: string): Promise<string | undefined> {\n const { SSMClient, GetParameterCommand } = await import('@aws-sdk/client-ssm');\n const ssm = new SSMClient({ region: process.env.AWS_REGION || 'us-east-2' });\n const resp = await ssm.send(new GetParameterCommand({ Name: name, WithDecryption: true }));\n return resp.Parameter?.Value;\n}\n\n/**\n * Resolve the hub EKS cluster from SSM and write a session-scoped kubeconfig.\n *\n * Reads `/mesh-platform/{platformName}/{env}/core/eks` \u2014 platform-level cluster\n * data lives under the app's HUB platform (`platform.name` in the dev output,\n * e.g. \"trabian\"; \"mesh\" is only the default hub, MESH-2515). Writes to\n * `${tmpdir}/mesh-dev-sessions/{sessionName}.kubeconfig` (never touches\n * ~/.kube/config). Returns the path, or `null` if the cluster data can't be\n * resolved (best-effort \u2014 the caller continues without it; the failure detail\n * goes to `deps.onError`).\n */\nexport async function ensureKubeconfig(\n platformName: string,\n env: string,\n sessionName: string,\n deps: EnsureKubeconfigDeps = {},\n): Promise<string | null> {\n const parameter = `/mesh-platform/${platformName}/${env}/core/eks`;\n const getParameter = deps.getParameter ?? ssmGetParameter;\n\n let cluster: EksClusterData;\n try {\n const value = await getParameter(parameter);\n if (!value) throw new Error('parameter is empty or missing');\n const parsed = JSON.parse(value) as Partial<EksClusterData>;\n if (!parsed.clusterEndpoint || !parsed.clusterCaData || !parsed.clusterName) {\n throw new Error('cluster data is missing clusterEndpoint/clusterCaData/clusterName');\n }\n cluster = {\n clusterEndpoint: parsed.clusterEndpoint,\n clusterCaData: parsed.clusterCaData,\n clusterName: parsed.clusterName,\n };\n } catch (error) {\n deps.onError?.({ parameter, error });\n return null;\n }\n\n const region = process.env.AWS_REGION || 'us-east-2';\n const kubeconfigPath = sessionKubeconfigPath(sessionName);\n if (!fs.existsSync(path.dirname(kubeconfigPath))) {\n fs.mkdirSync(path.dirname(kubeconfigPath), { recursive: true });\n }\n fs.writeFileSync(kubeconfigPath, buildKubeconfig(cluster, region), { mode: 0o600 });\n return kubeconfigPath;\n}\n", "/**\n * Temporal auth resolution for the mesh CLI.\n *\n * Two responsibilities, kept together because they're always used as a pair:\n * 1. `resolveTemporalAuth` \u2014 discover the M2M client_credentials + Zitadel\n * issuer/project for a tenant/env from SSM (with a kubectl pod-env fallback).\n * This is what `mesh dev` injects into worker/service env.\n * 2. `acquireTemporalBearer` \u2014 exchange those credentials for a Zitadel Bearer\n * JWT via the OAuth2 client_credentials grant, so CLI commands that talk to\n * an auth-enforcing Temporal frontend (describe/history/terminate) can attach\n * `authorization: Bearer <token>` gRPC metadata. Without it the server's\n * MeshAuthorizer denies calls with \"Request unauthorized\".\n *\n * The token fetch is intentionally reimplemented here (not imported from\n * `@mesh-tech/app-kit`, which mirrors it) because app-kit *depends on* mesh-cli \u2014\n * importing it back would create a dependency cycle.\n */\n\nimport { execFileSync } from \"node:child_process\";\nimport { logSuccess, logWarn } from \"./log.js\";\n\n/**\n * Discover Temporal M2M credentials + Zitadel issuer/project for a tenant/env.\n *\n * Returns an env-var-shaped record (TEMPORAL_AUTH_CLIENT_ID/SECRET,\n * ZITADEL_ISSUER, ZITADEL_PROJECT_ID, \u2026). Missing pieces are simply absent \u2014\n * callers decide whether what resolved is enough to mint a token.\n *\n * `platformName` keys the Zitadel issuer lookup and is the platform NAME\n * (e.g. \"trabian\"/\"mesh\"), NOT the app tenant \u2014 getting it wrong means the\n * issuer never resolves, so no Bearer, so Temporal denies with \"Request\n * unauthorized\".\n */\nexport async function resolveTemporalAuth(\n tenant: string,\n env: string,\n platformName: string = tenant,\n): Promise<Record<string, string>> {\n const { SSMClient, GetParameterCommand } = await import(\"@aws-sdk/client-ssm\");\n const ssm = new SSMClient({ region: process.env.AWS_REGION || \"us-east-2\" });\n\n const results: Record<string, string> = {};\n\n // Each SSM lookup is independent so a missing optional parameter\n // (e.g. token-exchange-app) doesn't prevent other credentials from resolving.\n async function trySSM(name: string): Promise<string | undefined> {\n try {\n const resp = await ssm.send(new GetParameterCommand({ Name: name, WithDecryption: true }));\n return resp.Parameter?.Value ?? undefined;\n } catch {\n return undefined;\n }\n }\n\n try {\n // \u2500\u2500 Scheme 1: Zitadel-managed per-tenant credentials \u2500\u2500\n const workerPath = `/mesh-platform/${tenant}/${env}/temporal/worker-service-account-key`;\n const exchangePath = `/mesh-platform/${tenant}/${env}/temporal/token-exchange-app`;\n\n const workerJson = await trySSM(workerPath);\n if (workerJson) {\n const worker = JSON.parse(workerJson) as { clientId: string; clientSecret: string };\n results.TEMPORAL_AUTH_CLIENT_ID = worker.clientId;\n results.TEMPORAL_AUTH_CLIENT_SECRET = worker.clientSecret;\n }\n\n // Token exchange app credentials (optional \u2014 not all tenants have this)\n const exchangeJson = await trySSM(exchangePath);\n if (exchangeJson) {\n const exchange = JSON.parse(exchangeJson) as { clientId: string; clientSecret: string };\n results.ZITADEL_TOKEN_EXCHANGE_CLIENT_ID = exchange.clientId;\n results.ZITADEL_TOKEN_EXCHANGE_CLIENT_SECRET = exchange.clientSecret;\n }\n\n // Zitadel issuer URL and project ID from the PLATFORM's config, keyed by the\n // platform NAME (not the app tenant, not a hardcoded \"mesh\").\n const platformJson = await trySSM(`/mesh-platform/${platformName}/${env}/platform/zitadel`);\n if (platformJson) {\n const platform = JSON.parse(platformJson) as { endpoint?: string; projectId?: string };\n if (platform.endpoint) results.ZITADEL_ISSUER = platform.endpoint;\n if (platform.projectId) results.ZITADEL_PROJECT_ID = platform.projectId;\n }\n\n // \u2500\u2500 Scheme 2: Legacy shared credentials (fallback) \u2500\u2500\n if (!results.TEMPORAL_AUTH_CLIENT_ID) {\n const legacyClientId = await trySSM(\"/platform/temporal/auth/CLIENT_ID\");\n const legacyClientSecret = await trySSM(\"/platform/temporal/auth/CLIENT_SECRET\");\n if (legacyClientId && legacyClientSecret) {\n results.TEMPORAL_AUTH_CLIENT_ID = legacyClientId;\n results.TEMPORAL_AUTH_CLIENT_SECRET = legacyClientSecret;\n }\n }\n\n // \u2500\u2500 Discover Zitadel config from Temporal server pods (final fallback) \u2500\u2500\n if (!results.ZITADEL_ISSUER) {\n try {\n const podEnv = execFileSync(\n \"kubectl\",\n [\n \"get\",\n \"pods\",\n \"-n\",\n `temporal-${env}`,\n \"-l\",\n \"app.kubernetes.io/component=frontend\",\n \"-o\",\n \"jsonpath={.items[0].spec.containers[0].env}\",\n ],\n { encoding: \"utf-8\", timeout: 10_000, stdio: [\"pipe\", \"pipe\", \"pipe\"] },\n ).trim();\n\n if (podEnv) {\n const envVars = JSON.parse(podEnv) as Array<{ name: string; value?: string }>;\n for (const v of envVars) {\n if (v.name === \"ZITADEL_ISSUER_URL\" && v.value && !results.ZITADEL_ISSUER) {\n results.ZITADEL_ISSUER = v.value;\n }\n if (v.name === \"ZITADEL_PROJECT_ID\" && v.value && !results.ZITADEL_PROJECT_ID) {\n results.ZITADEL_PROJECT_ID = v.value;\n }\n }\n }\n } catch (err) {\n const detail = err instanceof Error ? err.message : String(err);\n const stderr = String((err as { stderr?: unknown })?.stderr ?? \"\");\n if (/\\.kube[/\\\\]config|error loading config file/i.test(`${detail} ${stderr}`)) {\n logWarn(\n \"kubectl could not read a kubeconfig and fell back to ~/.kube/config \" +\n \"(macOS blocks it for shells without Full Disk Access). Run inside the \" +\n \"mesh dev tmux session, or export KUBECONFIG=$TMPDIR/mesh-dev-sessions/<session>.kubeconfig.\",\n );\n }\n }\n }\n\n if (results.TEMPORAL_AUTH_CLIENT_ID && results.ZITADEL_ISSUER) {\n logSuccess(`Temporal auth resolved (client: ${results.TEMPORAL_AUTH_CLIENT_ID})`);\n } else if (Object.keys(results).length > 0) {\n logWarn(\"Partial Temporal auth resolved (some credentials missing)\");\n }\n } catch (err) {\n logWarn(\n `Could not resolve Temporal auth from SSM: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n\n return results;\n}\n\n/**\n * Exchange resolved M2M credentials for a Zitadel Bearer access token via the\n * OAuth2 client_credentials grant. Reads from the passed record first, then the\n * ambient env (which `mesh dev` may already have populated).\n *\n * Returns `undefined` when credentials are incomplete \u2014 the caller then connects\n * unauthenticated (correct for local/non-enforcing Temporal servers).\n *\n * Mirrors `@mesh-tech/app-kit`'s `acquireToken` (kept in sync deliberately; see\n * the module doc for why it isn't imported).\n */\nexport async function acquireTemporalBearer(\n vars: Record<string, string | undefined> = {},\n): Promise<string | undefined> {\n const issuerUrl = vars.ZITADEL_ISSUER ?? process.env.ZITADEL_ISSUER;\n const projectId = vars.ZITADEL_PROJECT_ID ?? process.env.ZITADEL_PROJECT_ID;\n const clientId = vars.TEMPORAL_AUTH_CLIENT_ID ?? process.env.TEMPORAL_AUTH_CLIENT_ID;\n const clientSecret = vars.TEMPORAL_AUTH_CLIENT_SECRET ?? process.env.TEMPORAL_AUTH_CLIENT_SECRET;\n\n if (!issuerUrl || !clientId || !clientSecret) {\n return undefined;\n }\n\n const scopes = [\"openid\"];\n if (projectId) {\n scopes.push(`urn:zitadel:iam:org:project:id:${projectId}:aud`);\n // Request project roles in the token (MeshAuthorizer Path A). Same env gate\n // as app-kit: skipping the roles scope falls back to client_id parsing\n // (Path B), which currently also yields the reader bit.\n if (process.env.TEMPORAL_M2M_SKIP_ROLES_SCOPE !== \"true\") {\n scopes.push(\"urn:zitadel:iam:org:projects:roles\");\n }\n }\n\n const response = await fetch(`${issuerUrl}/oauth/v2/token`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({\n grant_type: \"client_credentials\",\n client_id: clientId,\n client_secret: clientSecret,\n scope: scopes.join(\" \"),\n }),\n });\n\n if (!response.ok) {\n const text = await response.text();\n throw new Error(\n `Temporal token acquisition failed: ${response.status} ${response.statusText} \u2014 ${text}`,\n );\n }\n\n const data = (await response.json()) as { access_token: string };\n return data.access_token;\n}\n", "/**\n * TCP reachability probe for transport selection.\n *\n * `mesh dev`'s VPN detection is otherwise a *presence* check \u2014 it asks whether a\n * Tailscale/VPN connection exists, not whether the mesh VPC actually routes. On a\n * machine using Tailscale for SSH (but not the mesh Headscale VPN) that presence\n * check returns true, `mesh dev` picks \"VPN-direct\", and the worker then dies with\n * `DnsResolutionError` / `ECONNREFUSED` on the Temporal frontend. Dialing the\n * endpoint before committing to VPN-direct turns that tribal-knowledge failure\n * into an automatic SSM fallback (MESH-2016).\n */\nimport { createConnection } from \"node:net\";\n\n/**\n * Resolve `true` if a TCP connection to `host:port` completes within\n * `timeoutMs`, else `false`. Never rejects \u2014 any failure (timeout, refused, DNS)\n * is a `false`, since for transport selection \"can't reach it\" is the only signal\n * that matters. The socket is always destroyed.\n */\nexport function probeTcpReachable(host: string, port: number, timeoutMs = 1500): Promise<boolean> {\n return new Promise((resolve) => {\n let settled = false;\n const socket = createConnection({ host, port });\n const finish = (ok: boolean) => {\n if (settled) return;\n settled = true;\n socket.destroy();\n resolve(ok);\n };\n socket.setTimeout(timeoutMs);\n socket.once(\"connect\", () => finish(true));\n socket.once(\"timeout\", () => finish(false));\n socket.once(\"error\", () => finish(false));\n });\n}\n\n/**\n * Resolve `true` if a connection to `host:port` completes AND survives a brief\n * grace window (`holdMs`). Stronger than {@link probeTcpReachable} for probing a\n * LOCAL FORWARDER port, where \"the port accepts\" is not proof the tunnel carries\n * traffic: a forwarder (SSM port-forward, or the userspace-Tailscale SOCKS\n * bridge) binds its local port even when its upstream leg is dead \u2014 so a plain\n * connect succeeds while nothing flows. A dead-upstream forwarder accepts the\n * TCP connection and then tears it down SYNCHRONOUSLY (e.g. the Tailscale bridge\n * dials a SOCKS port the daemon isn't on and destroys the client \u2014 MESH-2169);\n * measured, that teardown lands in ~1ms.\n *\n * The window is deliberately SMALL \u2014 just enough to clear that ~1ms fail-fast\n * teardown. It is NOT a latency budget for the upstream: a real upstream need\n * send no bytes and may itself idle-close a bare connection (Temporal's UI drops\n * an idle HTTP connection at ~50ms; Temporal gRPC and Postgres hold indefinitely).\n * So \"closed within ~1ms of connecting\" means the forwarder never reached a real\n * upstream; surviving `holdMs` means it did. A larger window would mis-report a\n * healthy-but-idle-closing service (like the Temporal UI) as DOWN. Never rejects;\n * the socket is always destroyed.\n */\nexport function probeConnectionHolds(\n host: string,\n port: number,\n timeoutMs = 800,\n holdMs = 25,\n): Promise<boolean> {\n return new Promise((resolve) => {\n let settled = false;\n let holdTimer: ReturnType<typeof setTimeout> | undefined;\n const socket = createConnection({ host, port });\n const finish = (ok: boolean) => {\n if (settled) return;\n settled = true;\n if (holdTimer) clearTimeout(holdTimer);\n socket.destroy();\n resolve(ok);\n };\n socket.setTimeout(timeoutMs);\n // Healthy iff the connection survives the grace window after connecting.\n socket.once(\"connect\", () => {\n holdTimer = setTimeout(() => finish(true), holdMs);\n });\n // Closed before the grace window elapsed \u2192 the forwarder's upstream is dead.\n socket.once(\"close\", () => finish(false));\n socket.once(\"timeout\", () => finish(false));\n socket.once(\"error\", () => finish(false));\n });\n}\n", "/**\n * Workflow-source fingerprint for relaunch safety (MESH-2017).\n *\n * A `mesh dev` relaunch (or `restart <worker>`) restarts the Temporal worker onto\n * whatever code is current. If the WORKFLOW code changed since the session\n * started, in-flight conversations replay against the new code and \u2014 if the change\n * is replay-incompatible \u2014 get stranded (observed: conversation 523a4103). The\n * replay-safety gate (MESH-2091) catches this at CI; this catches it at the *local*\n * dev loop, where uncommitted edits haven't been through CI.\n *\n * We fingerprint the source the agent/interpreter worker bundles into Temporal\n * workflows: the workflow packages agent-sdk, workflow-interpreter, agent-contracts\n * (the same set the CI replay-gate path filter covers). A content hash (not mtime)\n * so a `git checkout`/rebase that rewrites mtimes without changing content doesn't\n * produce a false \"code changed\" warning; paths are hashed repo-root-relative so\n * moving/renaming the checkout doesn't either.\n *\n * NOTE (MESH-2017 follow-up): this covers the shared workflow packages, not a\n * tenant repo's own worker source \u2014 `workflowSourceDirs` accepts extra dirs for\n * that, but no caller wires them yet, so in a repo without those packages the\n * fingerprint is empty and the guard is inert. Tracked separately.\n */\nimport { createHash } from \"node:crypto\";\nimport { existsSync, readFileSync, readdirSync } from \"node:fs\";\nimport { dirname, isAbsolute, join, relative } from \"node:path\";\n\n/**\n * Workspace packages whose src the agent/interpreter worker bundles as workflows.\n * MUST stay a subset of the CI replay-gate path filter (`checks.yaml` \u2192\n * `replay-changes`); a drift-guard test asserts it (MESH-2093).\n */\nexport const WORKFLOW_PACKAGE_DIRS = [\n \"packages/agent-sdk/src\",\n \"packages/workflow-interpreter/src\",\n \"packages/agent-contracts/src\",\n];\n\nconst EXCLUDE = /(^|\\/)(node_modules|dist|__tests__)(\\/|$)|\\.(test|spec)\\.[cm]?tsx?$/;\n\n/**\n * Walk up from `startDir` to the monorepo root (the dir with pnpm-workspace.yaml).\n * Falls back to `startDir` if none is found.\n */\nexport function findRepoRoot(startDir: string): string {\n let dir = startDir;\n for (;;) {\n if (existsSync(join(dir, \"pnpm-workspace.yaml\"))) return dir;\n const parent = dirname(dir);\n if (parent === dir) return startDir;\n dir = parent;\n }\n}\n\n/**\n * The set of directories whose `.ts` the worker turns into Temporal workflows.\n *\n * Prefers the shared workflow **packages** (agent-sdk / interpreter / contracts)\n * when they exist \u2014 the precise, low-noise signal for the monorepo agent/interpreter\n * dev loop. When they're absent (a **tenant repo**), falls back to the app's own\n * worker source (`extraDirs`) so the guard isn't silently inert there (MESH-2093).\n * Only existing dirs are returned.\n */\nexport function workflowSourceDirs(repoRoot: string, extraDirs: string[] = []): string[] {\n const pkgDirs = WORKFLOW_PACKAGE_DIRS.map((d) => join(repoRoot, d)).filter((d) => existsSync(d));\n if (pkgDirs.length > 0) return pkgDirs;\n return extraDirs.filter((d) => existsSync(d));\n}\n\n/**\n * Resolve the worker service(s)' source dirs from a dev-output `services` map, so a\n * tenant repo (no shared workflow packages) still fingerprints the code its worker\n * actually runs. A service is a worker when its name matches `/worker/i` (best\n * effort until dev-output carries a `type: \"temporal-worker\"` marker \u2014 MESH-2093).\n */\nexport function resolveWorkerSourceDirs(\n repoRoot: string,\n services: Record<string, { src?: string }> = {},\n): string[] {\n const dirs: string[] = [];\n for (const [name, svc] of Object.entries(services)) {\n if (/worker/i.test(name) && svc?.src) {\n dirs.push(isAbsolute(svc.src) ? svc.src : join(repoRoot, svc.src));\n }\n }\n return dirs;\n}\n\n/**\n * Content fingerprint of every non-test `.ts`/`.tsx` under `dirs`. Stable across\n * runs for identical content; changes iff a workflow source file's content\n * changes. Returns a short hex digest ('' if no files).\n *\n * Each file is labelled by its path relative to `relativeTo` (when given) so the\n * hash is stable across checkout location/renames; falls back to the absolute path\n * otherwise.\n */\nexport function computeWorkflowFingerprint(dirs: string[], relativeTo?: string): string {\n const files: string[] = [];\n for (const dir of dirs) {\n let rels: string[];\n try {\n rels = readdirSync(dir, { recursive: true }) as string[];\n } catch {\n continue; // dir removed mid-scan\n }\n for (const rel of rels) {\n const p = String(rel);\n if (/\\.(ts|tsx)$/.test(p) && !EXCLUDE.test(p)) files.push(join(dir, p));\n }\n }\n files.sort();\n if (files.length === 0) return \"\";\n const h = createHash(\"sha256\");\n for (const f of files) {\n try {\n const content = readFileSync(f);\n h.update(relativeTo ? relative(relativeTo, f) : f);\n h.update(\"\\0\");\n h.update(content);\n h.update(\"\\0\");\n } catch {\n /* unreadable/removed mid-scan \u2014 skip */\n }\n }\n return h.digest(\"hex\").slice(0, 16);\n}\n\n/**\n * Convenience: fingerprint an app's workflow source. Pass the dev-output `services`\n * map so a tenant repo falls back to its worker source when the shared workflow\n * packages aren't present.\n */\nexport function fingerprintWorkflowSource(\n appRoot: string,\n services: Record<string, { src?: string }> = {},\n): string {\n const repoRoot = findRepoRoot(appRoot);\n const workerDirs = resolveWorkerSourceDirs(repoRoot, services);\n return computeWorkflowFingerprint(workflowSourceDirs(repoRoot, workerDirs), repoRoot);\n}\n", "/**\n * Helpers for launching `mesh dev` services via per-session env files.\n *\n * Background: `mesh dev` used to inline every env var into a single giant\n * `env K1=V1 K2=V2 \u2026 <command>` string passed to `tmux send-keys`. With large\n * values (system prompts, encoding keys, OAuth creds) tmux intermittently\n * truncated the string \u2014 the service never started \u2014 and `mesh dev restart`\n * re-derived the env from scratch, drifting from what the service was\n * originally launched with (e.g. a different TEMPORAL_ENCODING_KEY).\n *\n * Instead, the full env is written once at launch to a 0600 file under the\n * session state dir, and the send-keys command is just:\n *\n * cd '<dir>' && source '<envfile>' && <command>\n *\n * Restart sources the SAME file, guaranteeing a byte-identical environment.\n */\n\nimport * as fs from 'fs';\nimport * as net from 'net';\nimport * as path from 'path';\n\n/** Env files contain secrets \u2014 owner read/write only. */\nexport const ENV_FILE_MODE = 0o600;\n\n/** Valid POSIX env var name. Anything else is rejected to avoid shell injection. */\nconst ENV_KEY_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;\n\n/**\n * Single-quote a value for POSIX shells (bash/zsh), escaping embedded\n * single quotes via the standard `'\\''` dance. Safe for newlines, spaces,\n * `$`, backticks, etc.\n */\nexport function quoteShellValue(value: string): string {\n return `'${value.replace(/'/g, \"'\\\\''\")}'`;\n}\n\n/**\n * Render a sourceable env file: one `export K='V'` per line.\n * Throws on env var names that aren't valid shell identifiers.\n */\nexport function renderEnvFile(env: Record<string, string>): string {\n const lines: string[] = [\n '# Auto-generated by mesh dev \u2014 do not edit.',\n '# Sourced by service launch/restart commands; this file IS the',\n \"# session's env contract for the service (restart fidelity).\",\n ];\n for (const [key, value] of Object.entries(env)) {\n if (!ENV_KEY_RE.test(key)) {\n throw new Error(`Invalid env var name for env file: ${JSON.stringify(key)}`);\n }\n lines.push(`export ${key}=${quoteShellValue(value)}`);\n }\n return lines.join('\\n') + '\\n';\n}\n\n/** Filesystem-safe env file name for a service. */\nexport function envFileName(serviceName: string): string {\n return `${serviceName.replace(/[^A-Za-z0-9._-]/g, '-')}.env.sh`;\n}\n\n/**\n * Write the env file (creating parent dirs) with mode 0600.\n * chmod is applied explicitly so a pre-existing file is tightened too.\n */\nexport function writeEnvFile(filePath: string, env: Record<string, string>): void {\n fs.mkdirSync(path.dirname(filePath), { recursive: true });\n fs.writeFileSync(filePath, renderEnvFile(env), { mode: ENV_FILE_MODE });\n fs.chmodSync(filePath, ENV_FILE_MODE);\n}\n\n/**\n * Build the short, untruncatable command sent to tmux:\n * cd '<dir>' && source '<envfile>' && <command>\n *\n * `command` is the service's dev command (already shell syntax) and is\n * passed through verbatim.\n *\n * With `logShipper` (mesh dev --local: the path of assets/log-shipper.mjs),\n * the service's combined stdout/stderr is piped through the shipper: raw\n * bytes go to the pane (its stderr), ANSI-stripped lines ship to the local\n * platform's OTel collector via OTLP \u2014 the same ingestion path instrumented\n * apps use, carrying the OTEL_* resource attributes from the env file. Logs\n * never cross the macOS Docker file mount (whose stale attribute caching\n * hides appends from in-container tailers).\n */\nexport function buildLaunchCommand(\n envFilePath: string,\n dir: string,\n command: string,\n logShipper?: string,\n): string {\n const base = `cd ${quoteShellValue(dir)} && source ${quoteShellValue(envFilePath)} && `;\n if (!logShipper) return `${base}${command}`;\n // NODE_OPTIONS= : the shipper must not inherit the service's OTel\n // auto-instrumentation \u2014 its own OTLP POSTs would show up as traces.\n return `${base}{ ${command}; } 2>&1 | NODE_OPTIONS= node ${quoteShellValue(logShipper)}`;\n}\n\n/**\n * Poll until a TCP port accepts connections, or the timeout elapses.\n * Returns true when the port accepted, false on timeout.\n */\nexport async function waitForPort(\n host: string,\n port: number,\n timeoutMs: number,\n intervalMs = 500,\n): Promise<boolean> {\n const deadline = Date.now() + timeoutMs;\n\n // Always attempt at least once, even with a zero/negative timeout.\n for (;;) {\n const remaining = deadline - Date.now();\n const attemptTimeout = Math.max(250, Math.min(1000, remaining));\n if (await tryConnect(host, port, attemptTimeout)) return true;\n if (Date.now() + intervalMs >= deadline) return false;\n await new Promise((resolve) => setTimeout(resolve, intervalMs));\n }\n}\n\nfunction tryConnect(host: string, port: number, timeoutMs: number): Promise<boolean> {\n return new Promise((resolve) => {\n const socket = net.connect({ host, port });\n const done = (ok: boolean) => {\n socket.removeAllListeners();\n socket.destroy();\n resolve(ok);\n };\n socket.setTimeout(timeoutMs);\n socket.once('connect', () => done(true));\n socket.once('timeout', () => done(false));\n socket.once('error', () => done(false));\n });\n}\n", "/**\n * First-boot seeding for the `mesh start` local platform.\n *\n * Registers tenant `local` / env `dev` in the local AWS fabric's (ministack)\n * SSM registry with the same shape TenantEnvironments writes in the cloud\n * (/mesh-platform/{tenant}/{env}/app-tenants \u2192 TenantEnvironmentsExports), and\n * creates the tenant artifacts bucket. Idempotent \u2014 parameters are overwritten,\n * the bucket create tolerates \"already owned by you\".\n *\n * Zitadel org/project/CLI-app + test-user seeding (the `mesh login local`\n * path) is tracked as a follow-up on the mesh start epic.\n */\n\nimport { logInfo, logSuccess } from \"../../utils/log.js\";\nimport { MeshCliError } from \"../../utils/errors.js\";\n\nexport const LOCAL_TENANT = \"local\";\nexport const LOCAL_ENV = \"dev\";\nexport const LOCAL_AWS_ENDPOINT = \"http://localhost:4566\";\nexport const LOCAL_AWS_REGION = \"us-east-2\";\nexport const ARTIFACTS_BUCKET = \"mesh-local-artifacts\";\nexport const APP_TENANTS_PARAM = `/mesh-platform/${LOCAL_TENANT}/${LOCAL_ENV}/app-tenants`;\n\nexport const LOCAL_AWS_CONFIG = {\n endpoint: LOCAL_AWS_ENDPOINT,\n region: LOCAL_AWS_REGION,\n credentials: { accessKeyId: \"test\", secretAccessKey: \"test\" },\n};\nconst AWS_CONFIG = LOCAL_AWS_CONFIG;\n\n/**\n * Env vars that point any AWS SDK process on the host at the local fabric \u2014\n * the SDK-native endpoint override (AWS_ENDPOINT_URL, supported since SDK JS\n * v3 ~3.428), so no client-code changes are needed. `mesh dev` local mode\n * injects these into app processes; humans can `eval` them from the\n * `mesh start` output. In-network services get the same wiring with\n * http://ministack:4566 (see the compose file's x-local-aws-env anchor).\n */\nexport function localAwsEnv(): Record<string, string> {\n return {\n AWS_ENDPOINT_URL: LOCAL_AWS_ENDPOINT,\n AWS_REGION: LOCAL_AWS_REGION,\n AWS_ACCESS_KEY_ID: \"test\",\n AWS_SECRET_ACCESS_KEY: \"test\",\n };\n}\n\n/**\n * The local tenant registration, shaped like TenantEnvironmentsExports\n * (libs/infra-components \u2026/platform/TenantEnvironments.ts) so consumers of the\n * registry (Hub API, init checks) read local and cloud identically. AWS-only\n * fields carry inert local placeholders.\n */\nexport function buildAppTenantsSeed() {\n const tenantExport = {\n albGroupName: LOCAL_TENANT,\n certificateArn: \"\",\n baseDomain: \"localhost\",\n deployerRoleArn: \"arn:aws:iam::000000000000:role/local-dev-deployer\",\n artifactsBucket: ARTIFACTS_BUCKET,\n spicedb: {\n endpoint: \"localhost:50051\",\n presharedKeySecret: \"local-dev-key\",\n },\n zitadel: {\n orgId: \"local\",\n domain: \"localhost:8080\",\n issuer: \"http://localhost:8080\",\n },\n };\n return {\n hubTenant: LOCAL_TENANT,\n primaryTenant: tenantExport,\n sharedTenants: {},\n };\n}\n\nexport interface SeedResult {\n parameter: string;\n bucket: string;\n}\n\nexport const FABRIC_CHECK_PATH = `/mesh-platform/${LOCAL_TENANT}/${LOCAL_ENV}/.fabric-check`;\n\n/** The tenant's Temporal namespace, matching the cloud convention\n * TemporalNamespaceProvisioner uses ({tenant}-{env}, e.g. \"acme-dev\"). */\nexport const TEMPORAL_NAMESPACE = `${LOCAL_TENANT}-${LOCAL_ENV}`;\nexport const TEMPORAL_ADDRESS = \"localhost:7233\";\n\n/**\n * Register the local tenant's Temporal namespace ({tenant}-{env} \u2014 the same\n * name TemporalNamespaceProvisioner would create in the cloud). Idempotent:\n * \"already exists\" is success. Dynamic import \u2014 @temporalio/client is an\n * optionalDependency (same pattern as commands/temporal.ts).\n */\nexport async function seedTemporalNamespace(): Promise<void> {\n await ensureTemporalNamespace(\n TEMPORAL_NAMESPACE,\n `Mesh local tenant '${LOCAL_TENANT}' env '${LOCAL_ENV}' (seeded by mesh start)`,\n );\n}\n\n/**\n * Idempotently register a Temporal namespace. `mesh dev --local` uses this\n * for the per-app namespaces ({tenant}-{env}-{app}) the cloud provisioner\n * creates \u2014 the Hub's per-app workflow views resolve exactly that name.\n */\nexport async function ensureTemporalNamespace(namespace: string, description?: string): Promise<void> {\n const { Connection } = await import(\"@temporalio/client\");\n const connection = await Connection.connect({ address: TEMPORAL_ADDRESS });\n try {\n await connection.workflowService.registerNamespace({\n namespace,\n description: description ?? `Mesh local namespace '${namespace}'`,\n // protobufjs accepts plain numbers for int64 at runtime; the generated\n // typing insists on Long (whose package isn't a direct dep), hence any.\n workflowExecutionRetentionPeriod: { seconds: (3 * 24 * 60 * 60) as any },\n });\n // A freshly registered namespace isn't usable until the frontend's\n // namespace cache refreshes (~10s) \u2014 a worker connecting immediately\n // would die on \"Namespace not found\". Wait it out once, here.\n logInfo(`Registered Temporal namespace '${namespace}' \u2014 waiting for it to become active\u2026`);\n const deadline = Date.now() + 20_000;\n while (Date.now() < deadline) {\n try {\n await connection.workflowService.describeTaskQueue({\n namespace,\n taskQueue: { name: \"namespace-propagation-probe\" },\n taskQueueType: 1,\n } as any);\n break;\n } catch {\n await new Promise((resolve) => setTimeout(resolve, 1_000));\n }\n }\n logSuccess(`Temporal namespace '${namespace}' is active`);\n } catch (err: any) {\n if (err?.name === \"NamespaceAlreadyExistsError\" || /already exists/i.test(err?.message ?? \"\")) {\n logInfo(`Temporal namespace '${namespace}' already exists`);\n } else {\n throw err;\n }\n } finally {\n await connection.close();\n }\n}\n\n/**\n * A deterministic >4 KB payload for the Advanced-tier round-trip. Standard\n * SSM params cap at 4 KB; mesh.exports.Export writes tier \"Advanced\" values\n * up to 8 KB (Export.ts), and the emulator's fidelity there is the one open\n * question the design (\u00A72.5) requires this check to answer on every boot.\n */\nexport function buildFabricCheckPayload(targetBytes = 8_000): string {\n const base = { probe: \"advanced-tier-round-trip\", tenant: LOCAL_TENANT, env: LOCAL_ENV, pad: \"\" };\n const overhead = JSON.stringify(base).length;\n return JSON.stringify({ ...base, pad: \"x\".repeat(Math.max(0, targetBytes - overhead)) });\n}\n\n/**\n * Verify the local AWS fabric behaves like real SSM where the platform\n * depends on it: an 8 KB Advanced-tier parameter round-trips intact, and\n * child parameters under a path come back via GetParametersByPath (the\n * shape mesh.exports.Export's splitKeys mode reads). Check params are\n * removed afterwards.\n */\nexport async function verifyFabric(): Promise<void> {\n const { SSMClient, PutParameterCommand, GetParameterCommand, GetParametersByPathCommand, DeleteParametersCommand } =\n await import(\"@aws-sdk/client-ssm\");\n const ssm = new SSMClient(AWS_CONFIG);\n const payload = buildFabricCheckPayload();\n const mainParam = FABRIC_CHECK_PATH;\n const childParams = [`${FABRIC_CHECK_PATH}/vpc`, `${FABRIC_CHECK_PATH}/eks`];\n\n try {\n await ssm.send(\n new PutParameterCommand({\n Name: mainParam,\n Type: \"String\",\n Tier: \"Advanced\",\n Overwrite: true,\n Value: payload,\n }),\n );\n for (const name of childParams) {\n await ssm.send(\n new PutParameterCommand({ Name: name, Type: \"String\", Overwrite: true, Value: `{\"probe\":\"${name}\"}` }),\n );\n }\n\n const roundTrip = await ssm.send(new GetParameterCommand({ Name: mainParam }));\n if (roundTrip.Parameter?.Value !== payload) {\n throw new MeshCliError(\n `Local AWS fabric failed the ${payload.length}-byte Advanced-tier SSM round-trip (got ${roundTrip.Parameter?.Value?.length ?? 0} bytes back).`,\n {\n remediation: {\n docs: \"libs/mesh-cli/stack/docker-compose.yml \u2014 swap the ministack image for motoserver/moto (design \u00A72.5 fallback)\",\n },\n },\n );\n }\n\n const byPath = await ssm.send(\n new GetParametersByPathCommand({ Path: FABRIC_CHECK_PATH, Recursive: true }),\n );\n const returned = new Set((byPath.Parameters ?? []).map((p) => p.Name));\n const missing = childParams.filter((name) => !returned.has(name));\n if (missing.length > 0) {\n throw new MeshCliError(\n `Local AWS fabric's GetParametersByPath missed child parameter(s): ${missing.join(\", \")} (splitKeys exports would not resolve).`,\n {\n remediation: {\n docs: \"libs/mesh-cli/stack/docker-compose.yml \u2014 swap the ministack image for motoserver/moto (design \u00A72.5 fallback)\",\n },\n },\n );\n }\n\n logSuccess(`Fabric check passed: ${payload.length}-byte Advanced-tier round-trip + GetParametersByPath`);\n } finally {\n await ssm\n .send(new DeleteParametersCommand({ Names: [mainParam, ...childParams] }))\n .catch(() => {});\n }\n}\n\n/** Write the Hub-readable tenant + environment registrations (the shapes\n * hub-api's SSM assembler requires: RawTenant at /{tenant}, RawEnvironment\n * at /{tenant}/{env}). Exported for reuse by app-tenant provisioning. */\nexport async function registerTenantEnv(\n tenant: string,\n opts: { tier?: \"hub\" | \"dedicated\" | \"shared\" } = {},\n): Promise<void> {\n const { SSMClient, PutParameterCommand } = await import(\"@aws-sdk/client-ssm\");\n const ssm = new SSMClient(AWS_CONFIG);\n await ssm.send(\n new PutParameterCommand({\n Name: `/mesh-platform/${tenant}`,\n Type: \"String\",\n Overwrite: true,\n Value: JSON.stringify({ name: tenant, tier: opts.tier ?? \"shared\", subdomain: tenant }),\n Description: `Tenant registration (seeded by mesh CLI, local platform)`,\n }),\n );\n await ssm.send(\n new PutParameterCommand({\n Name: `/mesh-platform/${tenant}/${LOCAL_ENV}`,\n Type: \"String\",\n Overwrite: true,\n Value: JSON.stringify({\n env: LOCAL_ENV,\n region: LOCAL_AWS_REGION,\n baseDomain: \"localhost\",\n // monitoring is true: the local stack runs the same Loki/Tempo/\n // Prometheus backends the hosted platform provides.\n services: { temporal: true, zitadel: true, monitoring: true },\n }),\n Description: `Environment registration (seeded by mesh CLI, local platform)`,\n }),\n );\n}\n\nexport async function seedLocalPlatform(): Promise<SeedResult> {\n const { SSMClient, PutParameterCommand } = await import(\"@aws-sdk/client-ssm\");\n const ssm = new SSMClient(AWS_CONFIG);\n await ssm.send(\n new PutParameterCommand({\n Name: APP_TENANTS_PARAM,\n Type: \"String\",\n Overwrite: true,\n Value: JSON.stringify(buildAppTenantsSeed()),\n Description: `TenantEnvironments exports for ${LOCAL_TENANT}-${LOCAL_ENV} (seeded by mesh start)`,\n }),\n );\n await registerTenantEnv(LOCAL_TENANT, { tier: \"hub\" });\n logSuccess(`Registered tenant '${LOCAL_TENANT}' env '${LOCAL_ENV}' \u2192 ${APP_TENANTS_PARAM}`);\n\n const { S3Client, CreateBucketCommand } = await import(\"@aws-sdk/client-s3\");\n const s3 = new S3Client({ ...AWS_CONFIG, forcePathStyle: true });\n try {\n await s3.send(new CreateBucketCommand({ Bucket: ARTIFACTS_BUCKET }));\n logSuccess(`Created artifacts bucket s3://${ARTIFACTS_BUCKET}`);\n } catch (err: any) {\n if (err?.name === \"BucketAlreadyOwnedByYou\" || err?.name === \"BucketAlreadyExists\") {\n logInfo(`Artifacts bucket s3://${ARTIFACTS_BUCKET} already exists`);\n } else {\n throw err;\n }\n }\n\n await seedTemporalNamespace();\n\n return { parameter: APP_TENANTS_PARAM, bucket: ARTIFACTS_BUCKET };\n}\n", "/**\n * Small shared helpers for the local-platform commands \u2014 extracted from the\n * copies that had grown in auth-provision/mocks (secret upsert) and\n * dev-local/stack (TCP probe).\n */\n\nimport * as net from \"net\";\nimport { LOCAL_AWS_CONFIG } from \"./seed.js\";\n\n/** The subset of SecretsManagerClient upsertLocalSecret depends on. */\nexport interface SecretsSender {\n send(command: unknown): Promise<unknown>;\n}\n\n/**\n * Create-or-update a Secrets Manager secret in the local AWS fabric\n * (ministack). Create first; on ResourceExistsException, put a new value.\n * `client` is injectable for tests; defaults to a client against the local\n * fabric.\n */\nexport async function upsertLocalSecret(\n secretId: string,\n value: Record<string, string>,\n client?: SecretsSender,\n): Promise<void> {\n const { SecretsManagerClient, CreateSecretCommand, PutSecretValueCommand } = await import(\n \"@aws-sdk/client-secrets-manager\"\n );\n const sm = client ?? new SecretsManagerClient(LOCAL_AWS_CONFIG);\n const secretString = JSON.stringify(value);\n try {\n await sm.send(new CreateSecretCommand({ Name: secretId, SecretString: secretString }));\n } catch (err: any) {\n if (err?.name === \"ResourceExistsException\") {\n await sm.send(new PutSecretValueCommand({ SecretId: secretId, SecretString: secretString }));\n } else {\n throw err;\n }\n }\n}\n\n/** True when a TCP connect to host:port succeeds within timeoutMs. */\nexport function probeTcp(\n port: number,\n opts: { host?: string; timeoutMs?: number } = {},\n): Promise<boolean> {\n const { host = \"127.0.0.1\", timeoutMs = 2000 } = opts;\n return new Promise((resolve) => {\n const socket = net.connect({ host, port, timeout: timeoutMs });\n socket.once(\"connect\", () => {\n socket.destroy();\n resolve(true);\n });\n socket.once(\"error\", () => resolve(false));\n socket.once(\"timeout\", () => {\n socket.destroy();\n resolve(false);\n });\n });\n}\n", "/**\n * Helpers for the `mesh start/stop/status` full-local platform stack.\n *\n * The docker compose project (name `mesh-local`) ships inside the CLI package\n * at `<package root>/stack/`, so the stack works in any repo with only Docker\n * installed and is version-locked to the CLI.\n */\n\nimport { execFileSync, spawn, spawnSync } from \"child_process\";\nimport * as fs from \"fs\";\nimport { probeTcp } from \"./helpers.js\";\nimport * as os from \"os\";\nimport * as path from \"path\";\nimport { fileURLToPath } from \"url\";\nimport { parse as parseYaml } from \"yaml\";\nimport { MeshCliError } from \"../../utils/errors.js\";\nimport { startHeartbeat } from \"../../utils/log.js\";\n\nexport const COMPOSE_PROJECT = \"mesh-local\";\n\n/**\n * Host directory `mesh dev --local` writes service logs into\n * ({namespace}/{service}.log). The stack's OTel collector tails it (filelog\n * receiver) and ships to Loki with the hosted k8s_* label scheme, so the\n * Hub's logs view works on local runs unchanged.\n */\nexport function localLogsDir(): string {\n const dir = path.join(os.homedir(), \".cache\", \"mesh\", \"mesh-local\", \"logs\");\n fs.mkdirSync(dir, { recursive: true });\n return dir;\n}\n\n/**\n * Host directory holding blackbox probe targets (Prometheus file_sd JSON) \u2014\n * written by `mesh dev --externals` for external services, mounted into the\n * stack's Prometheus. The local analog of the hosted Probe CRs.\n */\nexport function localProbesDir(): string {\n const dir = path.join(os.homedir(), \".cache\", \"mesh\", \"mesh-local\", \"probes\");\n fs.mkdirSync(dir, { recursive: true });\n return dir;\n}\n\n/** Endpoints the local stack exposes on the host. */\nexport interface StackEndpoint {\n service: string;\n label: string;\n url: string;\n /** How `mesh status` probes it from the host */\n probe: { kind: \"http\"; url: string } | { kind: \"tcp\"; port: number } | { kind: \"none\" };\n /** Extra hint printed under the endpoint (credentials, tokens, \u2026) */\n hint?: string;\n}\n\nexport const STACK_ENDPOINTS: StackEndpoint[] = [\n {\n service: \"temporal\",\n label: \"Temporal gRPC\",\n url: \"localhost:7233\",\n probe: { kind: \"tcp\", port: 7233 },\n },\n {\n service: \"temporal-ui\",\n label: \"Temporal UI\",\n url: \"http://localhost:8233/namespaces/local-dev/workflows\",\n probe: { kind: \"http\", url: \"http://localhost:8233\" },\n hint: \"seeded namespace: local-dev\",\n },\n {\n service: \"zitadel\",\n label: \"Zitadel console\",\n url: \"http://localhost:8080\",\n probe: { kind: \"http\", url: \"http://localhost:8080/debug/healthz\" },\n hint: \"admin@local.mesh / LocalDev1!\",\n },\n {\n service: \"database\",\n label: \"Postgres\",\n url: \"postgres://postgres:postgres@localhost:5433\",\n probe: { kind: \"tcp\", port: 5433 },\n hint: \"databases: temporal, app, spicedb, hub\",\n },\n {\n service: \"spicedb\",\n label: \"SpiceDB gRPC\",\n url: \"localhost:50051\",\n probe: { kind: \"tcp\", port: 50051 },\n hint: \"preshared key: local-dev-key\",\n },\n {\n service: \"ministack\",\n label: \"ministack (local AWS endpoint)\",\n url: \"http://localhost:4566\",\n probe: { kind: \"http\", url: \"http://localhost:4566/_ministack/health\" },\n hint: \"SSM registry under /mesh-platform/local/dev\",\n },\n {\n service: \"stackport\",\n label: \"StackPort (local AWS console)\",\n url: \"http://localhost:4567\",\n probe: { kind: \"http\", url: \"http://localhost:4567\" },\n hint: \"browse the registry (SSM), secrets, S3 artifacts\",\n },\n {\n service: \"memcached\",\n label: \"Memcached\",\n url: \"localhost:11211\",\n probe: { kind: \"tcp\", port: 11211 },\n },\n {\n service: \"loki\",\n label: \"Loki (logs)\",\n url: \"http://localhost:3100\",\n probe: { kind: \"http\", url: \"http://localhost:3100/ready\" },\n hint: \"mesh dev --local service logs, hosted label scheme\",\n },\n {\n service: \"tempo\",\n label: \"Tempo (traces)\",\n url: \"http://localhost:3200\",\n probe: { kind: \"http\", url: \"http://localhost:3200/ready\" },\n },\n {\n service: \"prometheus\",\n label: \"Prometheus (metrics)\",\n url: \"http://localhost:9090\",\n probe: { kind: \"http\", url: \"http://localhost:9090/-/ready\" },\n },\n {\n service: \"otel-collector\",\n label: \"OTel collector (OTLP in)\",\n url: \"http://localhost:4318\",\n probe: { kind: \"http\", url: \"http://localhost:13133\" },\n hint: \"apps: OTEL_EXPORTER_OTLP_ENDPOINT (injected by mesh dev --local)\",\n },\n {\n service: \"elasticsearch\",\n label: \"OpenSearch (Temporal visibility)\",\n url: \"http://localhost:9200\",\n probe: { kind: \"http\", url: \"http://localhost:9200\" },\n },\n];\n\n/** Default host port for the containerized local Hub. `mesh hub dev` derives\n * its dev-server default from this too (hub/index.ts), so the two Hubs share\n * one source for \"9000\" while keeping separate override variables\n * (MESH_HUB_PORT here, MESH_HUB_DEV_PORT there). */\nexport const DEFAULT_HUB_PORT = \"9000\";\n\n/**\n * Host port the Hub is published on (docker-compose.hub.yml binds\n * `${MESH_HUB_PORT:-9000}:4180`). Override with MESH_HUB_PORT to run the\n * local Hub beside another process that owns 9000 \u2014 e.g. a hub-ui dev\n * server running from a different checkout. Export it for BOTH `mesh start`\n * and later `mesh status` calls: the compose file and these probes read the\n * same variable (MESH-2256 tracks deriving it from the running stack so\n * `mesh status` stops depending on shell hygiene). `mesh start` reconciles\n * the seeded Zitadel Hub app's redirect URIs to include the chosen port \u2014\n * Zitadel requires every redirect URI to be registered even in devMode\n * (devMode only allows http).\n *\n * Empty string falls back like compose's `${MESH_HUB_PORT:-9000}` does \u2014\n * `??` alone would diverge (probe `:`, publish 9000).\n */\nexport function hubPort(): string {\n const raw = process.env.MESH_HUB_PORT?.trim();\n if (!raw) return DEFAULT_HUB_PORT;\n if (!/^\\d+$/.test(raw) || Number(raw) < 1 || Number(raw) > 65535) {\n throw new MeshCliError(`MESH_HUB_PORT must be a TCP port number 1\u201365535 (got '${raw}').`, {\n remediation: { command: \"unset MESH_HUB_PORT # or export a valid port, e.g. 9100\" },\n });\n }\n return raw;\n}\n\n/** Hub overlay endpoints \u2014 probed only when the hub containers exist.\n * A function (not a module constant) so hubPort() is read at call time:\n * the CLI's env is fixed before node starts, but tests and programmatic\n * callers set MESH_HUB_PORT after import. */\nexport function hubEndpoints(): StackEndpoint[] {\n return [\n {\n service: \"hub-api\",\n label: \"Hub API\",\n url: \"http://localhost:4568\",\n probe: { kind: \"http\", url: \"http://localhost:4568/health\" },\n },\n {\n service: \"hub-ui\",\n label: \"Hub UI\",\n url: `http://localhost:${hubPort()}`,\n probe: { kind: \"http\", url: `http://localhost:${hubPort()}/ping` },\n hint: \"sign in: admin@local.mesh or dev@local.mesh / LocalDev1! (oauth2-proxy, same as deployed)\",\n },\n ];\n}\n\n/**\n * Locate the CLI package root (the directory whose package.json is\n * @mesh-tech/mesh-cli). Works from both the compiled layout (dist/src/\u2026)\n * and the source layout (src/\u2026 under tsx).\n */\nexport function findPackageRoot(startDir?: string): string {\n let dir = startDir ?? path.dirname(fileURLToPath(import.meta.url));\n for (let i = 0; i < 8; i++) {\n const pkgPath = path.join(dir, \"package.json\");\n if (fs.existsSync(pkgPath)) {\n try {\n const pkg = JSON.parse(fs.readFileSync(pkgPath, \"utf-8\"));\n if (pkg.name === \"@mesh-tech/mesh-cli\") return dir;\n } catch {\n // unreadable package.json \u2014 keep walking\n }\n }\n const parent = path.dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n throw new MeshCliError(\"Could not locate the mesh-cli package root (stack assets missing).\", {\n remediation: { command: \"npm install -g @mesh-tech/mesh-cli\" },\n });\n}\n\nexport function stackDir(): string {\n const dir = path.join(findPackageRoot(), \"stack\");\n if (!fs.existsSync(path.join(dir, \"docker-compose.yml\"))) {\n throw new MeshCliError(`Local stack assets not found at ${dir}.`, {\n remediation: { command: \"npm install -g @mesh-tech/mesh-cli\" },\n });\n }\n return dir;\n}\n\n/** The compose overlay that declares the Hub services. */\nexport const HUB_OVERLAY_FILE = \"docker-compose.hub.yml\";\n\n/** Top-level service names a compose file declares. Pure \u2014 takes the file text. */\nexport function parseComposeServiceNames(yamlText: string): string[] {\n const doc = parseYaml(yamlText) as { services?: Record<string, unknown> } | null;\n return Object.keys(doc?.services ?? {});\n}\n\nlet hubOverlayServicesCache: ReadonlySet<string> | undefined;\n\n/**\n * The services the Hub overlay \u2014 and only the overlay \u2014 declares.\n *\n * Read from `docker-compose.hub.yml` rather than hard-coded beside\n * ONE_SHOT_SERVICES on purpose: a second name list rots the moment the\n * overlay gains or renames a service. (It already declares three \u2014 hub-api,\n * hub-ui, hub-auth \u2014 not the two the Hub is usually described by.)\n */\nexport function hubOverlayServices(): ReadonlySet<string> {\n if (!hubOverlayServicesCache) {\n const file = path.join(stackDir(), HUB_OVERLAY_FILE);\n if (!fs.existsSync(file)) {\n throw new MeshCliError(`Local stack assets are incomplete: ${file} is missing.`, {\n remediation: { command: \"npm install -g @mesh-tech/mesh-cli\" },\n });\n }\n hubOverlayServicesCache = new Set(parseComposeServiceNames(fs.readFileSync(file, \"utf-8\")));\n }\n return hubOverlayServicesCache;\n}\n\n/**\n * The compose project is a MACHINE-WIDE singleton (`mesh-local`), but any\n * checkout of the CLI can drive it \u2014 and `docker compose up` from a checkout\n * whose stack config differs will recreate shared containers out from under\n * whatever else is running against the stack (a second project's `mesh dev`\n * session, a Hub built from another worktree, \u2026).\n *\n * Returns the working dir of the checkout that last (re)created the running\n * stack when it is NOT this one; undefined when the stack isn't running or\n * is already owned here. Callers gate lifecycle commands on it.\n */\nexport function stackOwnedElsewhere(): string | undefined {\n // Fail-open by design: a stack that exists but is NOT running (`ps -q`\n // without -a) has nothing to disrupt, so `start` silently re-owns it; and\n // any docker/inspect hiccup disables the guard rather than blocking\n // legitimate lifecycle commands.\n try {\n const first = compose([\"ps\", \"-q\"]).trim().split(\"\\n\").filter(Boolean)[0];\n if (!first) return undefined;\n const label = execFileSync(\n \"docker\",\n [\"inspect\", first, \"--format\", '{{ index .Config.Labels \"com.docker.compose.project.working_dir\" }}'],\n { encoding: \"utf-8\" },\n ).trim();\n if (!label) return undefined;\n // realpath both sides: symlinked layouts (macOS /tmp \u2192 /private/tmp,\n // linked worktree parents) must not make the same physical dir compare\n // as foreign. Fall back to the raw path when realpath fails (dir gone).\n const real = (p: string) => {\n try {\n return fs.realpathSync(p);\n } catch {\n return path.resolve(p);\n }\n };\n return real(label) === real(stackDir()) ? undefined : label;\n } catch {\n return undefined;\n }\n}\n\n/** Throw a remediated error if the docker daemon isn't reachable. */\nexport function ensureDockerAvailable(): void {\n const probe = spawnSync(\"docker\", [\"info\", \"--format\", \"{{.ServerVersion}}\"], {\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n if (probe.error || probe.status !== 0) {\n throw new MeshCliError(\"Docker is not available (is Docker Desktop / the docker daemon running?).\", {\n remediation: { docs: \"https://docs.docker.com/get-docker/\" },\n });\n }\n}\n\n/** Run `docker compose` against the packaged stack. `hub` adds the Hub\n * overlay file (safe for ps/logs/down: services simply may not exist);\n * `env` adds process-env overrides (e.g. MESH_HUB_VERSION). */\nexport function compose(\n args: string[],\n opts: { inherit?: boolean; hub?: boolean; env?: Record<string, string> } = {},\n): string {\n const dir = stackDir();\n const files = [\"-f\", path.join(dir, \"docker-compose.yml\")];\n if (opts.hub) files.push(\"-f\", path.join(dir, \"docker-compose.hub.yml\"));\n const fullArgs = [\"compose\", \"-p\", COMPOSE_PROJECT, ...files, ...args];\n return execFileSync(\"docker\", fullArgs, {\n cwd: dir,\n encoding: \"utf-8\",\n // MESH_LOCAL_LOGS on every call: the compose file mounts it into the\n // OTel collector, and an unset variable would both warn and resolve to\n // a different mount (recreate churn between CLI and raw compose runs).\n // IGNORE_ORPHANS: base-only `up` calls would otherwise flag the hub\n // overlay's running containers as orphans.\n env: {\n ...process.env,\n MESH_LOCAL_LOGS: localLogsDir(),\n MESH_LOCAL_PROBES: localProbesDir(),\n COMPOSE_IGNORE_ORPHANS: \"1\",\n ...opts.env,\n },\n stdio: opts.inherit ? [\"ignore\", \"inherit\", \"inherit\"] : [\"ignore\", \"pipe\", \"pipe\"],\n }) as unknown as string;\n}\n\n/**\n * Pick the one line worth reading out of a failed compose run's output:\n * the last error-looking line, else the last non-empty line (MESH-2479).\n * Pure so the selection heuristic is unit-testable.\n */\nexport function summarizeComposeFailure(output: string): string {\n const lines = output\n .split(\"\\n\")\n .map((l) => l.trim())\n .filter(Boolean);\n const errorish = lines.filter((l) =>\n /\\b(error|failed|failure|fatal|denied|unauthorized|cannot|no such)\\b/i.test(l),\n );\n const line = errorish.at(-1) ?? lines.at(-1) ?? \"no output captured\";\n return line.length > 300 ? `${line.slice(0, 297)}\u2026` : line;\n}\n\n/** Where a lifecycle command's full compose output is written (per operation). */\nexport function composeLogPath(op: string): string {\n const dir = path.join(os.homedir(), \".cache\", \"mesh\", \"mesh-local\");\n fs.mkdirSync(dir, { recursive: true });\n return path.join(dir, `compose-${op.replace(/[^a-z0-9-]/gi, \"_\")}.log`);\n}\n\n/**\n * `docker compose` for lifecycle commands (`up -d`): stream output like\n * `compose({inherit: true})` does, but never bury the failure \u2014 on a non-zero\n * exit throw a one-line summary instead of leaving ~200 lines of pull/create\n * noise as the only signal (MESH-2479). In non-TTY runs the output is also\n * teed to a log file (named in the error) and a heartbeat fills long quiet\n * stretches; interactive terminals keep docker's own progress rendering.\n */\nexport async function composeStreamed(\n args: string[],\n opts: { hub?: boolean; env?: Record<string, string> } = {},\n): Promise<void> {\n const dir = stackDir();\n const files = [\"-f\", path.join(dir, \"docker-compose.yml\")];\n if (opts.hub) files.push(\"-f\", path.join(dir, \"docker-compose.hub.yml\"));\n const fullArgs = [\"compose\", \"-p\", COMPOSE_PROJECT, ...files, ...args];\n const env = {\n ...process.env,\n MESH_LOCAL_LOGS: localLogsDir(),\n MESH_LOCAL_PROBES: localProbesDir(),\n COMPOSE_IGNORE_ORPHANS: \"1\",\n ...opts.env,\n };\n const op = args[0] ?? \"cmd\";\n\n if (process.stderr.isTTY) {\n const res = spawnSync(\"docker\", fullArgs, {\n cwd: dir,\n env,\n stdio: [\"ignore\", \"inherit\", \"inherit\"],\n });\n if (res.status !== 0) {\n throw new MeshCliError(\n `docker compose ${op} failed (exit ${res.status ?? \"?\"}) \u2014 the compose output above has the details.`,\n {\n remediation: {\n command: `docker compose -p ${COMPOSE_PROJECT} ps && docker compose -p ${COMPOSE_PROJECT} logs --tail 50`,\n },\n },\n );\n }\n return;\n }\n\n const logPath = composeLogPath(op);\n const logStream = fs.createWriteStream(logPath);\n const heartbeat = startHeartbeat(`docker compose ${args.join(\" \")}`);\n let captured = \"\";\n let exitCode: number;\n try {\n exitCode = await new Promise<number>((resolve, reject) => {\n const child = spawn(\"docker\", fullArgs, {\n cwd: dir,\n env,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n const consume = (chunk: Buffer) => {\n heartbeat.touch();\n const text = chunk.toString();\n captured += text;\n logStream.write(text);\n process.stderr.write(text);\n };\n child.stdout.on(\"data\", consume);\n child.stderr.on(\"data\", consume);\n child.on(\"error\", reject);\n child.on(\"close\", (code) => resolve(code ?? 1));\n });\n } finally {\n heartbeat.stop();\n // Flush the log file before any throw can reach handleCliError's\n // process.exit(), which doesn't wait for pending writes.\n await new Promise<void>((resolve) => logStream.end(resolve));\n }\n if (exitCode !== 0) {\n throw new MeshCliError(\n `docker compose ${op} failed (exit ${exitCode}): ${summarizeComposeFailure(captured)}`,\n {\n remediation: {\n command: `docker compose -p ${COMPOSE_PROJECT} logs --tail 50`,\n docs: logPath,\n },\n },\n );\n }\n}\n\nexport interface ServiceStatus {\n name: string;\n state: string;\n health?: string;\n}\n\n/** Parse `docker compose ps --format json` (NDJSON, one object per line). */\nexport function parseComposePs(output: string): ServiceStatus[] {\n const services: ServiceStatus[] = [];\n for (const line of output.split(\"\\n\")) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n try {\n const entry = JSON.parse(trimmed);\n services.push({\n name: entry.Service ?? entry.Name ?? \"unknown\",\n state: entry.State ?? \"unknown\",\n health: entry.Health || undefined,\n });\n } catch {\n // non-JSON noise from docker \u2014 skip\n }\n }\n return services;\n}\n\nexport function stackServices(): ServiceStatus[] {\n // Include the hub overlay so its containers show up when running.\n return parseComposePs(compose([\"ps\", \"-a\", \"--format\", \"json\"], { hub: true }));\n}\n\n/** Services expected to exit (one-shot jobs) \u2014 an `exited` state is fine. */\nexport const ONE_SHOT_SERVICES = new Set([\"spicedb-migrate\", \"zitadel-machinekey-init\"]);\n\n/**\n * The services whose `exited` state is a real failure *right now*.\n *\n * `stackServices()` scans the whole `mesh-local` compose project, overlay\n * included \u2014 but `mesh start` brings the base stack up first and the Hub\n * overlay only afterwards. Before that point an `exited` hub container is a\n * leftover from a previous run (a Docker restart, a laptop sleep), not a\n * crash: the base `up -d` deliberately never started it. Counting it made\n * `mesh start` abort before it ever tried to start the Hub, pointing at the\n * wrong thing.\n *\n * Once the overlay HAS been started, an exited overlay service is a crash\n * like any other \u2014 pass `overlayStarted: true` and the signal is preserved.\n */\nexport function crashedServices(\n services: ServiceStatus[],\n opts: { overlayServices: ReadonlySet<string>; overlayStarted: boolean },\n): ServiceStatus[] {\n return services.filter(\n (s) =>\n s.state === \"exited\" &&\n !ONE_SHOT_SERVICES.has(s.name) &&\n (opts.overlayStarted || !opts.overlayServices.has(s.name)),\n );\n}\n\n/**\n * Whether the Hub overlay is up in this run \u2014 i.e. at least one overlay\n * container is actually `running`. `mesh status` has no other way to know\n * (it never started anything), and \"a container exists\" is not it: a\n * leftover `exited` one exists too.\n */\nexport function hubOverlayRunning(\n services: ServiceStatus[],\n overlayServices: ReadonlySet<string>,\n): boolean {\n return services.some((s) => overlayServices.has(s.name) && s.state === \"running\");\n}\n\n/**\n * Whether the Hub API is serving. `some(s => s.name === \"hub-api\")` is not\n * the same question \u2014 that is true of a leftover exited container, and\n * probing Hub endpoints that were never meant to be up this run reports the\n * stack unhealthy for a Hub nobody started.\n */\nexport function hubApiRunning(services: ServiceStatus[]): boolean {\n return services.some((s) => s.name === \"hub-api\" && s.state === \"running\");\n}\n\n/** Probe a host endpoint (http 2xx-4xx counts as up; tcp connect counts as up). */\nexport async function probeEndpoint(endpoint: StackEndpoint): Promise<boolean> {\n if (endpoint.probe.kind === \"http\") {\n try {\n const res = await fetch(endpoint.probe.url, { signal: AbortSignal.timeout(3000) });\n return res.status < 500;\n } catch {\n return false;\n }\n }\n if (endpoint.probe.kind === \"tcp\") {\n return probeTcp(endpoint.probe.port, { timeoutMs: 3000 });\n }\n return true;\n}\n", "/**\n * `mesh dev --externals` (alias `--mock`) \u2014 external-service realizations\n * for a local dev session (MESH-1885, design C4).\n *\n * Apps DECLARE how each external dependency is realized locally in the root\n * package.json under `mesh.externals` (legacy key `mesh.mocks` still read).\n * Every declaration runs in exactly one of three MODES:\n *\n * mock \u2014 the service is MIMICKED: no real instance exists locally or\n * remotely. Realized from an OpenAPI spec (`openapi` \u2192 Prism\n * mock server) or a hand-written mock process (`src`).\n * local \u2014 a LOCAL VERSION of the real service runs on this machine,\n * e.g. a vendor-shaped database replica. Realized from a docker\n * compose file (`compose` + published `port`).\n * remote \u2014 the session connects to the ACTUAL external service: either\n * the vendor's real endpoint with inline `credentials` (e.g. a\n * sandbox), or the external service as configured in the app's\n * tenant environment (`remote.env`, e.g. dev \u2014 credentials are\n * pulled from that environment's secret).\n *\n * \"mesh\": {\n * \"externals\": {\n * \"plaid-db\": { // \u2500\u2500 local (default) \u2500\u2500\n * \"mode\": \"local\",\n * \"compose\": \"libs/plaid-db/docker/docker-compose.yml\",\n * \"port\": 1433, // REQUIRED: the published port\n * \"probe\": \"tcp\", // non-HTTP uptime probe\n * \"external\": \"plaid-db\",\n * \"credentials\": { // {{host}}/{{port}} \u2192 localhost:1433\n * \"host\": \"{{host}}\", \"port\": \"{{port}}\",\n * \"name\": \"Plaid_Clean\", \"username\": \"sa\",\n * \"password\": \"{{env:PLAID_DB_PASSWORD}}\"\n * },\n * \"remote\": { \"env\": \"dev\" } // `--externals plaid-db=remote`\n * }, // pulls the dev-configured secret\n * \"plaid\": { // \u2500\u2500 remote \u2500\u2500\n * \"mode\": \"remote\",\n * \"external\": \"plaid\", // the vendor's REAL sandbox\n * \"displayName\": \"Plaid\", // the Hub shows the real name\u2026\n * \"type\": \"api\", // \u2026and the integration type\n * \"docs\": \"https://plaid.com/docs/api/\", // vendor reference docs\n * \"credentials\": {\n * \"endpoint\": \"https://sandbox.plaid.com\",\n * \"client_id\": \"{{env:PLAID_CLIENT_ID}}\",\n * \"secret\": \"{{env:PLAID_SECRET}}\"\n * }\n * },\n * \"vendorpay\": { // \u2500\u2500 mock \u2500\u2500\n * \"mode\": \"mock\",\n * \"openapi\": \"api/docs/spec/openapi.json\", // spec \u2192 Prism emulation\n * \"external\": \"vendorpay\",\n * \"credentials\": { \"baseUrl\": \"{{url}}\", \"apiKey\": \"mock\" }\n * }\n * }\n * }\n *\n * `mode` picks the DEFAULT; a declaration may carry more than one\n * realization (e.g. compose + remote.env) and the CLI overrides per\n * external at run time: `mesh dev --externals plaid-db=remote,plaid`.\n * Declarations without `mode` infer it from their fields (compose \u2192 local,\n * openapi/src \u2192 mock, sandbox/credentials-only \u2192 remote), so pre-mode\n * declarations keep working (`sandbox: true` is a deprecated alias for\n * mode remote).\n *\n * All credential values support `{{env:VAR}}` interpolation from the\n * developer's environment, so real secrets (sandbox keys, DB passwords)\n * never land in package.json.\n *\n * Realization: mock externals join the SAME orchestration as services named\n * mock-{name} (ports, env files, tmux windows, Loki log pipeline); local\n * externals come up via `docker compose up -d --wait` before the app's\n * services and are torn down on `mesh dev --kill`; remote externals spawn\n * nothing. In every mode the ExternalService credential secret is seeded at\n * mesh/{tenant}/{env}/external/{name} so the app's resolveCredentials()\n * path runs UNCHANGED, the vendor is registered in the local Hub's\n * external-services view, and a blackbox uptime probe watches the\n * realization \u2014 remote endpoints included.\n */\n\nimport { execFileSync } from \"child_process\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport { logInfo, logSuccess, logWarn } from \"../../utils/log.js\";\nimport { MeshCliError } from \"../../utils/errors.js\";\nimport { LOCAL_ENV, LOCAL_AWS_CONFIG } from \"./seed.js\";\nimport { probeTcp, upsertLocalSecret } from \"./helpers.js\";\nimport { localProbesDir } from \"./stack.js\";\n\nexport interface LocalMockDecl {\n /** Default mode for this external: \"mock\" (emulate via openapi/src),\n * \"local\" (docker compose local version), \"remote\" (the actual service).\n * Inferred from the realization fields when omitted; overridable per run\n * with `mesh dev --externals name=mode`. */\n mode?: ExternalMode;\n /** Mock mode: directory (relative to app root) with a package.json `dev`\n * script \u2014 a hand-written mock process. */\n src?: string;\n /** Local mode: docker compose file (relative to app root) running a local\n * version of the external service \u2014 e.g. a vendor-shaped database\n * replica. `mesh dev` runs `docker compose up -d --wait` before the\n * app's services and `docker compose down` on `--kill`. Requires `port`. */\n compose?: string;\n /** Mock mode: OpenAPI spec file (relative to app root); the CLI emulates\n * the service with a Prism mock server (`npx @stoplight/prism-cli mock`)\n * as mock-{name}. */\n openapi?: string;\n /** @deprecated alias for `mode: \"remote\"` (with inline credentials). */\n sandbox?: boolean;\n /** Remote-mode credential source. When the external runs in remote mode,\n * its credentials come from (first match): `remote.credentials` (inline,\n * env-interpolated), the top-level `credentials` if this declaration has\n * no local/mock realization (a pure-remote declaration), or the external\n * service configured in the app's tenant environment `remote.env`\n * (default \"dev\") \u2014 secret mesh/{tenant}/{env}/external/{name}, read\n * with the developer's ambient AWS credentials. `remote.profile` names\n * the AWS profile for that pull when the shell carries no AWS identity\n * (no AWS_ACCESS_KEY_ID / AWS_PROFILE); the MESH_AWS_PROFILE env var\n * overrides it \u2014 the same convention repo pull scripts use. */\n remote?: { env?: string; credentials?: Record<string, string>; profile?: string };\n /** Human-facing integration name shown in the Hub (e.g. \"Plaid\",\n * \"Unit21\"). @default the external name title-cased (\"plaid-db\" \u2192\n * \"Plaid Db\"). */\n displayName?: string;\n /** Vendor reference documentation for the integration, linked from the\n * Hub \u2014 a URL string or `{ url, provider }`.\n * @example \"https://plaid.com/docs/api/\" */\n docs?: string | { url: string; provider?: string };\n /** Fixed port; omitted = auto-allocated after the app's services.\n * REQUIRED in local (compose) mode \u2014 the compose file's published port. */\n port?: number;\n /** Launch command (default: [\"pnpm\", \"dev\"]; openapi mocks synthesize a\n * Prism command) */\n command?: string[];\n /** Extra env for the mock process */\n env?: Record<string, string>;\n /** ExternalService name this declaration realizes */\n external?: string;\n /** Credential JSON seeded into the external secret (the local/mock\n * realization's template; also the remote source for pure-remote\n * declarations). Tokens: \"{{url}}\" \u2192 the stand-in's URL, \"{{host}}\"/\n * \"{{port}}\" \u2192 its host/port, and \"{{env:VAR}}\" \u2192 the developer's\n * environment (all modes). */\n credentials?: Record<string, string>;\n /** Integration type shown in the Hub \u2014 api, database, object_storage,\n * sftp, banking_core, \u2026 (@default \"other\"). Display only; derived\n * reachability probes key off the credential fields themselves (a\n * `bucket` credential probes TCP to the bucket endpoint regardless of\n * the declared type). */\n type?: string;\n /** Health endpoint path probed by the platform's blackbox exporter\n * (uptime in the Hub). @default \"/health\" for local/mock realizations;\n * remote endpoints default to probing the endpoint root (\"\") since\n * vendors rarely expose /health. */\n healthPath?: string;\n /** Blackbox probe module. \"http\" (default) GETs the health URL and\n * expects 2xx; \"tcp\" only checks the port accepts connections \u2014 REQUIRED\n * for non-HTTP externals (databases, SFTP, \u2026) whose uptime would\n * otherwise always read down. */\n probe?: \"http\" | \"tcp\";\n}\n\n/** The three ways an external service exists in a local dev session. */\nexport type ExternalMode = \"mock\" | \"local\" | \"remote\";\n\nconst EXTERNAL_MODES: readonly ExternalMode[] = [\"mock\", \"local\", \"remote\"];\n\nconst DECL_DOCS = { docs: 'package.json \u2192 \"mesh\": { \"externals\": { \u2026 } }' };\n\n/**\n * Resolve + validate an external's mode: explicit `mode` (or the one\n * inferred from the realization fields), checked against the fields that\n * mode needs. Pre-mode declarations infer: compose \u2192 local, openapi/src \u2192\n * mock, sandbox/credentials-only \u2192 remote.\n */\nexport function externalMode(name: string, decl: LocalMockDecl): ExternalMode {\n const mode: ExternalMode | undefined =\n decl.mode ??\n (decl.compose\n ? \"local\"\n : decl.openapi || decl.src\n ? \"mock\"\n : decl.sandbox || decl.credentials || decl.remote\n ? \"remote\"\n : undefined);\n if (!mode || !EXTERNAL_MODES.includes(mode)) {\n throw new MeshCliError(\n `External '${name}': cannot determine mode \u2014 set \"mode\" to mock | local | remote (or declare openapi/src, compose, or credentials).`,\n { remediation: DECL_DOCS },\n );\n }\n if (mode === \"local\") {\n if (!decl.compose) {\n throw new MeshCliError(\n `External '${name}': local mode requires \"compose\" \u2014 the docker compose file running the local version of the service.`,\n { remediation: DECL_DOCS },\n );\n }\n if (typeof decl.port !== \"number\") {\n throw new MeshCliError(\n `External '${name}': local (compose) mode requires \"port\" \u2014 the port the compose file publishes on localhost.`,\n { remediation: DECL_DOCS },\n );\n }\n }\n if (mode === \"mock\" && !decl.openapi && !decl.src) {\n throw new MeshCliError(\n `External '${name}': mock mode emulates the service \u2014 declare \"openapi\" (spec \u2192 Prism mock) or \"src\" (mock process).`,\n { remediation: DECL_DOCS },\n );\n }\n if (mode === \"remote\" && !remoteInlineCredentials(decl) && !decl.external) {\n throw new MeshCliError(\n `External '${name}': remote mode needs a credential source \u2014 inline \"credentials\", \"remote\": { \"env\": \u2026 }, or \"external\" (pulls that environment's configured secret).`,\n { remediation: DECL_DOCS },\n );\n }\n return mode;\n}\n\n/** A parsed `--externals` selection: the externals named, and the per-run\n * mode overrides typed alongside them (`plaid-db=remote`). */\nexport interface ExternalsSelection {\n names: string[];\n overrides: Map<string, ExternalMode>;\n}\n\n/**\n * Parse a `--externals` value \u2014 a comma-separated list of `name` or\n * `name=mode` entries. An explicit mode overrides that declaration's\n * default FOR THIS RUN; a bare name keeps the declared default.\n *\n * Names are returned in the order typed, de-duplicated (the last mode\n * given for a name wins, so `--externals plaid,plaid=remote` is remote).\n */\nexport function parseExternalsSelection(input: string): ExternalsSelection {\n const names: string[] = [];\n const overrides = new Map<string, ExternalMode>();\n for (const entry of input.split(\",\").map((s) => s.trim()).filter(Boolean)) {\n const [rawName, mode, ...rest] = entry.split(\"=\").map((s) => s.trim());\n const name = rawName ?? \"\";\n if (!name) {\n throw new MeshCliError(\n `Bad --externals entry '${entry}' \u2014 expected name or name=mode with mode \u2208 ${EXTERNAL_MODES.join(\" | \")}.`,\n { remediation: { command: \"mesh dev --externals plaid-db=remote,plaid\" } },\n );\n }\n if (mode !== undefined) {\n if (rest.length > 0 || !EXTERNAL_MODES.includes(mode as ExternalMode)) {\n throw new MeshCliError(\n `Bad --externals entry '${entry}' \u2014 expected name or name=mode with mode \u2208 ${EXTERNAL_MODES.join(\" | \")}.`,\n { remediation: { command: \"mesh dev --externals plaid-db=remote,plaid\" } },\n );\n }\n overrides.set(name, mode as ExternalMode);\n }\n if (!names.includes(name)) names.push(name);\n }\n return { names, overrides };\n}\n\n/**\n * The inline credential template a remote-mode run should use, if any:\n * `remote.credentials` always wins; top-level `credentials` count only when\n * the declaration has no local/mock realization (otherwise they are that\n * realization's template, full of {{host}}/{{port}} tokens that only mean\n * something against a local endpoint).\n */\nexport function remoteInlineCredentials(decl: LocalMockDecl): Record<string, string> | undefined {\n if (decl.remote?.credentials) return decl.remote.credentials;\n if (decl.credentials && !decl.compose && !decl.openapi && !decl.src) return decl.credentials;\n return undefined;\n}\n\n/** Whether this declaration runs as a mock-{name} service in the dev\n * orchestration (mock mode) vs outside it (local compose / remote). */\nexport function isServiceMode(name: string, decl: LocalMockDecl): boolean {\n return externalMode(name, decl) === \"mock\";\n}\n\n/** Endpoint tokens available to credential interpolation. */\nexport interface MockEndpoint {\n url: string;\n host: string;\n port: number;\n}\n\n/**\n * Interpolate one credential value: {{url}}/{{host}}/{{port}} from the\n * stand-in's endpoint, {{env:VAR}} from the developer's environment\n * (missing env vars are a hard error \u2014 a half-seeded secret is worse).\n */\nexport function interpolateCredentialValue(\n raw: string,\n endpoint: MockEndpoint | undefined,\n env: NodeJS.ProcessEnv = process.env,\n): string {\n let value = raw.replace(/\\{\\{env:([A-Za-z_][A-Za-z0-9_]*)\\}\\}/g, (_, name: string) => {\n const resolved = env[name];\n if (resolved === undefined) {\n throw new MeshCliError(\n `Credential value references {{env:${name}}} but ${name} is not set in your environment.`,\n { remediation: { command: `export ${name}=\u2026 # then re-run mesh dev` } },\n );\n }\n return resolved;\n });\n if (endpoint) {\n value = value\n .replaceAll(\"{{url}}\", endpoint.url)\n .replaceAll(\"{{host}}\", endpoint.host)\n .replaceAll(\"{{port}}\", String(endpoint.port));\n }\n return value;\n}\n\n/** The Prism mock command for an openapi-mode declaration. `$PORT` expands\n * in the service's launch shell (tmux and docker runners both source the\n * env file), so port reallocation keeps working. */\nexport function openapiMockCommand(decl: LocalMockDecl): string[] {\n return (\n decl.command ?? [\n \"npx\",\n \"-y\",\n \"@stoplight/prism-cli@5\",\n \"mock\",\n \"-p\",\n \"$PORT\",\n \"-h\",\n \"0.0.0.0\",\n decl.openapi!,\n ]\n );\n}\n\n/** Compose-mode project name \u2014 pinned so `--kill` can tear down exactly\n * what `up` created, regardless of the compose file's own `name:`. */\nexport function composeProjectName(sessionName: string, mockName: string): string {\n return `mesh-ext-${sessionName}-${mockName}`.toLowerCase().replace(/[^a-z0-9_-]/g, \"-\");\n}\n\n/** A compose-mode external recorded in session state for teardown. */\nexport interface ComposeExternalRef {\n name: string;\n composeFile: string;\n project: string;\n}\n\n/** Wait until the external's published port accepts TCP (bounded). */\nasync function waitForPort(port: number, timeoutMs: number): Promise<boolean> {\n const deadline = Date.now() + timeoutMs;\n while (Date.now() < deadline) {\n if (await probeTcp(port, { timeoutMs: 2000 })) return true;\n await new Promise((r) => setTimeout(r, 2000));\n }\n return false;\n}\n\n/** What an existing realization of a compose external means for this run.\n * - `up` \u2192 nothing foreign in the way (or the realization is OURS):\n * normal idempotent `up`, ref recorded for `--kill`.\n * - `adopt-served` \u2192 ANOTHER realization of THIS compose file already serves\n * the declared port.\n * - `adopt-stopped` \u2192 a stopped container from another compose project holds\n * a `container_name` this file pins.\n * - `conflict` \u2192 the port is served by something this compose file does\n * not define (a native database, an unrelated container).\n * Never adopted: the app's credentials would be seeded\n * against the wrong service. */\nexport type ComposeExternalPlan =\n | { action: \"up\" }\n | { action: \"adopt-served\"; container: string }\n | { action: \"adopt-stopped\"; container: string }\n | { action: \"conflict\"; container?: string };\n\n/** The docker/network lookups `planComposeExternal` needs, injectable so the\n * branch table is unit-testable without a docker daemon. */\nexport interface ComposeExternalProbes {\n /** Is a container of OUR compose project already running for this file? */\n ownsRunning(composeFile: string, project: string): boolean;\n /** Does anything accept TCP on the declared port? */\n portServed(port: number): Promise<boolean>;\n /** A pinned `container_name` held by a DIFFERENT compose project. */\n foreignPinned(composeFile: string, project: string): string | undefined;\n /** Who publishes `port`, and is it a service THIS compose file defines?\n * Undefined when nothing in docker publishes it (a native process, or no\n * docker at all) \u2014 which is itself disqualifying for adoption. */\n portPublisher(\n composeFile: string,\n port: number,\n ): { container: string; definedByFile: boolean } | undefined;\n}\n\n/**\n * Decide how to realize a compose external, given what already exists.\n *\n * OWNERSHIP FIRST: a port probe can't tell WHO serves the port, and the\n * ordinary flow re-runs `mesh dev` against a session whose compose externals\n * are deliberately left running. Adopting there would drop the ref from\n * session state and permanently orphan the checkout's own container, so our\n * own realization takes the normal `up` path (idempotent, ref re-recorded)\n * and only a foreign one is adopted.\n *\n * IDENTITY SECOND: a foreign publisher is only adopted when it is a service\n * THIS compose file defines. Well-known ports (1433/5432/22) are exactly\n * where a native install or an unrelated container turns up, and adopting one\n * silently seeds the app's credentials against the wrong database.\n */\nexport async function planComposeExternal(\n composeFile: string,\n project: string,\n port: number,\n probes: ComposeExternalProbes,\n): Promise<ComposeExternalPlan> {\n if (probes.ownsRunning(composeFile, project)) return { action: \"up\" };\n if (await probes.portServed(port)) {\n const publisher = probes.portPublisher(composeFile, port);\n if (!publisher || !publisher.definedByFile) {\n return { action: \"conflict\", ...(publisher ? { container: publisher.container } : {}) };\n }\n return { action: \"adopt-served\", container: publisher.container };\n }\n // Pinned container_name held by a STOPPED container from another checkout/\n // project would make `up` fail with a name conflict \u2014 start that container\n // instead. (A RUNNING one is caught by the port probe above.)\n const foreign = probes.foreignPinned(composeFile, project);\n if (foreign) return { action: \"adopt-stopped\", container: foreign };\n return { action: \"up\" };\n}\n\n/** Real docker/network probes \u2014 replaced in tests. */\nconst dockerProbes: ComposeExternalProbes = {\n ownsRunning: ownsRunningRealization,\n portServed: (port) => probeTcp(port, { timeoutMs: 2000 }),\n foreignPinned: foreignPinnedContainer,\n portPublisher: composeFilePortPublisher,\n};\n\n/**\n * Bring a compose-mode external up (idempotent; waits for healthchecks \u2014\n * vendor DBs restoring seed data can take a while, hence the timeout).\n *\n * ADOPTION: the same external is often realized by more than one checkout \u2014\n * e.g. a vendor-DB compose ported from a legacy repo pins `container_name`\n * and a host port, so whichever checkout created it first blocks every other\n * `docker compose up` (name + port conflicts). An external service is by\n * definition outside the app, so if ANOTHER checkout already serves its\n * published port \u2014 or left a stopped container holding the pinned name \u2014\n * this ADOPTS that realization instead of failing: skip/`docker start`, wait\n * for the port, and return undefined so `--kill` never tears down what\n * another checkout owns. Our OWN realization is never adopted (see\n * `planComposeExternal`) \u2014 it stays recorded so `--kill` still cleans it up,\n * and a publisher this compose file doesn't define is never adopted either\n * (it would seed the app's credentials against the wrong service).\n */\nexport async function composeExternalUp(\n appRoot: string,\n sessionName: string,\n name: string,\n decl: LocalMockDecl,\n probes: ComposeExternalProbes = dockerProbes,\n): Promise<ComposeExternalRef | undefined> {\n const composeFile = path.resolve(appRoot, decl.compose!);\n if (!fs.existsSync(composeFile)) {\n throw new MeshCliError(`External '${name}': compose file not found at ${composeFile}.`, {\n remediation: { docs: 'package.json \u2192 \"mesh\": { \"externals\": { \u2026 } }' },\n });\n }\n const project = composeProjectName(sessionName, name);\n const plan = await planComposeExternal(composeFile, project, decl.port!, probes);\n if (plan.action === \"conflict\") {\n throw new MeshCliError(\n `External '${name}': localhost:${decl.port} is already served by ${\n plan.container ? `container '${plan.container}'` : \"a process outside docker\"\n }, which ${decl.compose} does not define \u2014 refusing to seed '${name}' credentials against it.`,\n {\n remediation: {\n command: `docker ps --filter publish=${decl.port} # stop it, or change the declared port`,\n },\n },\n );\n }\n if (plan.action === \"adopt-served\") {\n logInfo(\n `External '${name}' already served on localhost:${decl.port} by container '${plan.container}' \u2014 adopting it (started outside this checkout; \\`mesh dev --kill\\` won't touch it).`,\n );\n return undefined;\n }\n if (plan.action === \"adopt-stopped\") {\n const { container } = plan;\n logInfo(`External '${name}': container '${container}' exists from another checkout \u2014 starting and adopting it.`);\n execFileSync(\"docker\", [\"start\", container], { stdio: [\"ignore\", \"ignore\", \"inherit\"] });\n if (!(await waitForPort(decl.port!, 300_000))) {\n throw new MeshCliError(\n `External '${name}': adopted container '${container}' never served localhost:${decl.port}.`,\n { remediation: { command: `docker logs ${container} # then: docker rm -f ${container} and re-run` } },\n );\n }\n return undefined;\n }\n execFileSync(\n \"docker\",\n [\"compose\", \"-p\", project, \"-f\", composeFile, \"up\", \"-d\", \"--wait\", \"--wait-timeout\", \"300\"],\n { stdio: [\"ignore\", \"inherit\", \"inherit\"] },\n );\n return { name, composeFile, project };\n}\n\n/** Whether OUR compose project already has a container running for this file.\n * `docker compose ps` (running only) covers services WITHOUT a pinned\n * `container_name` too, which the label-inspect path below structurally\n * cannot \u2014 an unpinned service of ours is just `<project>-<svc>-1`. */\nfunction ownsRunningRealization(composeFile: string, project: string): boolean {\n try {\n const out = execFileSync(\n \"docker\",\n [\"compose\", \"-p\", project, \"-f\", composeFile, \"ps\", \"--format\", \"json\"],\n { encoding: \"utf-8\", stdio: [\"ignore\", \"pipe\", \"ignore\"] },\n ).trim();\n // Compose emits either a JSON array or NDJSON depending on version;\n // \"has any row\" is all we need from it.\n return out.length > 0 && out !== \"[]\";\n } catch {\n // ps hiccup \u2014 treat as \"not ours\" and let the normal paths decide.\n return false;\n }\n}\n\n/** The compose file's rendered service map, or undefined when it can't be\n * rendered (docker missing / bad file \u2014 callers decide what that means). */\nfunction composeServices(composeFile: string): Record<string, any> | undefined {\n try {\n const config = JSON.parse(\n execFileSync(\"docker\", [\"compose\", \"-f\", composeFile, \"config\", \"--format\", \"json\"], {\n encoding: \"utf-8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n }),\n );\n const services = config?.services;\n return services && typeof services === \"object\" ? services : undefined;\n } catch {\n return undefined;\n }\n}\n\n/** The container publishing `port` on the host, with the compose identity\n * labels docker stamps on it. Undefined when nothing in docker publishes it\n * (a native process, or no docker at all). */\ninterface PortPublisher {\n container: string;\n image?: string;\n project?: string;\n service?: string;\n}\n\nfunction portPublisher(port: number): PortPublisher | undefined {\n try {\n const out = execFileSync(\n \"docker\",\n [\n \"ps\",\n \"--filter\",\n `publish=${port}`,\n \"--format\",\n '{{.Names}}\\t{{.Image}}\\t{{.Label \"com.docker.compose.project\"}}\\t{{.Label \"com.docker.compose.service\"}}',\n ],\n { encoding: \"utf-8\", stdio: [\"ignore\", \"pipe\", \"ignore\"] },\n );\n const line = out\n .split(\"\\n\")\n .map((l) => l.trim())\n .filter(Boolean)[0];\n if (!line) return undefined;\n const [container, image, project, service] = line.split(\"\\t\");\n if (!container) return undefined;\n return {\n container,\n image: image || undefined,\n project: project || undefined,\n service: service || undefined,\n };\n } catch {\n return undefined;\n }\n}\n\n/** Whether the container publishing the declared port is a service THIS\n * compose file defines \u2014 the evidence adoption requires. Matches on the\n * pinned `container_name`, or on the compose service name (cross-checked\n * against the image when both sides declare one, so an unrelated project's\n * service that happens to be called `db` isn't mistaken for ours). */\nfunction composeFileOwns(composeFile: string, publisher: PortPublisher | undefined): boolean {\n if (!publisher) return false;\n const services = composeServices(composeFile);\n if (!services) return false; // no identity evidence \u2014 don't adopt\n for (const [key, svc] of Object.entries<any>(services)) {\n if (svc?.container_name && svc.container_name === publisher.container) return true;\n if (publisher.service && publisher.service === key) {\n if (!svc?.image || !publisher.image || svc.image === publisher.image) return true;\n }\n }\n return false;\n}\n\n/** `ComposeExternalProbes.portPublisher` \u2014 who serves the declared port, and\n * whether this compose file defines it. Undefined when docker publishes\n * nothing there (a native process on the port, or no docker at all), which\n * `planComposeExternal` treats as a conflict rather than an adoption. */\nfunction composeFilePortPublisher(\n composeFile: string,\n port: number,\n): { container: string; definedByFile: boolean } | undefined {\n const publisher = portPublisher(port);\n if (!publisher) return undefined;\n return { container: publisher.container, definedByFile: composeFileOwns(composeFile, publisher) };\n}\n\n/** Find a container holding a `container_name` this compose file pins, when\n * it belongs to a different compose project (another checkout's realization\n * of the same external). Returns the container name, or undefined. */\nfunction foreignPinnedContainer(composeFile: string, project: string): string | undefined {\n // config render hiccup \u2014 fall through to the normal `up`, which reports\n // real errors itself.\n for (const svc of Object.values<any>(composeServices(composeFile) ?? {})) {\n const pinned = svc?.container_name;\n if (!pinned) continue;\n try {\n const owner = execFileSync(\n \"docker\",\n [\"inspect\", pinned, \"--format\", '{{ index .Config.Labels \"com.docker.compose.project\" }}'],\n { encoding: \"utf-8\", stdio: [\"ignore\", \"pipe\", \"ignore\"] },\n ).trim();\n if (owner !== project) return pinned;\n } catch {\n // no container by that name \u2014 nothing to adopt for this service\n }\n }\n return undefined;\n}\n\n/** Tear down compose-mode externals recorded in session state. Volumes are\n * kept (vendor DB data survives sessions, like the cloud external it\n * stands in for); best-effort per project. */\nexport function composeExternalsDown(refs: ComposeExternalRef[] | undefined): void {\n for (const ref of refs ?? []) {\n try {\n execFileSync(\"docker\", [\"compose\", \"-p\", ref.project, \"-f\", ref.composeFile, \"down\", \"--remove-orphans\"], {\n stdio: [\"ignore\", \"inherit\", \"inherit\"],\n });\n } catch {\n /* best effort \u2014 the file may be gone or docker down */\n }\n }\n}\n\n/** Same heuristic the schema seed uses: which credential keys are secret. */\nconst SECRET_KEY_RE = /key|secret|password|token/i;\n\n/** Read the app's declared externals (root package.json \u2192 mesh.externals;\n * legacy key mesh.mocks still read, externals wins on name collision). */\nexport function readLocalMocks(appRoot: string): Record<string, LocalMockDecl> {\n try {\n const pkg = JSON.parse(fs.readFileSync(path.join(appRoot, \"package.json\"), \"utf-8\"));\n const mocks = pkg?.mesh?.mocks;\n const externals = pkg?.mesh?.externals;\n return {\n ...(mocks && typeof mocks === \"object\" ? mocks : {}),\n ...(externals && typeof externals === \"object\" ? externals : {}),\n };\n } catch {\n return {};\n }\n}\n\nexport function externalSecretPath(tenant: string, external: string): string {\n return `mesh/${tenant}/${LOCAL_ENV}/external/${external}`;\n}\n\n/**\n * Pull an external service's credentials as configured in the app's tenant\n * environment (the CLOUD platform, not the local fabric) \u2014 secret\n * mesh/{tenant}/{env}/external/{name}, read with the developer's ambient\n * AWS credentials (AWS_PROFILE / SSO session for that tenant's account).\n * When the shell carries no AWS identity at all, `profile` (from the\n * declaration; MESH_AWS_PROFILE overrides) names the profile to use \u2014 the\n * same convention repo pull scripts follow.\n */\nexport async function fetchRemoteExternalCredentials(\n tenant: string,\n env: string,\n external: string,\n profile?: string,\n): Promise<Record<string, string>> {\n const secretId = `mesh/${tenant}/${env}/external/${external}`;\n const region = process.env.MESH_PLATFORM_REGION ?? process.env.AWS_REGION ?? \"us-east-2\";\n const fallbackProfile =\n !process.env.AWS_ACCESS_KEY_ID && !process.env.AWS_PROFILE\n ? (process.env.MESH_AWS_PROFILE ?? profile)\n : undefined;\n try {\n const { SecretsManagerClient, GetSecretValueCommand } = await import(\n \"@aws-sdk/client-secrets-manager\"\n );\n // The SDK's default chain reads AWS_PROFILE at first resolution \u2014 scope\n // the fallback to this client's call (no ambient identity to clobber).\n if (fallbackProfile) process.env.AWS_PROFILE = fallbackProfile;\n const sm = new SecretsManagerClient({ region });\n let res;\n try {\n res = await sm.send(new GetSecretValueCommand({ SecretId: secretId }));\n } finally {\n if (fallbackProfile) delete process.env.AWS_PROFILE;\n }\n const parsed: unknown = JSON.parse(res.SecretString ?? \"{}\");\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n throw new Error(\"secret value is not a JSON object\");\n }\n return Object.fromEntries(Object.entries(parsed).map(([key, v]) => [key, String(v)]));\n } catch (err) {\n throw new MeshCliError(\n `External '${external}': could not pull remote credentials from the ${env} environment (${secretId}, region ${region}): ${err instanceof Error ? err.message : err}`,\n {\n remediation: {\n command: `AWS_PROFILE=<${tenant}-${env} profile> mesh dev \u2026 # or set \"remote\": { \"profile\": \u2026 } on the declaration / MESH_AWS_PROFILE`,\n },\n },\n );\n }\n}\n\n/** The prober runs inside the stack: anything addressed at the developer\n * host must go through host.docker.internal. */\nfunction hostForProber(target: string): string {\n return target.replace(/\\b(?:localhost|127\\.0\\.0\\.1)\\b/, \"host.docker.internal\");\n}\n\n/**\n * A credential's endpoint value as an HTTP probe target, or undefined when\n * it isn't one. Credentials pulled from a tenant secret carry whatever the\n * vendor configured \u2014 a JDBC/ODBC connection string, an `sftp://` URL, or\n * an http URL with embedded userinfo. Anything non-http(s) falls through to\n * the tcp branch, and userinfo is stripped: the target is written to a\n * plaintext probe file and relabeled into Prometheus' `instance` label, so\n * a password in it would leak into every `probe_*` series.\n */\nfunction httpProbeUrl(raw: string | undefined): string | undefined {\n if (!raw) return undefined;\n let parsed: URL;\n try {\n parsed = new URL(raw);\n } catch {\n return undefined;\n }\n if (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") return undefined;\n parsed.username = \"\";\n parsed.password = \"\";\n return hostForProber(parsed.toString());\n}\n\n/** Reachability target for a non-HTTP integration, derived from its\n * credentials: a host/port pair (databases, SFTP) or an S3 bucket endpoint\n * (probed via TCP \u2014 no SDK or credentials needed, the technique CSP's\n * network lib used). */\nfunction derivedTcpTarget(creds: Record<string, string>): string | undefined {\n if (creds.host && creds.port) return `${hostForProber(creds.host)}:${creds.port}`;\n if (creds.bucket) return `${creds.bucket}.s3.${creds.region || \"us-east-1\"}.amazonaws.com:443`;\n return undefined;\n}\n\n/** The blackbox probe target for a realization, by mode: local/mock\n * stand-ins are probed on the host (the prober runs inside the stack \u2192\n * host.docker.internal); remote externals are probed at their REAL\n * endpoint, so the Hub shows actual vendor reachability. Every integration\n * gets AT LEAST a reachability check when its credentials expose a target:\n * an HTTP endpoint, a host(:port), or an S3 bucket (probed via TCP to the\n * bucket endpoint \u2014 no SDK/credentials needed, the same technique CSP's\n * network lib used). Undefined = nothing probeable in the credentials.\n *\n * Target and module come from ONE decision here so they can't drift: a\n * misrouted probe just reports probe_success 0, indistinguishable from a\n * genuinely down service. `tcp` yields host:port with no scheme/path and\n * routes the scrape to blackbox's tcp_connect (the scrape config's default\n * stays http_2xx); `http` GETs the target and expects 2xx. */\nexport function resolveProbeTarget(\n mode: ExternalMode,\n decl: LocalMockDecl,\n endpoint: MockEndpoint | undefined,\n creds: Record<string, string>,\n): { target: string; module?: \"tcp_connect\" } | undefined {\n if (mode === \"remote\") {\n // The endpoint comes from a TENANT SECRET, so it may be anything a\n // vendor credential carries \u2014 a JDBC/ODBC connection string, or a URL\n // with userinfo. Only a real http(s) URL is probeable, and its\n // credentials must never reach the probe file (world-readable) or the\n // Prometheus `instance` label.\n const url = httpProbeUrl(creds.endpoint ?? creds.url ?? creds.baseUrl);\n // Reachability fallbacks for non-HTTP integrations: host:port\n // (databases, SFTP) or the S3 bucket endpoint (object storage).\n const tcpTarget = derivedTcpTarget(creds);\n if (decl.probe === \"tcp\" || (!url && tcpTarget)) {\n if (!tcpTarget && decl.probe === \"tcp\") {\n logWarn(\n `External '${decl.external ?? \"\"}': probe: \"tcp\" declared but the remote credentials carry no host/port (or bucket) to probe \u2014 no uptime probe registered.`,\n );\n }\n return tcpTarget ? { target: tcpTarget, module: \"tcp_connect\" } : undefined;\n }\n // Remote endpoints rarely expose /health \u2014 default to the endpoint\n // root (Plaid's sandbox, for one, answers 200 there).\n return url ? { target: url.replace(/\\/+$/, \"\") + (decl.healthPath ?? \"\") } : undefined;\n }\n if (!endpoint) return undefined;\n if (decl.probe === \"tcp\") {\n return { target: `host.docker.internal:${endpoint.port}`, module: \"tcp_connect\" };\n }\n return {\n target: hostForProber(endpoint.url).replace(/\\/+$/, \"\") + (decl.healthPath ?? \"/health\"),\n };\n}\n\n/** Hub display name: explicit `displayName`, else the external name\n * title-cased on word boundaries (\"plaid-db\" \u2192 \"Plaid Db\"). */\nexport function externalDisplayName(name: string, decl: LocalMockDecl): string {\n return (\n decl.displayName ??\n name\n .split(/[-_\\s]+/)\n .filter(Boolean)\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\n .join(\" \")\n );\n}\n\n/** Normalize the decl's `docs` (string URL or {url, provider}) for the meta. */\nexport function externalDocs(\n decl: LocalMockDecl,\n): { url: string; provider?: string } | undefined {\n if (!decl.docs) return undefined;\n return typeof decl.docs === \"string\" ? { url: decl.docs } : decl.docs;\n}\n\n/** Prometheus file_sd target file for one external's uptime probe. One\n * file per (tenant, app, external) so a session's probes can be removed on\n * `--kill` without touching another app's. */\nexport function localProbeFile(tenant: string, app: string, external: string): string {\n return path.join(localProbesDir(), `${tenant}-${app}-${external}.json`);\n}\n\n/** Drop probe target files (best effort). Called on `mesh dev --kill` so\n * Prometheus stops scraping stand-ins that no longer exist \u2014 otherwise the\n * Hub shows an integration down for a session that isn't running. */\nexport function localProbesRemove(files: string[] | undefined): void {\n for (const file of files ?? []) {\n try {\n fs.rmSync(file, { force: true });\n } catch {\n /* best effort \u2014 the cache dir may be gone */\n }\n }\n}\n\n/**\n * Wire a realization into the platform: seed the external-service\n * credential secret and register the vendor in the local Hub's\n * external-services view \u2014 the same shapes ExternalService exports in the\n * cloud. `endpoint` is the local stand-in's address (absent in remote\n * mode \u2014 the credentials carry the real endpoint).\n *\n * Returns the probe target file this realization registered, if any, so the\n * caller can record it in session state and remove it on `--kill`.\n */\nexport async function seedLocalMock(args: {\n tenant: string;\n app: string;\n name: string;\n decl: LocalMockDecl;\n endpoint?: MockEndpoint;\n}): Promise<string | undefined> {\n const { tenant, app, name, decl, endpoint } = args;\n if (!decl.external) return undefined;\n const mode = externalMode(name, decl);\n\n // Credential values by mode: local/mock interpolate the declared template\n // against the stand-in's endpoint; remote uses inline credentials or\n // pulls the tenant environment's configured secret.\n let value: Record<string, string>;\n if (mode === \"remote\") {\n const inline = remoteInlineCredentials(decl);\n value = inline\n ? Object.fromEntries(\n Object.entries(inline).map(([key, raw]) => [\n key,\n interpolateCredentialValue(raw, undefined),\n ]),\n )\n : await fetchRemoteExternalCredentials(\n tenant,\n decl.remote?.env ?? \"dev\",\n decl.external,\n decl.remote?.profile,\n );\n } else {\n if (!decl.credentials) return undefined;\n value = Object.fromEntries(\n Object.entries(decl.credentials).map(([key, raw]) => [\n key,\n interpolateCredentialValue(raw, endpoint),\n ]),\n );\n }\n\n const secretName = externalSecretPath(tenant, decl.external);\n await upsertLocalSecret(secretName, value);\n // The .config mirror \u2014 non-secret fields only. This is what the Hub's\n // credential views READ (the main secret is runtime-only by design), so\n // baseUrl etc. display in the Integrations detail page.\n await upsertLocalSecret(\n `${secretName}/.config`,\n Object.fromEntries(Object.entries(value).filter(([key]) => !SECRET_KEY_RE.test(key))),\n );\n\n // Hub discovery \u2014 the same per-stack shapes ExternalService exports in the\n // cloud (/apps/{app}/stacks/{stack}/external-services/{name}/\u2026).\n const { SSMClient, PutParameterCommand } = await import(\"@aws-sdk/client-ssm\");\n const ssm = new SSMClient(LOCAL_AWS_CONFIG);\n const base = `/mesh-platform/${tenant}/${LOCAL_ENV}/apps/${app}/stacks/local/external-services/${decl.external}`;\n await ssm.send(\n new PutParameterCommand({\n Name: `${base}/meta`,\n Type: \"String\",\n Overwrite: true,\n Value: JSON.stringify({\n name: decl.external,\n // The integration keeps its REAL name in the Hub (\"Plaid\", not a\n // generated phrase); the description leads with it too, so display\n // heuristics that promote description heads still land on the name.\n displayName: externalDisplayName(name, decl),\n type: decl.type ?? \"other\",\n description:\n mode === \"local\"\n ? `${externalDisplayName(name, decl)} \u2014 local replica via mesh dev (docker compose)`\n : mode === \"remote\"\n ? remoteInlineCredentials(decl)\n ? `${externalDisplayName(name, decl)} \u2014 remote service (vendor credentials)`\n : `${externalDisplayName(name, decl)} \u2014 remote service (${decl.remote?.env ?? \"dev\"} environment credentials)`\n : `${externalDisplayName(name, decl)} \u2014 emulated by mesh dev (mock)`,\n secretPrefix: secretName,\n ...(externalDocs(decl) ? { docs: externalDocs(decl) } : {}),\n }),\n Description: `External service registration (local mock ${name})`,\n }),\n );\n await ssm.send(\n new PutParameterCommand({\n Name: `${base}/credentials`,\n Type: \"String\",\n Overwrite: true,\n Value: JSON.stringify({\n fields: Object.fromEntries(\n Object.keys(value).map((key) => [\n key,\n { type: \"field\", name: key, description: \"\", secret: SECRET_KEY_RE.test(key), optional: false },\n ]),\n ),\n keyedBy: null,\n }),\n Description: `External service credential schema (local mock ${name})`,\n }),\n );\n\n // Blackbox probe target (Prometheus file_sd) \u2014 the local analog of the\n // Probe CR ExternalService creates in the cloud, with the SAME label set,\n // so probe_success drives the Hub's health/uptime views unchanged.\n // Local/mock stand-ins are probed on the host; remote externals at their\n // real endpoint (host:port via the tcp_connect module for non-HTTP\n // externals \u2014 the __probe_module label routes the module through the\n // scrape config's relabeling, and \"__\"-prefixed labels drop after\n // relabeling so it never pollutes the stored series).\n const probe = resolveProbeTarget(mode, decl, endpoint, value);\n\n await ssm.send(\n new PutParameterCommand({\n Name: `${base}/healthCheck`,\n Type: \"String\",\n Overwrite: true,\n Value: JSON.stringify({ intervalSeconds: 30, timeoutSeconds: 10, hasCustomCheck: false, hasProbe: !!probe }),\n Description: `External service health check config (local mock ${name})`,\n }),\n );\n\n // The file and `hasProbe` must never disagree: a realization that no\n // longer resolves a probe target drops the file it wrote on a previous\n // run, or Prometheus keeps scraping the old target forever.\n const probeFile = localProbeFile(tenant, app, decl.external);\n if (probe) {\n fs.writeFileSync(\n probeFile,\n JSON.stringify(\n [\n {\n targets: [probe.target],\n labels: {\n type: \"external-service\",\n tenant,\n env: LOCAL_ENV,\n app,\n external_service: decl.external,\n target: decl.external,\n // \"__\"-prefixed labels drop after relabeling, so the module\n // selector never pollutes the stored series.\n ...(probe.module ? { __probe_module: probe.module } : {}),\n },\n },\n ],\n null,\n 2,\n ),\n );\n } else {\n localProbesRemove([probeFile]);\n }\n\n const endpointShown =\n endpoint?.url ??\n value.endpoint ??\n value.url ??\n value.baseUrl ??\n (value.host ? `${value.host}${value.port ? `:${value.port}` : \"\"}` : \"credentials\");\n logSuccess(\n `External '${name}' wired (${mode}): ${secretName} \u2192 ${endpointShown}` +\n ` (Hub registration${probe ? \" + uptime probe\" : \"\"})`,\n );\n return probe ? probeFile : undefined;\n}\n", "/**\n * @mesh-tech/api-registry/hub-roles \u2014 the Hub operator role vocabulary, declared\n * once (MESH-2504).\n *\n * This is a contract between three parties that cannot import each other:\n *\n * - `libs/infra-components` DECLARES the roles, by handing\n * `hubOperatorRoleKeys()` to the Hub's Zitadel project. A role that isn't\n * declared is not grantable.\n * - `apps/hub/api` ENFORCES them, in `middleware/authz.ts` `checkPolicy`.\n * - `apps/hub/ui` PRESENTS them, in `lib/auth.server.ts` (which affordances to\n * render) and `lib/api/types.ts` (`UserRole`).\n *\n * plus `libs/mesh-cli`, which seeds the same roles into the local Zitadel, and\n * `apps/hub/ai-assistant`, whose user-creation tools offer them as choices.\n *\n * Before this module the vocabulary was restated in each of those places and kept\n * in sync by comment. Every drift mode was silent: miss the declaration and the\n * role is never grantable; miss the enforcement and it silently cannot write; miss\n * the presentation and the UI reads it as no-role. Nothing threw and no build\n * failed \u2014 the roles claim just didn't contain what someone expected.\n *\n * This module carries no dependencies on purpose. It is reachable from Pulumi\n * (infra-components), from node (hub-api, mesh-cli) and from the browser (hub-ui)\n * because it is plain data plus two pure parsers, and it is a separate export path\n * from the package root so importing it never pulls zod in.\n *\n * ## The two classes\n *\n * Staff roles are GLOBAL: Trabian operators run every estate. `ops` and `admin`\n * may also mutate; `developer` is read-only.\n *\n * Restricted roles are granted per tenant as tenant-keyed role keys\n * (`vendor:<tenant>`, `auditor:<tenant>`). hub-api's `checkPolicy` parses the key\n * and only allows reads on the named tenant. The bare `vendor`/`auditor` keys stay\n * declared so pre-existing grants keep resolving, but a bare key grants nothing\n * tenant-scoped.\n *\n * The model is the MESH-2496 decision, enforced by MESH-2122.\n */\n\n/** Global roles. `ops`/`admin` may mutate; `developer` is read-only. */\nexport const HUB_STAFF_ROLES = ['ops', 'admin', 'developer'] as const;\n\n/** Granted per tenant as `<role>:<tenant>` keys; may never write. */\nexport const HUB_RESTRICTED_ROLES = ['auditor', 'vendor'] as const;\n\nexport type HubStaffRole = (typeof HUB_STAFF_ROLES)[number];\nexport type HubRestrictedRole = (typeof HUB_RESTRICTED_ROLES)[number];\nexport type HubRole = HubStaffRole | HubRestrictedRole;\n\n/**\n * Every base role, staff first. This is the grantable vocabulary before tenant\n * keying \u2014 what the local Zitadel seed registers and what the UI offers when\n * creating a user.\n */\nexport const HUB_BASE_ROLES = [\n ...HUB_STAFF_ROLES,\n ...HUB_RESTRICTED_ROLES,\n] as const satisfies readonly HubRole[];\n\n/**\n * The roles allowed to mutate \u2014 a subset of the staff roles, since a restricted\n * role may never write. Asserted against {@link HUB_STAFF_ROLES} in the tests.\n */\nexport const HUB_WRITE_ROLES = ['ops', 'admin'] as const satisfies readonly HubStaffRole[];\n\n/**\n * Base roles ordered by privilege, highest first, for highest-privilege-wins\n * presentation in the UI.\n *\n * Precedence lives on the presentation side of the contract on purpose: it decides\n * which affordances to render, and the API deliberately returns the raw verified\n * vocabulary. It is declared here rather than in the UI only so that adding a role\n * without ranking it is a test failure instead of a role the UI silently ignores.\n */\nexport const HUB_ROLE_PRIORITY = [\n 'ops',\n 'admin',\n 'developer',\n 'auditor',\n 'vendor',\n] as const satisfies readonly HubRole[];\n\n/**\n * Separates a restricted role from the tenant it is granted on\n * (`vendor:acme`). Shared because the declaration side builds keys with it and\n * the enforcement side parses them with it \u2014 a divergence here would turn every\n * restricted grant into a no-op that still looks provisioned.\n */\nexport const HUB_ROLE_KEY_SEPARATOR = ':';\n\nconst RESTRICTED = new Set<string>(HUB_RESTRICTED_ROLES);\n\n/**\n * The restricted base of a role key (`vendor:acme` \u2192 `vendor`), or null when the\n * key is not a restricted role at all.\n *\n * A bare `vendor`/`auditor` returns its own base: it IS a restricted role, it just\n * names no tenant. Callers that need the tenant ask {@link hubRoleKeyTenant}.\n */\nexport function restrictedRoleBase(roleKey: string): HubRestrictedRole | null {\n const sep = roleKey.indexOf(HUB_ROLE_KEY_SEPARATOR);\n const base = sep === -1 ? roleKey : roleKey.slice(0, sep);\n return RESTRICTED.has(base) ? (base as HubRestrictedRole) : null;\n}\n\n/**\n * The tenant a role key names, or null when the key carries none.\n *\n * Splits on the FIRST separator, so the tenant half is returned whole. That is\n * deliberate rather than incidental: it means a tenant name containing the\n * separator cannot silently read as a different tenant's grant \u2014 and\n * {@link hubOperatorRoleKeys} refuses to mint such a key in the first place.\n */\nexport function hubRoleKeyTenant(roleKey: string): string | null {\n const sep = roleKey.indexOf(HUB_ROLE_KEY_SEPARATOR);\n return sep === -1 ? null : roleKey.slice(sep + 1);\n}\n\n/**\n * The full set of role keys the Hub's Zitadel project declares: the base roles\n * plus a tenant-keyed pair per known tenant, deduped and in a stable order so the\n * Pulumi diff doesn't churn when tenant config reorders.\n */\nexport function hubOperatorRoleKeys(tenants: string[]): string[] {\n const cleaned = [...new Set(tenants.filter((t) => t !== ''))].sort();\n for (const tenant of cleaned) {\n if (tenant.includes(HUB_ROLE_KEY_SEPARATOR)) {\n throw new Error(\n `hubOperatorRoleKeys: tenant name \"${tenant}\" contains the role-key separator ` +\n `\"${HUB_ROLE_KEY_SEPARATOR}\" \u2014 it would parse as a different tenant's grant`,\n );\n }\n }\n return [\n ...HUB_BASE_ROLES,\n ...cleaned.flatMap((tenant) =>\n HUB_RESTRICTED_ROLES.map((role) => `${role}${HUB_ROLE_KEY_SEPARATOR}${tenant}`),\n ),\n ];\n}\n", "/**\n * @mesh-tech/api-registry \u2014 the shared contract between an Integration (producer,\n * infra-components) and a docs/discovery consumer (the hub). Types + path\n * helpers + the entry zod contract; no Pulumi, no Temporal, so either side can\n * import it.\n */\n\nimport { z } from 'zod';\n\n/** The transports an Integration projects. Only enabled surfaces appear. */\nexport interface ApiSurface {\n http?: { url: string };\n nexus?: { endpoint: string; taskQueue: string };\n}\n\n/** One per-owner registry record at `/mesh-platform/{tenant}/{env}/apis/<name>`. */\nexport interface ApiRegistryEntry {\n /** Contract version for forward-compat; absent = 1 (see `parseApiRegistryEntry`). */\n schemaVersion?: number;\n /** Unique key (the Integration name). */\n name: string;\n /** Family \u2014 groups variants (e.g. multiple SilverLake versions) in the hub. */\n provider?: string;\n /** Human version label + selector. */\n version?: string;\n title?: string;\n description?: string;\n surfaces: ApiSurface;\n /** Multi-instance axis: null/absent = single instance. */\n credentials?: { keyedBy?: string | null };\n /** Pointer to the FULL OpenAPI doc in the tenant artifacts bucket. */\n docs: { url: string; contentHash: string };\n /** The deployment's enabled operation subset (availability overlay source). */\n enabledOps: string[];\n}\n\n// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Registry entry zod contract \u2014 consumers parse untrusted SSM JSON through\n// this so producer/consumer drift fails with a clear validation error rather\n// than propagating a malformed entry.\n// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Zod mirror of {@link ApiSurface}. */\nexport const apiSurfaceSchema = z.object({\n http: z.object({ url: z.string().min(1) }).optional(),\n nexus: z.object({ endpoint: z.string().min(1), taskQueue: z.string().min(1) }).optional(),\n});\n\n/**\n * Zod mirror of {@link ApiRegistryEntry}. Unknown keys are stripped (a newer\n * producer may add fields); `schemaVersion` defaults to 1 when absent so\n * consumers can branch on it forward-compatibly.\n */\nexport const apiRegistryEntrySchema = z.object({\n schemaVersion: z.number().int().positive().default(1),\n name: z.string().min(1),\n provider: z.string().optional(),\n version: z.string().optional(),\n title: z.string().optional(),\n description: z.string().optional(),\n surfaces: apiSurfaceSchema,\n credentials: z.object({ keyedBy: z.string().nullish() }).optional(),\n docs: z.object({ url: z.string().min(1), contentHash: z.string().min(1) }),\n enabledOps: z.array(z.string()),\n});\n\n/** A parsed entry: {@link ApiRegistryEntry} with `schemaVersion` resolved. */\nexport type ParsedApiRegistryEntry = z.infer<typeof apiRegistryEntrySchema>;\n\n// Compile-time drift guard: the zod contract must stay assignable to the\n// hand-written interface (which keeps the per-field docs).\nconst _entryContractCheck: ApiRegistryEntry = {} as ParsedApiRegistryEntry;\nvoid _entryContractCheck;\n\n/**\n * Parse an untrusted registry entry (e.g. JSON from SSM). Throws a clear\n * validation error naming the offending fields on producer/consumer drift.\n */\nexport function parseApiRegistryEntry(value: unknown): ParsedApiRegistryEntry {\n const result = apiRegistryEntrySchema.safeParse(value);\n if (!result.success) {\n const detail = result.error.issues\n .map((i) => `${i.path.join('.') || '<root>'}: ${i.message}`)\n .join('; ');\n throw new Error(`api-registry: invalid ApiRegistryEntry \u2014 ${detail}`);\n }\n return result.data;\n}\n\n// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Credential schema \u2014 the shared shape for an integration's outbound creds.\n// Owned here so both infra-components (ExternalService secret) and an\n// IntegrationDefinition reference ONE schema type. Mirrors the secret JSON tree.\n// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** A single credential field (a leaf in the schema tree). */\nexport interface CredentialField {\n /** Human-readable field name shown in CLI/UI. */\n name: string;\n description?: string;\n /** Mask in UI + encrypt at rest. */\n secret?: boolean;\n /** May be skipped. */\n optional?: boolean;\n}\n\n/** A nested group of credential fields. */\nexport interface CredentialGroup {\n name: string;\n description?: string;\n fields: Record<string, CredentialField | CredentialGroup>;\n}\n\nexport type CredentialEntry = CredentialField | CredentialGroup;\n\n/** A credential schema: field definitions keyed by storage key (the secret JSON shape). */\nexport interface CredentialSchema {\n fields: Record<string, CredentialEntry>;\n}\n\n/** Type guard: is this entry a nested group (vs a leaf field)? */\nexport const isCredentialGroup = (e: CredentialEntry): e is CredentialGroup => 'fields' in e;\n\n/**\n * A reusable, package-exported description of how to integrate one third-party\n * service. The data (infra-safe) half \u2014 `mesh.apps.Integration` consumes this.\n * The runtime factories (`buildApi`/`nexusService`) are added by\n * `@mesh-tech/app-kit`'s `IntegrationRuntime`, which extends this.\n */\nexport interface IntegrationDefinition {\n /** Unique key \u2014 the integration's name. */\n name: string;\n /** Family label \u2014 groups variants (e.g. multiple versions) in the hub. */\n provider?: string;\n version?: string;\n title?: string;\n description?: string;\n /** ExternalService category for the Hub UI (e.g. \"banking_core\"). */\n type?: string;\n /** Outbound credential schema (the secret shape). */\n credentialSchema: CredentialSchema;\n /** Package whose built `dist/openapi.json` is the full OpenAPI doc. */\n docPackage?: string;\n /** Multi-instance key (per-FI); absent = single instance. */\n keyedBy?: string;\n /** Default operation subset; overridable per deployment via ENABLED_OPS. */\n defaultEnabledOps: string[];\n /**\n * Optional surface-mediated health check: a cheap, side-effect-free vendor\n * liveness op. Its presence signals `mesh.apps.Integration` to wire an\n * in-cluster probe at the serve worker's /health, and `serveIntegration` to\n * run an always-on health listener that invokes `op` against the vendor.\n */\n health?: { op: string };\n}\n\n/** Guard: an interpolated SSM path segment must be non-empty and slash-free. */\nfunction assertPathSegment(value: string, label: string): string {\n if (!value || value.includes('/')) {\n throw new Error(\n `api-registry: invalid ${label} ${JSON.stringify(value)} \u2014 ` +\n 'SSM path segments must be non-empty and must not contain \"/\"',\n );\n }\n return value;\n}\n\n/** SSM path of the apis registry root (for GetParametersByPath traversal). */\nexport function apisRegistryRoot(tenant: string, env: string): string {\n return `/mesh-platform/${assertPathSegment(tenant, 'tenant')}/${assertPathSegment(env, 'env')}/apis`;\n}\n\n/** SSM path of one Integration's per-owner entry. */\nexport function apiEntryPath(tenant: string, env: string, name: string): string {\n return `${apisRegistryRoot(tenant, env)}/${assertPathSegment(name, 'name')}`;\n}\n\n/**\n * Overlay availability onto doc entries: an entry is `available` iff its `id`\n * (the operationId) is in the deployment's enabled set. Pure; the full doc is\n * never filtered \u2014 availability is computed, not baked.\n */\nexport function markAvailability<T extends { id: string }>(\n entries: readonly T[],\n enabledOps: Iterable<string>,\n): Array<T & { available: boolean }> {\n const set = new Set(enabledOps);\n return entries.map((e) => ({ ...e, available: set.has(e.id) }));\n}\n\n// Re-exported at the root so consumers whose packaging only supports root\n// imports (the published mesh-cli bundles its workspace deps inline \u2014\n// build-for-publish aliases resolve the root entry file only) can still reach\n// the Hub role vocabulary. The subpath export stays; both are the same module.\nexport * from \"./hub-roles.js\";\n", "/**\n * Zitadel seeding for the `mesh start` local platform \u2014 the `mesh login local`\n * path (P1 critical path, design \u00A72.1 seeding).\n *\n * Mirrors what ZitadelPlatformIdentity provisions in the cloud, via the\n * management REST API using the first-instance machine user's PAT (written to\n * the zitadel_machinekey volume by the compose bootstrap). Org structure\n * follows the approved Zitadel tenant-auth pattern: everything here lives in\n * the PLATFORM org (`mesh` \u2014 platform-layer creds home, named by the\n * compose first-instance config); app tenants get their own orgs, created by\n * `mesh dev --local` (see auth-provision.ts):\n * - project \"mesh-cli\" (pattern naming: project per app \u2014 the CLI is a\n * platform-level client feature)\n * - native OIDC application \"cli\" inside it (PKCE + device code, no\n * secret \u2014 the same shape as ZitadelPlatformIdentity's cliApp, plus\n * devMode for http)\n * - two human test users (dev@local.mesh, ops@local.mesh)\n * - registry parity: /mesh-platform/local/dev/platform/zitadel in the local\n * AWS fabric ({endpoint, cliClientId} \u2014 what `mesh login` SSM discovery\n * reads) and temporal/test-users entries (what `mesh dev test-user` reads)\n * - the `local` CLI login context in ~/.config/mesh/config.json, so\n * `mesh login local` works with zero discovery.\n *\n * Idempotent: search-before-create for project/app, \"already exists\" is\n * success for users, SSM params overwrite.\n */\n\nimport * as fs from \"fs\";\nimport * as os from \"os\";\nimport * as path from \"path\";\nimport { HUB_BASE_ROLES } from \"@mesh-tech/api-registry\";\nimport { logInfo, logSuccess } from \"../../utils/log.js\";\nimport { MeshCliError } from \"../../utils/errors.js\";\nimport { writeContextConfig } from \"../login.js\";\nimport { compose, hubPort, DEFAULT_HUB_PORT } from \"./stack.js\";\nimport { LOCAL_TENANT, LOCAL_ENV } from \"./seed.js\";\n\nexport const ZITADEL_ISSUER = \"http://localhost:8080\";\nexport const LOGIN_CONTEXT = \"local\";\n/** The platform org \u2014 home of platform-layer creds, same name as the cloud\n * platform tenant. Set by ZITADEL_FIRSTINSTANCE_ORG_NAME in the compose;\n * app tenants (incl. the default `local`) get their own orgs on demand. */\nexport const PLATFORM_ORG = \"mesh\";\n/**\n * Approved-pattern naming inside the platform org: project per app\n * (lowercase), application per service/client inside it. The CLI is a\n * platform-level client feature \u2192 project `mesh-cli`, application `cli`.\n * (The cloud's legacy catch-all \"Platform\" project is being retired by the\n * pattern doc's spec items; local starts pattern-true.)\n */\nexport const CLI_PROJECT_NAME = \"mesh-cli\";\nexport const CLI_APP_NAME = \"cli\";\nexport const CLI_REDIRECT_URI = \"http://localhost:9876/callback\";\n/**\n * The Hub's own auth config (pattern-true: the Hub is a platform app \u2192\n * project `hub` in the platform org, application per service). The `ui`\n * application backs the oauth2-proxy that fronts the Hub UI \u2014 the same\n * sidecar topology `mesh.apps.Service` deploys with `auth.provider: \"mesh\"`.\n * Roles ARE the Hub's vocabulary \u2014 imported from the module the deployed Hub's\n * infra declares them from, so a role that exists in the cloud is grantable\n * locally too (MESH-2504). Local seeds the base roles only; the tenant-keyed\n * restricted grants (`vendor:<tenant>`) are a deployed-estate concern.\n */\nexport const HUB_PROJECT_NAME = \"hub\";\nexport const HUB_APP_NAME = \"ui\";\n/** Registered on the seeded Hub app; the default-port URI is always included\n * so a later port switch never strands the app config. Zitadel's devMode only\n * relaxes the https requirement \u2014 every redirect URI must still be registered\n * exactly, so an existing app is RECONCILED (union-merged) on each seed run.\n * Functions, not constants: hubPort() must be read at call time so tests and\n * programmatic callers that set MESH_HUB_PORT after import see the override. */\nexport const hubRedirectUri = (): string => `http://localhost:${hubPort()}/oauth2/callback`;\nexport const HUB_DEFAULT_REDIRECT_URI = `http://localhost:${DEFAULT_HUB_PORT}/oauth2/callback`;\nexport const HUB_ROLES = HUB_BASE_ROLES;\nexport const ZITADEL_SSM_PARAM = `/mesh-platform/${LOCAL_TENANT}/${LOCAL_ENV}/platform/zitadel`;\nexport const TEST_USERS_SSM_PREFIX = `/mesh-platform/${LOCAL_TENANT}/${LOCAL_ENV}/temporal/test-users`;\n\nexport interface LocalTestUser {\n name: string;\n email: string;\n firstName: string;\n lastName: string;\n password: string;\n}\n\n/** Seeded human test users \u2014 plainly-labeled dev-grade credentials. */\nexport const TEST_USERS: LocalTestUser[] = [\n { name: \"dev\", email: \"dev@local.mesh\", firstName: \"Dev\", lastName: \"User\", password: \"LocalDev1!\" },\n { name: \"ops\", email: \"ops@local.mesh\", firstName: \"Ops\", lastName: \"User\", password: \"LocalDev1!\" },\n];\n\n/**\n * The CLI OIDC app payload \u2014 the same shape ZitadelPlatformIdentity creates in\n * the cloud (native, PKCE, device code, JWT access tokens, role assertions),\n * plus devMode so Zitadel accepts the http:// redirect locally.\n */\nexport function buildCliAppPayload() {\n return {\n name: CLI_APP_NAME,\n redirectUris: [CLI_REDIRECT_URI],\n responseTypes: [\"OIDC_RESPONSE_TYPE_CODE\"],\n grantTypes: [\"OIDC_GRANT_TYPE_AUTHORIZATION_CODE\", \"OIDC_GRANT_TYPE_DEVICE_CODE\"],\n appType: \"OIDC_APP_TYPE_NATIVE\",\n authMethodType: \"OIDC_AUTH_METHOD_TYPE_NONE\",\n accessTokenType: \"OIDC_TOKEN_TYPE_JWT\",\n accessTokenRoleAssertion: true,\n idTokenRoleAssertion: true,\n idTokenUserinfoAssertion: true,\n devMode: true,\n };\n}\n\n/** Read the seeder PAT the compose bootstrap wrote to the machinekey volume. */\nexport function readSeederPat(): string {\n const tmp = path.join(fs.mkdtempSync(path.join(os.tmpdir(), \"mesh-zitadel-\")), \"pat.txt\");\n try {\n compose([\"cp\", \"zitadel:/machinekey/pat.txt\", tmp]);\n const pat = fs.readFileSync(tmp, \"utf-8\").trim();\n if (!pat) throw new Error(\"empty PAT file\");\n return pat;\n } catch {\n throw new MeshCliError(\n \"Zitadel seeder PAT not found \u2014 the zitadel volume predates the bootstrap machine user (first-instance settings only apply on the first init).\",\n { remediation: { command: \"mesh stop --destroy && mesh start\" } },\n );\n } finally {\n fs.rmSync(path.dirname(tmp), { recursive: true, force: true });\n }\n}\n\n/** Call the local Zitadel REST API; `orgId` sets the org context header. */\nexport async function api(\n pat: string,\n method: string,\n apiPath: string,\n body?: unknown,\n orgId?: string,\n): Promise<any> {\n const res = await fetch(`${ZITADEL_ISSUER}${apiPath}`, {\n method,\n headers: {\n Authorization: `Bearer ${pat}`,\n \"Content-Type\": \"application/json\",\n ...(orgId ? { \"x-zitadel-orgid\": orgId } : {}),\n },\n body: body === undefined ? undefined : JSON.stringify(body),\n signal: AbortSignal.timeout(15_000),\n });\n const text = await res.text();\n const data = text ? JSON.parse(text) : {};\n if (!res.ok) {\n const err: any = new Error(`Zitadel ${method} ${apiPath} \u2192 ${res.status}: ${data?.message ?? text}`);\n err.status = res.status;\n err.zitadelCode = data?.code;\n throw err;\n }\n return data;\n}\n\nexport const isAlreadyExists = (err: any) =>\n err?.status === 409 || err?.zitadelCode === 6 || /already exists/i.test(err?.message ?? \"\");\n\n/**\n * Shared search-before-create for Zitadel projects: return the existing\n * project's id, else create it. Every ensure*Project in the local seeding\n * and auth-provisioning goes through this.\n */\nexport async function ensureZitadelProject(\n pat: string,\n name: string,\n opts: { orgId?: string; describe?: string; logExisting?: boolean } = {},\n): Promise<string> {\n const search = await api(\n pat,\n \"POST\",\n \"/management/v1/projects/_search\",\n { queries: [{ nameQuery: { name, method: \"TEXT_QUERY_METHOD_EQUALS\" } }] },\n opts.orgId,\n );\n const existing = search?.result?.[0]?.id;\n if (existing) {\n if (opts.logExisting) logInfo(`Zitadel project '${name}' already exists`);\n return existing;\n }\n const created = await api(\n pat,\n \"POST\",\n \"/management/v1/projects\",\n { name, projectRoleAssertion: true },\n opts.orgId,\n );\n logSuccess(`Created Zitadel project '${name}'${opts.describe ? ` (${opts.describe})` : \"\"}`);\n return created.id;\n}\n\n/** Shared name-equals application search; returns the raw app or undefined. */\nexport async function searchZitadelApp(\n pat: string,\n projectId: string,\n name: string,\n orgId?: string,\n): Promise<any | undefined> {\n const search = await api(\n pat,\n \"POST\",\n `/management/v1/projects/${projectId}/apps/_search`,\n { queries: [{ nameQuery: { name, method: \"TEXT_QUERY_METHOD_EQUALS\" } }] },\n orgId,\n );\n return search?.result?.[0];\n}\n\nconst ensureCliProject = (pat: string): Promise<string> =>\n ensureZitadelProject(pat, CLI_PROJECT_NAME, { describe: \"platform client feature\", logExisting: true });\n\nasync function ensureCliApp(pat: string, projectId: string): Promise<string> {\n const existing = (await searchZitadelApp(pat, projectId, CLI_APP_NAME))?.oidcConfig?.clientId;\n if (existing) {\n logInfo(`Zitadel app '${CLI_APP_NAME}' already exists`);\n return existing;\n }\n const created = await api(pat, \"POST\", `/management/v1/projects/${projectId}/apps/oidc`, buildCliAppPayload());\n logSuccess(`Created Zitadel application '${CLI_APP_NAME}' (PKCE + device code)`);\n return created.clientId;\n}\n\nasync function ensureTestUsers(pat: string): Promise<void> {\n for (const user of TEST_USERS) {\n try {\n await api(pat, \"POST\", \"/management/v1/users/human/_import\", {\n userName: user.email,\n profile: {\n firstName: user.firstName,\n lastName: user.lastName,\n displayName: `${user.firstName} ${user.lastName}`,\n },\n email: { email: user.email, isEmailVerified: true },\n password: user.password,\n passwordChangeRequired: false,\n });\n logSuccess(`Created test user ${user.email}`);\n } catch (err) {\n if (isAlreadyExists(err)) {\n logInfo(`Test user ${user.email} already exists`);\n } else {\n throw err;\n }\n }\n }\n}\n\n// \u2500\u2500 Hub auth (oauth2-proxy client) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface HubAuthConfig {\n clientId: string;\n clientSecret: string;\n cookieSecret: string;\n}\n\n/** Where the Hub's oauth2-proxy credentials persist between runs (the local\n * analog of the K8s Secret the Service component creates for the sidecar). */\nexport function hubAuthPath(): string {\n const dir = path.join(os.homedir(), \".cache\", \"mesh\", \"mesh-local\");\n fs.mkdirSync(dir, { recursive: true });\n return path.join(dir, \"hub-auth.json\");\n}\n\nexport function readHubAuth(): HubAuthConfig | null {\n try {\n const parsed = JSON.parse(fs.readFileSync(hubAuthPath(), \"utf-8\"));\n if (parsed?.clientId && parsed?.clientSecret && parsed?.cookieSecret) return parsed;\n return null;\n } catch {\n return null;\n }\n}\n\nconst ensureHubProject = (pat: string): Promise<string> =>\n ensureZitadelProject(pat, HUB_PROJECT_NAME, { describe: \"Hub platform app\" });\n\nasync function ensureHubRoles(pat: string, projectId: string): Promise<void> {\n for (const role of HUB_ROLES) {\n try {\n await api(pat, \"POST\", `/management/v1/projects/${projectId}/roles`, {\n roleKey: role,\n displayName: role,\n });\n logSuccess(`Created Hub role '${role}'`);\n } catch (err) {\n if (!isAlreadyExists(err)) throw err;\n }\n }\n}\n\n/** The slice of Zitadel's OIDC app shape the reconcile below reads. */\ninterface HubOidcApp {\n id: string;\n oidcConfig?: {\n clientId?: string;\n redirectUris?: string[];\n postLogoutRedirectUris?: string[];\n responseTypes?: string[];\n grantTypes?: string[];\n accessTokenType?: string;\n accessTokenRoleAssertion?: boolean;\n idTokenRoleAssertion?: boolean;\n idTokenUserinfoAssertion?: boolean;\n devMode?: boolean;\n };\n}\n\n/** Union-merge the current-port redirect URIs into an existing Hub app's OIDC\n * config. Needed whenever the app was seeded under a different MESH_HUB_PORT:\n * devMode does NOT exempt an unregistered redirect_uri (Zitadel rejects the\n * authorize call with \"redirect_uri is missing in the client configuration\"),\n * it only permits http://. No-op when everything is already registered.\n * Exported for tests. */\nexport async function reconcileHubRedirectUris(\n pat: string,\n projectId: string,\n app: HubOidcApp,\n): Promise<void> {\n const cfg = app?.oidcConfig ?? {};\n const redirectUris = [\n ...new Set([...(cfg.redirectUris ?? []), hubRedirectUri(), HUB_DEFAULT_REDIRECT_URI]),\n ];\n const postLogoutRedirectUris = [\n ...new Set([\n ...(cfg.postLogoutRedirectUris ?? []),\n `http://localhost:${hubPort()}`,\n `http://localhost:${DEFAULT_HUB_PORT}`,\n ]),\n ];\n if (\n redirectUris.length === (cfg.redirectUris ?? []).length &&\n postLogoutRedirectUris.length === (cfg.postLogoutRedirectUris ?? []).length\n ) {\n return;\n }\n // UpdateOIDCAppConfig replaces the whole config \u2014 carry the fields we seed\n // (falling back to the create-time shape; appType/authMethodType are\n // re-asserted to the seeded values). Fields we never seed \u2014 e.g.\n // additionalOrigins, clockSkew, backChannelLogoutUri \u2014 are NOT carried, so\n // anything set out-of-band in the Zitadel console is dropped here. Fine for\n // the local dev app; revisit before reusing against a shared instance.\n await api(pat, \"PUT\", `/management/v1/projects/${projectId}/apps/${app.id}/oidc_config`, {\n redirectUris,\n postLogoutRedirectUris,\n responseTypes: cfg.responseTypes ?? [\"OIDC_RESPONSE_TYPE_CODE\"],\n grantTypes: cfg.grantTypes ?? [\"OIDC_GRANT_TYPE_AUTHORIZATION_CODE\", \"OIDC_GRANT_TYPE_REFRESH_TOKEN\"],\n appType: \"OIDC_APP_TYPE_WEB\",\n authMethodType: \"OIDC_AUTH_METHOD_TYPE_BASIC\",\n accessTokenType: cfg.accessTokenType ?? \"OIDC_TOKEN_TYPE_JWT\",\n accessTokenRoleAssertion: cfg.accessTokenRoleAssertion ?? true,\n idTokenRoleAssertion: cfg.idTokenRoleAssertion ?? true,\n idTokenUserinfoAssertion: cfg.idTokenUserinfoAssertion ?? true,\n devMode: cfg.devMode ?? true,\n });\n logSuccess(`Registered Hub redirect URI http://localhost:${hubPort()}/oauth2/callback (MESH_HUB_PORT)`);\n}\n\n/** Ensure the Hub `ui` web application; heals a lost client secret (Zitadel\n * returns it once \u2014 regenerate when the persisted copy is gone) and keeps the\n * redirect URIs in sync with the configured Hub port. */\nasync function ensureHubApp(\n pat: string,\n projectId: string,\n): Promise<{ clientId: string; clientSecret?: string }> {\n const existing = await searchZitadelApp(pat, projectId, HUB_APP_NAME);\n if (existing) {\n await reconcileHubRedirectUris(pat, projectId, existing);\n const clientId = existing?.oidcConfig?.clientId;\n const persisted = readHubAuth();\n if (persisted && persisted.clientId === clientId) return { clientId };\n const regenerated = await api(\n pat,\n \"POST\",\n `/management/v1/projects/${projectId}/apps/${existing.id}/oidc_config/_generate_client_secret`,\n {},\n );\n logSuccess(`Regenerated Hub UI client secret (local copy was missing)`);\n return { clientId, clientSecret: regenerated.clientSecret };\n }\n const created = await api(pat, \"POST\", `/management/v1/projects/${projectId}/apps/oidc`, {\n name: HUB_APP_NAME,\n redirectUris: [...new Set([hubRedirectUri(), HUB_DEFAULT_REDIRECT_URI])],\n postLogoutRedirectUris: [\n ...new Set([`http://localhost:${hubPort()}`, `http://localhost:${DEFAULT_HUB_PORT}`]),\n ],\n responseTypes: [\"OIDC_RESPONSE_TYPE_CODE\"],\n grantTypes: [\"OIDC_GRANT_TYPE_AUTHORIZATION_CODE\", \"OIDC_GRANT_TYPE_REFRESH_TOKEN\"],\n appType: \"OIDC_APP_TYPE_WEB\",\n authMethodType: \"OIDC_AUTH_METHOD_TYPE_BASIC\",\n accessTokenType: \"OIDC_TOKEN_TYPE_JWT\",\n accessTokenRoleAssertion: true,\n idTokenRoleAssertion: true,\n idTokenUserinfoAssertion: true,\n devMode: true,\n });\n logSuccess(`Created Zitadel application '${HUB_APP_NAME}' (Hub UI web client, code flow)`);\n return { clientId: created.clientId, clientSecret: created.clientSecret };\n}\n\n/** Grant Hub roles: admin@local.mesh + dev get `ops` (full dashboard),\n * ops@local.mesh gets `developer` \u2014 proves per-user role claims. */\nasync function ensureHubGrants(pat: string, projectId: string): Promise<void> {\n const grants: Array<{ email: string; roles: string[] }> = [\n { email: \"admin@local.mesh\", roles: [\"ops\"] },\n { email: \"dev@local.mesh\", roles: [\"ops\"] },\n { email: \"ops@local.mesh\", roles: [\"developer\"] },\n ];\n for (const grant of grants) {\n const search = await api(pat, \"POST\", \"/management/v1/users/_search\", {\n queries: [{ userNameQuery: { userName: grant.email, method: \"TEXT_QUERY_METHOD_EQUALS\" } }],\n });\n const userId = search?.result?.[0]?.id;\n if (!userId) continue;\n try {\n await api(pat, \"POST\", `/management/v1/users/${userId}/grants`, {\n projectId,\n roleKeys: grant.roles,\n });\n logSuccess(`Granted Hub role(s) ${grant.roles.join(\", \")} \u2192 ${grant.email}`);\n } catch (err) {\n if (!isAlreadyExists(err)) throw err;\n }\n }\n}\n\n/** Seed the Hub's auth config; persists oauth2-proxy credentials locally. */\nexport async function seedHubAuth(pat: string): Promise<HubAuthConfig> {\n const projectId = await ensureHubProject(pat);\n await ensureHubRoles(pat, projectId);\n const app = await ensureHubApp(pat, projectId);\n await ensureHubGrants(pat, projectId);\n\n const persisted = readHubAuth();\n // oauth2-proxy wants a RAW 16/24/32-byte cookie secret \u2014 the hosted\n // sidecar uses a 32-char RandomPassword; mirror that.\n const persistedCookie =\n persisted?.cookieSecret && [16, 24, 32].includes(persisted.cookieSecret.length)\n ? persisted.cookieSecret\n : undefined;\n const config: HubAuthConfig = {\n clientId: app.clientId,\n clientSecret: app.clientSecret ?? persisted?.clientSecret ?? \"\",\n cookieSecret:\n persistedCookie ?? (await import(\"crypto\")).randomBytes(16).toString(\"hex\"),\n };\n fs.writeFileSync(hubAuthPath(), JSON.stringify(config, null, 2), { mode: 0o600 });\n return config;\n}\n\n/** Registry parity: what SSM discovery and `mesh dev test-user` read in the cloud. */\nasync function writeRegistryParams(cliClientId: string, awsConfig: object): Promise<void> {\n const { SSMClient, PutParameterCommand } = await import(\"@aws-sdk/client-ssm\");\n const ssm = new SSMClient(awsConfig);\n await ssm.send(\n new PutParameterCommand({\n Name: ZITADEL_SSM_PARAM,\n Type: \"String\",\n Overwrite: true,\n Value: JSON.stringify({ endpoint: ZITADEL_ISSUER, cliClientId }),\n Description: \"Zitadel platform export (seeded by mesh start)\",\n }),\n );\n for (const user of TEST_USERS) {\n await ssm.send(\n new PutParameterCommand({\n Name: `${TEST_USERS_SSM_PREFIX}/${user.name}`,\n Type: \"String\",\n Overwrite: true,\n Value: JSON.stringify({ email: user.email, password: user.password, roles: [] }),\n Description: `Local test user '${user.name}' (dev-grade, seeded by mesh start)`,\n }),\n );\n }\n}\n\nexport interface ZitadelSeedResult {\n projectId: string;\n cliClientId: string;\n hubAuth: HubAuthConfig;\n}\n\nexport async function seedZitadel(awsConfig: object): Promise<ZitadelSeedResult> {\n const pat = readSeederPat();\n const org = await api(pat, \"POST\", \"/admin/v1/orgs/_search\", {\n queries: [{ nameQuery: { name: PLATFORM_ORG, method: \"TEXT_QUERY_METHOD_EQUALS\" } }],\n });\n if (!org?.result?.[0]) {\n throw new MeshCliError(\n `Platform org '${PLATFORM_ORG}' not found \u2014 the zitadel volume predates the org naming.`,\n { remediation: { command: \"mesh stop --destroy && mesh start\" } },\n );\n }\n logSuccess(`Platform org '${PLATFORM_ORG}' ready (platform tenant root \u2014 holds platform-service auth config)`);\n // Zitadel v4 defaults new instances to the login-v2 UI \u2014 a separate\n // container this stack doesn't run. Pin the built-in v1 login so the\n // authorize flow has a page to land on (idempotent; compose sets the\n // same default at first-instance time).\n try {\n await api(pat, \"PUT\", \"/v2/features/instance\", { loginV2: { required: false } });\n } catch {\n // pre-v4 instance or endpoint drift \u2014 v1 login is already the default\n }\n const projectId = await ensureCliProject(pat);\n const cliClientId = await ensureCliApp(pat, projectId);\n await ensureTestUsers(pat);\n // Hub auth AFTER test users exist (role grants target them).\n const hubAuth = await seedHubAuth(pat);\n await writeRegistryParams(cliClientId, awsConfig);\n writeContextConfig(LOGIN_CONTEXT, { issuer: ZITADEL_ISSUER, clientId: cliClientId });\n logSuccess(`Login context '${LOGIN_CONTEXT}' configured \u2192 try: mesh login ${LOGIN_CONTEXT}`);\n return { projectId, cliClientId, hubAuth };\n}\n", "/**\n * App-tenant auth auto-provisioning for the local platform \u2014 the local analog\n * of what the Pulumi components do in the cloud, per the approved Zitadel\n * tenant-auth pattern (Org / Project / Application / Service User):\n *\n * Org = app tenant (ZitadelTenantIdentity parity)\n * Project = one per app, (ZitadelAppIdentity parity \u2014\n * name = authz schema namespace the app IS the authz boundary)\n * Application = one per service inside it (API app, Basic creds)\n * Secret = mesh/{tenant}/{env}/apps/{app}/zitadel/{service}\n * (ministack Secrets Manager \u2014 same canonical path as cloud)\n *\n * `mesh dev --local` calls this on startup so scaffolding + running an app\n * auto-creates its auth config \u2014 no Pulumi deploy, no manual Zitadel steps.\n * Idempotent: search-before-create everywhere; the credential secret is only\n * written when the application is first created (Zitadel returns the secret\n * once).\n */\n\nimport { logInfo, logSuccess } from \"../../utils/log.js\";\nimport { LOCAL_ENV, LOCAL_AWS_CONFIG, registerTenantEnv } from \"./seed.js\";\nimport { api, readSeederPat, PLATFORM_ORG, ensureZitadelProject, searchZitadelApp } from \"./seed-zitadel.js\";\nimport { upsertLocalSecret } from \"./helpers.js\";\n\nexport interface AppTenantAuthArgs {\n /** App tenant (org name), e.g. \"acme\" */\n tenant: string;\n /** App name = project name = authz schema namespace */\n app: string;\n /** Service names \u2192 one API application each (api, worker, \u2026) */\n services: string[];\n /**\n * App-declared project roles (package.json \u2192 mesh.auth.roles). Created on\n * the app's Zitadel project and granted to the local `{app}-m2m` caller so\n * role-scoped services (roles claim \u2192 scopes) accept its tokens.\n */\n roles?: string[];\n}\n\nexport interface ProvisionedAuth {\n orgId: string;\n projectId: string;\n /** Services whose application (and secret) was created this run */\n created: string[];\n}\n\nexport function authSecretPath(tenant: string, app: string, service: string): string {\n return `mesh/${tenant}/${LOCAL_ENV}/apps/${app}/zitadel/${service}`;\n}\n\nasync function ensureOrg(pat: string, name: string): Promise<string> {\n const search = await api(pat, \"POST\", \"/admin/v1/orgs/_search\", {\n queries: [{ nameQuery: { name, method: \"TEXT_QUERY_METHOD_EQUALS\" } }],\n });\n const existing = search?.result?.[0]?.id;\n if (existing) return existing;\n const created = await api(pat, \"POST\", \"/v2/organizations\", { name });\n logSuccess(`Created Zitadel org '${name}' (app tenant)`);\n return created.organizationId;\n}\n\nconst ensureProject = (pat: string, orgId: string, name: string): Promise<string> =>\n ensureZitadelProject(pat, name, { orgId, describe: \"app\" });\n\ntype ServiceAppResult =\n | { created: true; clientId: string; clientSecret: string }\n | { created: false; appId: string; clientId?: string };\n\n/** Ensure the service's API application exists; returns fresh credentials\n * when it was created this run. */\nasync function ensureServiceApp(\n pat: string,\n orgId: string,\n projectId: string,\n service: string,\n): Promise<ServiceAppResult> {\n const existing = await searchZitadelApp(pat, projectId, service, orgId);\n if (existing) {\n return { created: false, appId: existing.id, clientId: existing?.apiConfig?.clientId };\n }\n const created = await api(\n pat,\n \"POST\",\n `/management/v1/projects/${projectId}/apps/api`,\n { name: service, authMethodType: \"API_AUTH_METHOD_TYPE_BASIC\" },\n orgId,\n );\n logSuccess(`Created Zitadel application '${service}' (service)`);\n return { created: true, clientId: created.clientId, clientSecret: created.clientSecret };\n}\n\n/** Ensure the app-declared project roles exist (idempotent). */\nasync function ensureProjectRoles(\n pat: string,\n orgId: string,\n projectId: string,\n roles: string[],\n): Promise<void> {\n if (roles.length === 0) return;\n const existing = await api(\n pat,\n \"POST\",\n `/management/v1/projects/${projectId}/roles/_search`,\n {},\n orgId,\n );\n const have = new Set((existing?.result ?? []).map((r: { key: string }) => r.key));\n for (const key of roles) {\n if (have.has(key)) continue;\n await api(\n pat,\n \"POST\",\n `/management/v1/projects/${projectId}/roles`,\n { roleKey: key, displayName: key },\n orgId,\n );\n logSuccess(`Created project role '${key}'`);\n }\n}\n\n/**\n * Ensure the app's LOCAL M2M caller: a machine user (`{app}-m2m`) with a\n * client-credentials secret, granted the app project (+ declared roles).\n * API applications are resource servers \u2014 they cannot obtain tokens \u2014 so\n * without this there is no way to mint a caller token against the local\n * Zitadel at all. Secret stored at mesh/{tenant}/dev/apps/{app}/zitadel/m2m.\n */\nasync function ensureM2mCaller(\n pat: string,\n tenant: string,\n app: string,\n orgId: string,\n projectId: string,\n roles: string[],\n): Promise<boolean> {\n const userName = `${app}-m2m`;\n const search = await api(\n pat,\n \"POST\",\n \"/management/v1/users/_search\",\n { queries: [{ userNameQuery: { userName, method: \"TEXT_QUERY_METHOD_EQUALS\" } }] },\n orgId,\n );\n let userId: string | undefined = search?.result?.[0]?.id;\n let createdUser = false;\n if (!userId) {\n const created = await api(\n pat,\n \"POST\",\n \"/management/v1/users/machine\",\n { userName, name: `${app} local M2M caller`, accessTokenType: \"ACCESS_TOKEN_TYPE_BEARER\" },\n orgId,\n );\n userId = created.userId as string;\n createdUser = true;\n logSuccess(`Created machine user '${userName}' (local M2M caller)`);\n }\n\n // Grant the project (+ declared roles); on re-runs update the existing\n // grant so newly-declared roles apply.\n try {\n await api(pat, \"POST\", `/management/v1/users/${userId}/grants`, { projectId, roleKeys: roles }, orgId);\n } catch (err) {\n const e = err as { status?: number; message?: string };\n if (e.status !== 409 && !/already exists/i.test(String(e.message))) throw err;\n const grants = await api(\n pat,\n \"POST\",\n \"/management/v1/users/grants/_search\",\n { queries: [{ userIdQuery: { userId } }, { projectIdQuery: { projectId } }] },\n orgId,\n );\n const grantId = grants?.result?.[0]?.id;\n if (grantId && roles.length > 0) {\n try {\n await api(pat, \"PUT\", `/management/v1/users/${userId}/grants/${grantId}`, { roleKeys: roles }, orgId);\n } catch (updateErr) {\n // Zitadel 400s a no-op update (\"User grant has not been changed\",\n // COMMAND-Rs8fy) \u2014 the grant already carries the declared roles.\n // Anything else is real. Must not throw here: aborting mid-provision\n // skips the secret (re-)mint below and leaves callers without creds.\n const ue = updateErr as { message?: string };\n if (!/has not been changed/i.test(String(ue.message))) throw updateErr;\n }\n }\n }\n\n if (createdUser || !(await authSecretExists(tenant, app, \"m2m\"))) {\n const secret = await api(pat, \"PUT\", `/management/v1/users/${userId}/secret`, {}, orgId);\n await writeAuthSecret(tenant, app, \"m2m\", {\n clientId: secret.clientId,\n clientSecret: secret.clientSecret,\n issuer: \"http://localhost:8080\",\n orgId,\n projectId,\n });\n return true;\n }\n return false;\n}\n\nasync function authSecretExists(tenant: string, app: string, service: string): Promise<boolean> {\n const { SecretsManagerClient, GetSecretValueCommand } = await import(\"@aws-sdk/client-secrets-manager\");\n const sm = new SecretsManagerClient(LOCAL_AWS_CONFIG);\n return sm.send(new GetSecretValueCommand({ SecretId: authSecretPath(tenant, app, service) })).then(\n () => true,\n () => false,\n );\n}\n\nasync function writeAuthSecret(\n tenant: string,\n app: string,\n service: string,\n value: Record<string, string>,\n): Promise<void> {\n const name = authSecretPath(tenant, app, service);\n await upsertLocalSecret(name, value);\n logSuccess(`Stored service credentials \u2192 ${name}`);\n}\n\n/**\n * Register the running app in the local platform registry \u2014 the same\n * self-registration path deployed apps use (/mesh-platform/{tenant}/{env}/\n * apps/{app}/meta), so StackPort (and the local Hub once its images land)\n * can visualize local apps.\n */\nexport async function registerLocalApp(\n args: AppTenantAuthArgs & {\n ports?: Record<string, number>;\n /** ExternalService names the app's services consume (ExternalService.link()\n * parity) \u2014 the Hub derives Integrations consumers + uptime from these. */\n links?: string[];\n },\n): Promise<string> {\n const { SSMClient, PutParameterCommand } = await import(\"@aws-sdk/client-ssm\");\n const ssm = new SSMClient(LOCAL_AWS_CONFIG);\n const put = (name: string, value: unknown, description: string) =>\n ssm.send(\n new PutParameterCommand({ Name: name, Type: \"String\", Overwrite: true, Value: JSON.stringify(value), Description: description }),\n );\n\n // The app's tenant + env must be registered for the Hub to list the app.\n await registerTenantEnv(args.tenant);\n\n // Per-stack registration in the exact shape hub-api's SSM assembler reads\n // (stack \"local\" = the mesh dev --local runtime).\n const namespace = `${args.tenant}-${LOCAL_ENV}-${args.app}`;\n const base = `/mesh-platform/${args.tenant}/${LOCAL_ENV}/apps/${args.app}/stacks/local`;\n await put(\n base,\n {\n name: args.app,\n tenant: args.tenant,\n stack: \"local\",\n namespace,\n platform: { name: \"local\", env: LOCAL_ENV },\n },\n `Local app registration for ${args.tenant}/${args.app} (mesh dev --local)`,\n );\n for (const service of args.services) {\n const port = args.ports?.[service];\n const isMock = service.startsWith(\"mock-\");\n await put(\n `${base}/services/${service}`,\n {\n ...(port ? { url: `http://localhost:${port}`, port } : {}),\n replicas: 1,\n tier: \"core\",\n ...(!isMock && args.links?.length ? { links: args.links } : {}),\n },\n `Local service registration (${service})`,\n );\n }\n // Worker registration \u2014 the shape deployed TemporalWorker components\n // write; hub-api discovers a tenant's Temporal namespaces from these, so\n // the tenant-wide workflows view finds local runs without an explicit\n // namespace filter. Template convention: worker services are named so.\n for (const service of args.services) {\n if (!/worker/i.test(service)) continue;\n await put(\n `${base}/workers/${service}`,\n { temporalNamespace: namespace, taskQueue: args.app },\n `Local worker registration (${service})`,\n );\n }\n await put(\n `${base}/meta`,\n { runtime: \"mesh-dev-local\", services: args.services, ports: args.ports ?? {} },\n \"Local run metadata (mesh dev --local)\",\n );\n logSuccess(`Registered app in the local registry \u2192 ${base}`);\n return base;\n}\n\n/**\n * Reconcile the platform registry from Zitadel \u2014 every app-tenant org (and\n * its projects = apps, applications = services) provisioned in Zitadel gets\n * a Hub-readable registration, even if the app hasn't been run since it was\n * provisioned. Zitadel is the auth source of truth; the registry mirrors it,\n * exactly like the cloud where ZitadelTenantIdentity/ZitadelAppIdentity and\n * the app's self-registration both flow from the same deploy. Idempotent:\n * existing per-stack registrations (which carry live ports/URLs from\n * `mesh dev --local`) are never overwritten.\n */\nexport async function reconcileRegistryFromZitadel(): Promise<{ tenants: string[]; apps: number }> {\n const pat = readSeederPat();\n const { SSMClient, GetParameterCommand, PutParameterCommand } = await import(\"@aws-sdk/client-ssm\");\n const ssm = new SSMClient(LOCAL_AWS_CONFIG);\n\n const orgs = await api(pat, \"POST\", \"/admin/v1/orgs/_search\", { query: { limit: 200 } });\n const tenants: string[] = [];\n let apps = 0;\n for (const org of orgs?.result ?? []) {\n const tenant = org?.name;\n // The platform org holds platform-service auth config, not an app tenant.\n if (!tenant || tenant === PLATFORM_ORG) continue;\n await registerTenantEnv(tenant);\n tenants.push(tenant);\n\n const projects = await api(\n pat,\n \"POST\",\n \"/management/v1/projects/_search\",\n { query: { limit: 200 } },\n org.id,\n );\n for (const project of projects?.result ?? []) {\n const app = project?.name;\n if (!app) continue;\n apps++;\n const base = `/mesh-platform/${tenant}/${LOCAL_ENV}/apps/${app}/stacks/local`;\n const exists = await ssm.send(new GetParameterCommand({ Name: base })).then(\n () => true,\n () => false,\n );\n if (exists) continue;\n await ssm.send(\n new PutParameterCommand({\n Name: base,\n Type: \"String\",\n Overwrite: true,\n Value: JSON.stringify({\n name: app,\n tenant,\n stack: \"local\",\n namespace: `${tenant}-${LOCAL_ENV}-${app}`,\n platform: { name: \"local\", env: LOCAL_ENV },\n }),\n Description: `App registration reconciled from Zitadel (${tenant}/${app})`,\n }),\n );\n const applications = await api(\n pat,\n \"POST\",\n `/management/v1/projects/${project.id}/apps/_search`,\n { query: { limit: 100 } },\n org.id,\n );\n for (const application of applications?.result ?? []) {\n const service = application?.name;\n if (!service) continue;\n await ssm.send(\n new PutParameterCommand({\n Name: `${base}/services/${service}`,\n Type: \"String\",\n Overwrite: true,\n Value: JSON.stringify({ replicas: 1, tier: \"core\" }),\n Description: `Service registration reconciled from Zitadel (${service})`,\n }),\n );\n }\n }\n }\n return { tenants, apps };\n}\n\n/**\n * Ensure the app tenant's full auth config exists (org \u2192 project \u2192\n * application-per-service \u2192 credential secrets).\n */\nexport async function ensureAppTenantAuth(args: AppTenantAuthArgs): Promise<ProvisionedAuth> {\n const pat = readSeederPat();\n const orgId = await ensureOrg(pat, args.tenant);\n const projectId = await ensureProject(pat, orgId, args.app);\n const roles = args.roles ?? [];\n await ensureProjectRoles(pat, orgId, projectId, roles);\n const created: string[] = [];\n for (const service of args.services) {\n const result = await ensureServiceApp(pat, orgId, projectId, service);\n if (result.created) {\n await writeAuthSecret(args.tenant, args.app, service, {\n clientId: result.clientId,\n clientSecret: result.clientSecret,\n issuer: \"http://localhost:8080\",\n orgId,\n projectId,\n });\n created.push(service);\n } else if (!(await authSecretExists(args.tenant, args.app, service))) {\n // Zitadel persists across stack restarts but the local secret store is\n // in-memory \u2014 heal the gap by regenerating the application's secret\n // (Zitadel returns it only once, so a lost secret can't be re-read).\n const regenerated = await api(\n pat,\n \"POST\",\n `/management/v1/projects/${projectId}/apps/${result.appId}/api_config/_generate_client_secret`,\n {},\n orgId,\n );\n await writeAuthSecret(args.tenant, args.app, service, {\n clientId: result.clientId ?? \"\",\n clientSecret: regenerated.clientSecret,\n issuer: \"http://localhost:8080\",\n orgId,\n projectId,\n });\n logSuccess(`Regenerated credentials for '${service}' (local secret store was reset)`);\n created.push(service);\n }\n }\n if (await ensureM2mCaller(pat, args.tenant, args.app, orgId, projectId, roles)) {\n created.push(\"m2m\");\n }\n if (created.length === 0) {\n logInfo(`Auth config for ${args.tenant}/${args.app} already provisioned`);\n }\n return { orgId, projectId, created };\n}\n", "/**\n * Local DevOutput source for `mesh dev` (design \u00A75.2, AC C1/C3).\n *\n * Instead of reading a deployed Pulumi stack, synthesize the same DevOutput\n * shape from repo conventions and point every service at the running\n * `mesh start` platform. Zero AWS credentials, zero VPN, zero Pulumi state \u2014\n * the app's code never knows it's local:\n * - Temporal \u2192 localhost:7233, namespace local-dev (seeded)\n * - Postgres \u2192 the local `app` database\n * - Zitadel \u2192 http://localhost:8080 (seeded org/app/users)\n * - SpiceDB \u2192 localhost:50051 (preshared key)\n * - AWS SDK \u2192 ministack via AWS_ENDPOINT_URL (SSM/Secrets/S3 registry)\n *\n * Detection convention = what `mesh create-app` templates emit: immediate\n * subdirectories of the app root whose package.json has a `dev` script\n * (api/, worker/, web/, \u2026); a single-package app root with its own `dev`\n * script becomes one service.\n */\n\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport { isServiceMode, openapiMockCommand } from \"./mocks.js\";\nimport { probeTcp } from \"./helpers.js\";\nimport { MeshCliError } from \"../../utils/errors.js\";\nimport { localAwsEnv, LOCAL_ENV } from \"./seed.js\";\nimport { TEMPORAL_ADDRESS } from \"./seed.js\";\nimport { LOGIN_CONTEXT, ZITADEL_ISSUER } from \"./seed-zitadel.js\";\nimport { authSecretPath } from \"./auth-provision.js\";\nimport { findPackageRoot } from \"./stack.js\";\nimport { getContextConfig } from \"../login.js\";\n\n/** Matches dev.ts's DevEnvVar/DevService/DevOutput shapes (kept structural \u2014\n * dev.ts owns the canonical interfaces). */\ninterface LocalDevEnvVar {\n value: string;\n}\ninterface LocalDevService {\n src: string;\n port: number;\n command: string[];\n env?: Record<string, LocalDevEnvVar>;\n}\nexport interface LocalDevOutput {\n platform: { tenant: string; env: string };\n app?: string;\n stack: string;\n services: Record<string, LocalDevService>;\n tunnels: Record<string, never>;\n}\n\nexport const LOCAL_STACK_NAME = \"local\";\nconst BASE_PORT = 3000;\n\n/**\n * The app's namespace, exactly the name the cloud gives it in K8s AND\n * Temporal ({tenant}-{env}-{app}) \u2014 the Hub resolves both from this one\n * convention, so local runs are addressable with zero translation.\n */\nexport function localAppNamespace(tenant: string, appName: string): string {\n return `${tenant}-${LOCAL_ENV}-${appName}`;\n}\n\n/** The OTLP log shipper (assets/log-shipper.mjs) each local service's\n * launch pipeline pipes through \u2014 ships stdout to the stack's collector\n * with the hosted k8s_* attribution. */\nexport function logShipperPath(): string {\n return path.join(findPackageRoot(), \"assets\", \"log-shipper.mjs\");\n}\n\n/**\n * OTel SDK bootstrap \u2014 the local analog of the OTel Operator's pod\n * injection: when the service ships `@opentelemetry/auto-instrumentations-\n * node` (the templates declare it), the platform injects the `--import`\n * register hook + exporter env, and HTTP/fetch/gRPC spans flow to the\n * stack's collector \u2192 Tempo \u2192 the Hub's Traces views. Apps without the\n * package run untouched.\n */\nexport function autoInstrumentationEnv(appRoot: string, src: string): Record<string, LocalDevEnvVar> {\n const pkgDir = path.join(\"node_modules\", \"@opentelemetry\", \"auto-instrumentations-node\");\n const present =\n fs.existsSync(path.join(appRoot, src, pkgDir)) || fs.existsSync(path.join(appRoot, pkgDir));\n if (!present) return {};\n return {\n NODE_OPTIONS: { value: \"--import @opentelemetry/auto-instrumentations-node/register\" },\n OTEL_TRACES_EXPORTER: { value: \"otlp\" },\n // Logs ship via the launch pipeline; metrics locally come from\n // Prometheus scrapes \u2014 keep the SDK to traces.\n OTEL_METRICS_EXPORTER: { value: \"none\" },\n OTEL_LOGS_EXPORTER: { value: \"none\" },\n OTEL_NODE_DISABLED_INSTRUMENTATIONS: { value: \"fs,dns,net\" },\n };\n}\n\n/** Hosted-parity resource attribution for a local service \u2014 what the\n * in-cluster k8sattributes processor stamps. */\nexport function otelEnv(\n tenant: string,\n appName: string,\n serviceName: string,\n): Record<string, LocalDevEnvVar> {\n const namespace = localAppNamespace(tenant, appName);\n return {\n OTEL_EXPORTER_OTLP_ENDPOINT: { value: \"http://localhost:4318\" },\n OTEL_SERVICE_NAME: { value: serviceName },\n OTEL_RESOURCE_ATTRIBUTES: {\n value: `k8s.namespace.name=${namespace},k8s.deployment.name=${serviceName},k8s.container.name=${serviceName},service.namespace=${appName}`,\n },\n };\n}\n\n/** Endpoints of the running `mesh start` platform, as service env. */\nexport function localPlatformEnv(\n tenant: string,\n appName: string,\n serviceName: string,\n): Record<string, LocalDevEnvVar> {\n const namespace = localAppNamespace(tenant, appName);\n const env: Record<string, LocalDevEnvVar> = {\n TEMPORAL_ADDRESS: { value: TEMPORAL_ADDRESS },\n TEMPORAL_NAMESPACE: { value: namespace },\n TEMPORAL_TASK_QUEUE: { value: appName },\n // OTel wiring, two consumers: instrumented services ship traces/metrics\n // themselves, and the launch pipeline's log shipper reads these to ship\n // stdout logs \u2014 both with the in-cluster k8sattributes attribution.\n ...otelEnv(tenant, appName, serviceName),\n DATABASE_URL: { value: \"postgres://postgres:postgres@localhost:5433/app\" },\n ZITADEL_ISSUER: { value: ZITADEL_ISSUER },\n // The service's own Zitadel M2M credentials (created by ensureAppTenantAuth\n // on session start) \u2014 resolveCredentials(\"zitadel\") picks this up, so apps\n // can hydrate introspection/M2M config the same way they resolve\n // ExternalService links instead of hand-carrying client ids in env files.\n ZITADEL_SECRET_PREFIX: { value: authSecretPath(tenant, appName, serviceName) },\n SPICEDB_ENDPOINT: { value: \"localhost:50051\" },\n SPICEDB_HTTP_ENDPOINT: { value: \"http://localhost:8443\" },\n SPICEDB_PRESHARED_KEY: { value: \"local-dev-key\" },\n MEMCACHED_SERVERS: { value: \"localhost:11211\" },\n MESH_LOCAL: { value: \"1\" },\n MESH_SERVICE: { value: serviceName },\n };\n // Local tokens come from `mesh login local` (the seeded CLI app), so that\n // app's clientId is the audience local APIs should verify. In the cloud,\n // consumers request the API project's audience scope instead.\n const cliClientId = getContextConfig(LOGIN_CONTEXT)?.clientId;\n if (cliClientId) {\n env.AUTH_AUDIENCE = { value: cliClientId };\n }\n for (const [key, value] of Object.entries(localAwsEnv())) {\n env[key] = { value };\n }\n return env;\n}\n\nfunction hasDevScript(dir: string): boolean {\n const pkgPath = path.join(dir, \"package.json\");\n if (!fs.existsSync(pkgPath)) return false;\n try {\n const pkg = JSON.parse(fs.readFileSync(pkgPath, \"utf-8\"));\n return typeof pkg?.scripts?.dev === \"string\";\n } catch {\n return false;\n }\n}\n\n/**\n * Detect runnable services by template convention: immediate subdirectories\n * with a package.json `dev` script; falls back to the app root itself when\n * it is a single-package app.\n */\nexport function detectLocalServices(appRoot: string): Record<string, { src: string }> {\n const services: Record<string, { src: string }> = {};\n for (const entry of fs.readdirSync(appRoot, { withFileTypes: true })) {\n if (!entry.isDirectory() || entry.name.startsWith(\".\") || entry.name === \"node_modules\") continue;\n if (hasDevScript(path.join(appRoot, entry.name))) {\n services[entry.name] = { src: entry.name };\n }\n }\n if (Object.keys(services).length === 0 && hasDevScript(appRoot)) {\n services[path.basename(appRoot)] = { src: \".\" };\n }\n return services;\n}\n\n/** Synthesize the DevOutput `mesh dev` would otherwise read from Pulumi.\n * `tenant` is the app tenant (detectLocalTenant) \u2014 it scopes the app's\n * namespace ({tenant}-{env}-{app}) for Temporal, logs, and traces.\n * `opts.mocks` (mesh dev --externals) appends declared mock services and injects\n * their ExternalService credential prefixes into every app service. */\nexport function buildLocalDevOutput(\n appRoot: string,\n tenant: string,\n opts: { mocks?: Record<string, import(\"./mocks.js\").LocalMockDecl> } = {},\n): LocalDevOutput {\n const detected = detectLocalServices(appRoot);\n const names = Object.keys(detected);\n if (names.length === 0) {\n throw new MeshCliError(\n `No runnable services found under ${appRoot} \u2014 expected subdirectories (api/, worker/, \u2026) with a package.json 'dev' script.`,\n { remediation: { command: \"mesh create-app\" } },\n );\n }\n // App name = project name = authz namespace. Pulumi.yaml `name:` wins\n // (matches getProjectName \u2014 a stack-backed app run with --local must keep\n // its deployed identity), then package.json name, then the basename.\n // Scoped package names (@scu-apps/plaid) are unusable as Temporal/K8s\n // namespaces \u2014 drop the scope.\n let appName = path.basename(appRoot);\n try {\n const pkg = JSON.parse(fs.readFileSync(path.join(appRoot, \"package.json\"), \"utf-8\"));\n if (typeof pkg?.name === \"string\" && pkg.name) appName = pkg.name.replace(/^@[^/]+\\//, \"\");\n } catch {\n // no root package.json \u2014 keep the basename\n }\n const pulumiYaml = path.join(appRoot, \"Pulumi.yaml\");\n if (fs.existsSync(pulumiYaml)) {\n const match = fs.readFileSync(pulumiYaml, \"utf-8\").match(/^name:\\s*(.+)$/m);\n if (match?.[1]?.trim()) appName = match[1].trim();\n }\n const services: Record<string, LocalDevService> = {};\n const mocks = opts.mocks ?? {};\n // Only process/openapi declarations run as mock-{name} services in this\n // orchestration; compose externals are docker-managed and sandbox\n // declarations spawn nothing (dev.ts seeds their credentials directly).\n const mockNames = Object.keys(mocks).filter((name) => isServiceMode(name, mocks[name]!));\n\n // The ExternalService link() contract, synthesized: every app service gets\n // {EXT}_SECRET_PREFIX for each mocked external, so resolveCredentials()\n // runs the exact deployed code path against the locally seeded secret.\n const externalEnv: Record<string, LocalDevEnvVar> = {};\n for (const decl of Object.values(mocks)) {\n if (!decl.external) continue;\n const prefix = decl.external.toUpperCase().replace(/-/g, \"_\");\n externalEnv[`${prefix}_SECRET_PREFIX`] = {\n value: `mesh/${tenant}/${LOCAL_ENV}/external/${decl.external}`,\n };\n }\n\n names.forEach((name, i) => {\n const port = BASE_PORT + i;\n services[name] = {\n src: detected[name]!.src,\n port,\n command: [\"pnpm\", \"dev\"],\n env: {\n // allocatePorts keeps service.port and env.PORT in sync on reallocation\n PORT: { value: String(port) },\n ...localPlatformEnv(tenant, appName, name),\n ...autoInstrumentationEnv(appRoot, detected[name]!.src),\n ...externalEnv,\n },\n };\n });\n\n // Sibling-service URLs \u2014 the local analog of the deployed cross-service\n // wiring (http://{svc}.{namespace}.svc.cluster.local:{port} in-cluster):\n // every app service gets SERVICE_{NAME}_URL for each app service, so code\n // can wire cross-service clients locally without knowing allocated ports.\n // allocatePorts' cross-service localhost:{port} rewrite keeps them in sync\n // when ports are reallocated.\n //\n // This is a PUBLIC, app-facing env contract \u2014 {NAME} is the service's\n // directory name upper-cased, non-[A-Z0-9] \u2192 \"_\". Apps that name their\n // link the same way (events.link({ environmentPrefix: \"SERVICE_EVENTS\" }))\n // read ONE variable deployed and locally, with no isLocal branch.\n // See docs/guides/mesh-dev-local-env.md.\n for (const name of names) {\n const key = `SERVICE_${name.toUpperCase().replace(/[^A-Z0-9]/g, \"_\")}_URL`;\n const url = `http://localhost:${services[name]!.port}`;\n for (const other of names) {\n services[other]!.env![key] = { value: url };\n }\n }\n\n // Declared mocks join the same orchestration (ports, env file, tmux\n // window, log pipeline) as first-class services named mock-{name}.\n mockNames.forEach((name, i) => {\n const decl = mocks[name]!;\n const serviceName = `mock-${name}`;\n const port = decl.port ?? BASE_PORT + names.length + i;\n services[serviceName] = {\n // openapi mode runs Prism from the app root against the spec path.\n src: decl.src ?? \".\",\n port,\n command: decl.openapi ? openapiMockCommand(decl) : (decl.command ?? [\"pnpm\", \"dev\"]),\n env: {\n PORT: { value: String(port) },\n ...otelEnv(tenant, appName, serviceName),\n ...Object.fromEntries(\n Object.entries(decl.env ?? {}).map(([key, value]) => [key, { value }]),\n ),\n },\n };\n });\n\n return {\n platform: { tenant: \"local\", env: \"dev\" },\n app: appName,\n stack: LOCAL_STACK_NAME,\n services,\n tunnels: {},\n };\n}\n\n/**\n * Whether the app is backed by a Pulumi program: its own (Pulumi.yaml or a\n * Pulumi.<stack>.yaml stack config in the app dir), or a monorepo ROOT\n * program above it (walk up to the repo boundary \u2014 .git/pnpm-workspace).\n * Apps like apps/hub deploy via a root program and have no per-app\n * Pulumi.yaml; they must NOT default into `mesh dev` local mode.\n */\nexport function hasStackBacking(appRoot: string): boolean {\n const hasOwn =\n fs.existsSync(path.join(appRoot, \"Pulumi.yaml\")) ||\n fs.readdirSync(appRoot).some((f) => /^Pulumi\\..+\\.yaml$/.test(f));\n if (hasOwn) return true;\n let dir = path.dirname(appRoot);\n while (true) {\n if (fs.existsSync(path.join(dir, \"Pulumi.yaml\"))) return true;\n if (fs.existsSync(path.join(dir, \".git\")) || fs.existsSync(path.join(dir, \"pnpm-workspace.yaml\"))) {\n return fs.existsSync(path.join(dir, \"Pulumi.yaml\"));\n }\n const parent = path.dirname(dir);\n if (parent === dir) return false;\n dir = parent;\n }\n}\n\n/**\n * The app's tenant, for auth provisioning: `mesh:tenant` from the app's\n * Pulumi stack config when present (templates write it), else \"local\".\n */\nexport function detectLocalTenant(appRoot: string): string {\n for (const file of fs.readdirSync(appRoot)) {\n if (!/^Pulumi\\..*\\.yaml$/.test(file)) continue;\n const match = fs\n .readFileSync(path.join(appRoot, file), \"utf-8\")\n .match(/^\\s*mesh:tenant:\\s*[\"']?([A-Za-z0-9-]+)[\"']?\\s*$/m);\n if (match) return match[1]!;\n }\n return \"local\";\n}\n\n/** The local platform must be up before `mesh dev` can wire services to it. */\nexport async function ensureLocalPlatformRunning(): Promise<void> {\n const [temporalUp, fabricUp] = await Promise.all([probeTcp(7233), probeTcp(4566)]);\n if (!temporalUp || !fabricUp) {\n throw new MeshCliError(\n \"The local Mesh platform is not running (mesh dev local mode wires services to it).\",\n { remediation: { command: \"mesh start\" } },\n );\n }\n}\n", "/**\n * Docker runner for `mesh dev --local` (design \u00A75.3, AC C2).\n *\n * The tmux runner stays the default on dev machines; `--runner docker` is\n * for environments where tmux isn't sensible \u2014 CI (the golden-path\n * workflow), headless agents, non-macOS boxes. It renders the SAME\n * synthesized DevOutput into a docker compose project:\n *\n * - one service per DevOutput service, `node:22-bookworm`, the app\n * bind-mounted at /workspace, `pnpm dev` in the service dir\n * - `network_mode: host` \u2014 services reach the `mesh start` platform on\n * localhost exactly like the tmux runner (Linux/CI semantics; on macOS\n * Docker Desktop host networking must be enabled, and host-installed\n * node_modules are platform-specific \u2014 tmux is the right runner there)\n * - per-service env files carrying the identical env contract\n * - logs ship through the same OTLP shipper (mounted from the CLI)\n *\n * Parity: `mesh dev --status|--kill|logs|restart` map to\n * `docker compose ps|down|logs|restart` via the session state's runner.\n */\n\nimport { execFileSync } from \"child_process\";\nimport * as fs from \"fs\";\nimport * as os from \"os\";\nimport * as path from \"path\";\nimport { logShipperPath } from \"./dev-local.js\";\n\n// Digest-pinned so dev-runner containers are reproducible (matches the\n// pinning of the stack's third-party images).\nconst DEV_RUNNER_IMAGE =\n \"node:22-bookworm@sha256:5647be709086c696ff32edaaf1c70cd26d1da6ab2b39c32f3c7b4c4a31957e37\";\n\ninterface RunnerService {\n src: string;\n port: number;\n command: string[];\n env?: Record<string, { value: string }>;\n}\n\nfunction sessionDir(sessionName: string): string {\n const dir = path.join(os.homedir(), \".cache\", \"mesh\", \"mesh-local\", \"dev\", sessionName);\n fs.mkdirSync(dir, { recursive: true });\n return dir;\n}\n\n/** docker env-file format: KEY=VALUE, no quoting, single-line values only. */\nfunction renderDockerEnvFile(env: Record<string, { value: string }>): string {\n const lines: string[] = [];\n for (const [key, entry] of Object.entries(env)) {\n if (entry.value.includes(\"\\n\")) continue; // multi-line values unsupported by env_file\n lines.push(`${key}=${entry.value}`);\n }\n return lines.join(\"\\n\") + \"\\n\";\n}\n\n/** Write the compose project for a dev session; returns the compose file path. */\nexport function writeDevCompose(\n sessionName: string,\n appRoot: string,\n services: Record<string, RunnerService>,\n): string {\n const dir = sessionDir(sessionName);\n const shipper = logShipperPath();\n\n const blocks: string[] = [\n `# Generated by \\`mesh dev --local --runner docker\\` \u2014 do not edit.`,\n `name: ${sessionName}`,\n `services:`,\n ];\n for (const [name, service] of Object.entries(services)) {\n const env = service.env ?? {};\n fs.writeFileSync(path.join(dir, `${name}.env`), renderDockerEnvFile(env), { mode: 0o600 });\n const workdir = path.posix.join(\"/workspace\", service.src === \".\" ? \"\" : service.src);\n const ship = env.OTEL_RESOURCE_ATTRIBUTES\n ? ` 2>&1 | NODE_OPTIONS= node /mesh-assets/log-shipper.mjs`\n : \"\";\n blocks.push(\n ` ${name}:`,\n ` image: ${DEV_RUNNER_IMAGE}`,\n ` network_mode: host`,\n ` working_dir: ${workdir}`,\n ` volumes:`,\n ` - '${appRoot}:/workspace'`,\n ` - '${path.dirname(shipper)}:/mesh-assets:ro'`,\n ` environment:`,\n // node_modules is the HOST's bind-mounted install \u2014 pnpm inside the\n // container must never \"verify\" it and try a purge/reinstall (pnpm\n // \u226510.9's verify-deps-before-run prompts and dies headless; worse, a\n // purge would clobber the host install).\n ` CI: 'true'`,\n ` npm_config_verify_deps_before_run: 'false'`,\n ` env_file:`,\n ` - './${name}.env'`,\n // pipefail: the container's exit code must be the SERVICE's, not the\n // log-shipper's \u2014 otherwise a crashed service reports success (CI).\n ` command: [\"bash\", \"-lc\", \"set -o pipefail; corepack enable >/dev/null 2>&1; { ${service.command.join(\" \")}; }${ship}\"]`,\n ` restart: unless-stopped`,\n );\n }\n const composePath = path.join(dir, \"compose.yml\");\n fs.writeFileSync(composePath, blocks.join(\"\\n\") + \"\\n\");\n return composePath;\n}\n\nfunction composeArgs(sessionName: string, args: string[]): string[] {\n return [\"compose\", \"-p\", sessionName, \"-f\", path.join(sessionDir(sessionName), \"compose.yml\"), ...args];\n}\n\nexport function dockerDevUp(sessionName: string): void {\n execFileSync(\"docker\", composeArgs(sessionName, [\"up\", \"-d\"]), {\n stdio: [\"ignore\", \"inherit\", \"inherit\"],\n });\n}\n\nexport function dockerDevDown(sessionName: string): void {\n execFileSync(\"docker\", composeArgs(sessionName, [\"down\", \"--remove-orphans\"]), {\n stdio: [\"ignore\", \"inherit\", \"inherit\"],\n });\n}\n\nexport function dockerDevPs(sessionName: string): string {\n return execFileSync(\"docker\", composeArgs(sessionName, [\"ps\", \"--format\", \"table {{.Service}}\\t{{.State}}\\t{{.Status}}\"]), {\n encoding: \"utf-8\",\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n }) as unknown as string;\n}\n\nexport function dockerDevLogs(sessionName: string, service: string, tail: number): string {\n return execFileSync(\"docker\", composeArgs(sessionName, [\"logs\", \"--tail\", String(tail), service]), {\n encoding: \"utf-8\",\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n }) as unknown as string;\n}\n\nexport function dockerDevRestart(sessionName: string, service: string): void {\n execFileSync(\"docker\", composeArgs(sessionName, [\"restart\", service]), {\n stdio: [\"ignore\", \"inherit\", \"inherit\"],\n });\n}\n", "/**\n * Stack-selection flag resolution (MESH-2154).\n *\n * `mesh` subcommands historically disagreed on the stack-selection flag:\n * `deploy`/`cluster` use `--stack` (Pulumi-native), while `dev`/`secrets` used\n * `--stage` (the SST-era term the platform has moved off). So `mesh kubectl\n * --stage dev` and `mesh dev --stack \u2026` each errored on muscle memory. We\n * consolidate on `--stack` everywhere and keep `--stage` as a HIDDEN, deprecated\n * alias that still works but warns \u2014 removable after a transition window.\n */\nimport { logWarn } from './log.js';\n\nexport interface StackSelector {\n /** Canonical Pulumi stack name. */\n stack?: string;\n /** @deprecated SST-era alias for {@link StackSelector.stack}; still accepted. */\n stage?: string;\n}\n\n/**\n * Resolve the stack selector, preferring the canonical `--stack` over the\n * deprecated `--stage` alias. Pure: reports whether the deprecated alias supplied\n * the value so the caller can warn. `--stack` wins when both are present.\n */\nexport function resolveStackSelector(opts: StackSelector): {\n stack: string | undefined;\n usedDeprecatedStage: boolean;\n} {\n if (opts.stack != null) return { stack: opts.stack, usedDeprecatedStage: false };\n if (opts.stage != null) return { stack: opts.stage, usedDeprecatedStage: true };\n return { stack: undefined, usedDeprecatedStage: false };\n}\n\nlet warnedOnce = false;\n\n/** Test-only: reset the once-per-process deprecation-warning latch. */\nexport function resetStackFlagWarning(): void {\n warnedOnce = false;\n}\n\n/**\n * Resolve `--stack`/`--stage` to the effective stack for use at a consumption\n * site, warning ONCE per process when the deprecated `--stage` alias supplied it.\n */\nexport function resolveStackOption(opts: StackSelector): string | undefined {\n const { stack, usedDeprecatedStage } = resolveStackSelector(opts);\n if (usedDeprecatedStage && !warnedOnce) {\n warnedOnce = true;\n logWarn(\n '--stage is deprecated; use --stack (the Pulumi-native name). --stage still works for now.',\n );\n }\n return stack;\n}\n", "/**\n * How peers address each other inside a `mesh dev` session (MESH-2597).\n *\n * `mesh dev` allocates local ports and rewrites `localhost:<oldPort>` references\n * across every service's env, which handles the PORT half of the question. The\n * HOST half was never handled: an env var derived from a `link()` renders as\n * `http://<svc>.<ns>.svc.cluster.local:8080`, and that survived untouched even\n * when the service it names was one of the ones just started on this laptop.\n *\n * Observed 2026-08-01: after a relaunch, `studio-ui` held\n * `AGENT_API_INTERNAL_URL=http://studio-api.fub-dev-studio.svc.cluster.local:8080`\n * while `studio-api` was running locally on :40161. The UI's proxy dialled the\n * cluster from the laptop, every request failed `getaddrinfo ENOTFOUND`, and the\n * whole app returned `502 upstream unavailable`.\n *\n * Its own module rather than more of `dev.ts` (already ~3.7k lines) so the\n * rewriting rule is testable without importing the launch path.\n */\n\n/** The subset of a dev service this module reads. */\nexport interface AddressableService {\n port: number;\n /** Empty for a DEPLOYED service \u2014 it is not running here. */\n command?: string[];\n env?: Record<string, { value: string }>;\n}\n\nexport interface AddressableOutput {\n services?: Record<string, AddressableService>;\n}\n\n/**\n * `http(s)://<name>.<namespace>.svc.cluster.local[:port]`.\n *\n * Anchored on the full service name so `studio-api` cannot match\n * `studio-api-worker`, and the name is escaped because it reaches this as data.\n */\nexport function clusterHostPattern(serviceName: string): RegExp {\n const name = serviceName.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n return new RegExp(`https?://${name}\\\\.[a-z0-9-]+\\\\.svc\\\\.cluster\\\\.local(?::\\\\d+)?`, \"g\");\n}\n\n/**\n * Point every reference to a LOCALLY-RUN service at its local port.\n *\n * Only services this session actually runs are rewritten. A deployed-only service\n * (no dev command) keeps its cluster address, because reaching that is the\n * tunnels' job, not this one's \u2014 rewriting it would break the one case that\n * currently works.\n *\n * The namespace is matched rather than resolved: the session already knows which\n * services it started and on which ports, and re-deriving the namespace here\n * would be a second source of truth for something the URL already carries.\n */\nexport function rewriteClusterHostsToLocal(devOutput: AddressableOutput): void {\n const localPorts = new Map<string, number>();\n for (const [name, service] of Object.entries(devOutput.services ?? {})) {\n if (!service.command || service.command.length === 0) continue;\n if (typeof service.port !== \"number\" || service.port <= 0) continue;\n localPorts.set(name, service.port);\n }\n if (localPorts.size === 0) return;\n\n for (const service of Object.values(devOutput.services ?? {})) {\n if (!service.env) continue;\n for (const envVar of Object.values(service.env)) {\n if (typeof envVar.value !== \"string\" || !envVar.value.includes(\".svc.cluster.local\")) continue;\n for (const [name, port] of localPorts) {\n envVar.value = envVar.value.replace(clusterHostPattern(name), `http://localhost:${port}`);\n }\n }\n }\n}\n", "/**\n * `mesh dev doctor` \u2014 preflight + on-demand diagnosis for `mesh dev`.\n *\n * Three layers kept deliberately separate so the bug-prone logic stays pure and\n * unit-testable without network/AWS:\n * 1. Engine + renderers (this section): `aggregateStatus`, `runChecks`,\n * `renderHuman`, `renderJson`.\n * 2. `DoctorContext` builder (resolves role/context/session once).\n * 3. The individual `Check`s (creds, tunnels, ports, \u2026), each returning data.\n *\n * Both `mesh dev doctor` and the `mesh dev` launch preflight call `runChecks`;\n * see MESH-2015 (docs/superpowers/specs/2026-07-08-mesh-dev-doctor-design.md).\n */\n\nimport { execFileSync } from \"node:child_process\";\nimport * as fs from \"node:fs\";\nimport * as net from \"node:net\";\nimport * as path from \"node:path\";\nimport type { SessionState } from \"./dev.js\";\nimport { isPortFree } from \"./dev.js\";\nimport type { ResolvedAwsCreds } from \"../utils/aws-auth.js\";\nimport {\n appUsesMeshPackages,\n probeRegistryToken,\n registryLoginFix,\n} from \"../utils/auth-preflight.js\";\nimport { probeCredentials, isRemoteEnvironment, type CredProbe } from \"./login.js\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type CheckStatus = \"ok\" | \"warn\" | \"error\";\nexport type CheckPhase = \"preflight\" | \"ondemand\";\n\nexport interface CheckResult {\n status: CheckStatus;\n /** One line, present tense. */\n summary: string;\n /** Exact command that fixes it (rendered indented under the summary). */\n remediation?: string;\n /** Optional extra context (PID, TTL, path, \u2026). */\n detail?: string;\n}\n\nexport interface Check {\n /** Stable slug, e.g. `creds`, `tunnels`. */\n id: string;\n /** Human label. */\n title: string;\n /** Which contexts this check runs in. */\n phases: CheckPhase[];\n /** `phase` is the context of THIS run \u2014 checks may bound work tighter in\n * `preflight` (launch path) than in on-demand `mesh dev doctor`. */\n run(ctx: DoctorContext, phase?: CheckPhase): Promise<CheckResult>;\n}\n\nexport interface DoctorContext {\n appRoot: string;\n stack: string;\n sessionName: string;\n /** Resolved deployer role ARN (incl. admin selection), or null if none. */\n deployerRole: string | null;\n /** `derivePlatformContext()` result (the Zitadel context), or null. */\n platformContext: string | null;\n /** How creds were obtained at launch; null when the probe determines it. */\n credMethod: ResolvedAwsCreds[\"method\"] | \"ambient\" | null;\n /** Live session state (allocated ports, tunnels); null pre-launch. */\n sessionState: SessionState | null;\n}\n\n// ============================================================================\n// Engine + renderers (pure)\n// ============================================================================\n\n/** `error` if any error, else `warn` if any warn, else `ok` (empty \u2192 `ok`). */\nexport function aggregateStatus(results: CheckResult[]): CheckStatus {\n if (results.some((r) => r.status === \"error\")) return \"error\";\n if (results.some((r) => r.status === \"warn\")) return \"warn\";\n return \"ok\";\n}\n\n/**\n * Run every check whose `phases` includes `phase`, concurrently. A check that\n * throws is captured as an `error` result rather than aborting the run \u2014 the\n * whole point of doctor is to report, never to crash.\n */\nexport async function runChecks(\n ctx: DoctorContext,\n phase: CheckPhase,\n checks: Check[],\n): Promise<Array<{ check: Check; result: CheckResult }>> {\n const applicable = checks.filter((c) => c.phases.includes(phase));\n return Promise.all(\n applicable.map(async (check) => {\n try {\n return { check, result: await check.run(ctx, phase) };\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return {\n check,\n result: {\n status: \"error\" as const,\n summary: `check '${check.id}' threw: ${msg}`,\n },\n };\n }\n }),\n );\n}\n\nconst ICONS: Record<CheckStatus, string> = { ok: \"\u2713\", warn: \"\u26A0\", error: \"\u2717\" };\n\n/** Human-readable: one line per check + indented remediation when present. */\nexport function renderHuman(\n results: Array<{ check: Check; result: CheckResult }>,\n): string {\n const lines: string[] = [];\n for (const { check, result } of results) {\n lines.push(`${ICONS[result.status]} ${check.title} \u2014 ${result.summary}`);\n if (result.detail) lines.push(` ${result.detail}`);\n if (result.remediation) lines.push(` Fix: ${result.remediation}`);\n }\n return lines.join(\"\\n\");\n}\n\n/** Machine-readable: stable key shape for tooling / future CI. */\nexport function renderJson(\n results: Array<{ check: Check; result: CheckResult }>,\n): string {\n return JSON.stringify(\n {\n status: aggregateStatus(results.map((r) => r.result)),\n checks: results.map(({ check, result }) => ({\n id: check.id,\n status: result.status,\n summary: result.summary,\n // Stable keys for tooling: always present, `null` when absent\n // (JSON.stringify would otherwise drop `undefined`).\n remediation: result.remediation ?? null,\n detail: result.detail ?? null,\n })),\n },\n null,\n 2,\n );\n}\n\n// ============================================================================\n// Check: credentials + TTL (creds)\n// ============================================================================\n\n/** Render a TTL in seconds as a compact human string (\"47m\", \"1h 10m\"). */\nfunction fmtTtl(seconds: number): string {\n if (seconds <= 0) return \"expired\";\n // Round to whole minutes first, then split \u2014 so 11h59.5m carries to \"12h\"\n // rather than rendering \"11h 60m\".\n const totalMin = Math.round(seconds / 60);\n const h = Math.floor(totalMin / 60);\n const m = totalMin % 60;\n if (h > 0) return m > 0 ? `${h}h ${m}m` : `${h}h`;\n return `${m}m`;\n}\n\n/**\n * Pure mapper: a `CredProbe` \u2192 a `CheckResult` with the exact remediation.\n * `headless` selects the device-flow `mesh login` variant (browser flow times\n * out over SSH/tailscale \u2014 see the credential runbook).\n */\nexport function credProbeToResult(\n probe: CredProbe,\n context: string,\n headless: boolean,\n): CheckResult {\n const loginCmd = `mesh login ${context}${headless ? \" --device\" : \"\"}`;\n switch (probe.state) {\n case \"ok\":\n return {\n status: probe.ttlSeconds < 300 ? \"warn\" : \"ok\",\n summary: `deployer creds valid ${fmtTtl(probe.ttlSeconds)}${probe.email ? ` (${probe.email})` : \"\"}`,\n detail: `expires ${probe.expiresAt}`,\n };\n case \"no-session\":\n return {\n status: \"error\",\n summary: `no Zitadel session for ${context}`,\n remediation: loginCmd,\n };\n case \"expired-session\":\n return {\n status: \"error\",\n summary: `Zitadel session for ${context} expired and could not refresh`,\n remediation: loginCmd,\n };\n case \"assume-denied\":\n return {\n status: \"error\",\n summary: \"session valid but AssumeRole denied \u2014 wrong IAM role/policy\",\n detail: probe.detail,\n remediation: `check mesh:deployerRole in the stack config and the role's trust/permissions; re-login if role changed: ${loginCmd}`,\n };\n case \"stale-env-override\":\n return {\n status: \"error\",\n summary:\n \"stale AWS_* env vars would override the self-refreshing login profile\",\n remediation:\n \"unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN\",\n };\n }\n}\n\nexport const credsCheck: Check = {\n id: \"creds\",\n title: \"Credentials\",\n phases: [\"preflight\", \"ondemand\"],\n async run(ctx) {\n // When creds were already resolved (launch preflight passes the method),\n // trust that result \u2014 avoids a second AssumeRole call, and correctly\n // reports the SSO/environment paths that `probeCredentials` (Zitadel-only)\n // would otherwise misdiagnose.\n switch (ctx.credMethod) {\n case \"sso\":\n return {\n status: \"ok\",\n summary: \"using AWS SSO credentials (auto-refresh from SSO cache)\",\n };\n case \"environment\":\n return { status: \"ok\", summary: \"using AWS credentials from environment\" };\n case \"zitadel\":\n return {\n status: \"ok\",\n summary:\n \"using Zitadel deployer credentials (credential_process auto-refresh)\",\n };\n }\n // credMethod null (on-demand doctor, or a failed launch resolution) or\n // 'ambient': determine the real state by probing.\n if (!ctx.platformContext || !ctx.deployerRole) {\n return {\n status: \"warn\",\n summary:\n \"no deployer role/context resolved \u2014 using ambient AWS credentials\",\n detail:\n \"add mesh:deployerRole to the Pulumi stack config to use mesh login credentials\",\n };\n }\n const probe = await probeCredentials(ctx.platformContext, ctx.deployerRole);\n return credProbeToResult(probe, ctx.platformContext, isRemoteEnvironment());\n },\n};\n\n// ============================================================================\n// Check: CodeArtifact registry token (registry) \u2014 MESH-2479\n// ============================================================================\n\n/**\n * Verify the @mesh-tech CodeArtifact token actually works BEFORE long work \u2014\n * an expired token otherwise surfaces minutes later as npm's generic E401\n * (\"try npm login\", which cannot fix a CodeArtifact registry). Warn-level:\n * `mesh dev` itself runs installed code, so a stale token shouldn't block\n * launch \u2014 it should name the fix.\n */\nexport const registryCheck: Check = {\n id: \"registry\",\n title: \"Registry auth\",\n phases: [\"preflight\", \"ondemand\"],\n async run(ctx, phase) {\n // The other preflight checks are fast \u2014 don't let an unreachable\n // registry (offline / VPN off) hold the whole launch for the full\n // on-demand bound. The zero-access local loop must stay snappy.\n const probe = await probeRegistryToken(phase === \"preflight\" ? { timeoutMs: 3_000 } : undefined);\n switch (probe.state) {\n case \"fresh\":\n return { status: \"ok\", summary: \"CodeArtifact token accepted by the @mesh-tech registry\" };\n case \"expired\":\n return {\n status: \"warn\",\n summary:\n \"CodeArtifact token expired/rejected \u2014 installing @mesh-tech packages will fail with E401\",\n detail: probe.detail,\n remediation: registryLoginFix(ctx.platformContext ?? undefined),\n };\n case \"unreachable\":\n return {\n status: \"ok\",\n summary: \"registry unreachable \u2014 CodeArtifact token not verified (offline?)\",\n detail: probe.detail,\n };\n case \"missing\":\n return appUsesMeshPackages(ctx.appRoot)\n ? {\n status: \"warn\",\n summary:\n \"no CodeArtifact auth in ~/.npmrc, but this app depends on @mesh-tech packages \u2014 pnpm install will fail with E401\",\n remediation: registryLoginFix(ctx.platformContext ?? undefined),\n }\n : {\n status: \"ok\",\n summary: \"no CodeArtifact auth configured (needed only to install @mesh-tech packages)\",\n };\n }\n },\n};\n\n// ============================================================================\n// Checks: tmux, ports, worktree\n// ============================================================================\n\n/**\n * Parse `lsof -ti :PORT` + `ps -o comm= -p PID` output into the squatting\n * process. `lsof` may list several PIDs (one per line); we name the first.\n */\nexport function parsePortSquatter(\n lsofOut: string,\n psOut: string,\n): { pid: number; command: string } | null {\n const firstLine = lsofOut.trim().split(\"\\n\")[0]?.trim();\n const pid = Number(firstLine);\n if (!firstLine || !Number.isInteger(pid)) return null;\n const command = psOut.trim().split(\"\\n\")[0]?.trim() || \"unknown\";\n return { pid, command };\n}\n\n/** True when `serviceSrc` lives under (or equals) `repoRoot`. */\nexport function sharesWorktreeRoot(\n serviceSrc: string,\n repoRoot: string,\n): boolean {\n const src = path.resolve(serviceSrc);\n const root = path.resolve(repoRoot);\n return src === root || src.startsWith(root + path.sep);\n}\n\n/** How a service port relates to the live session that should own it. */\nexport type PortOwnership = \"owned\" | \"foreign\" | \"dead\";\n\n/**\n * Pure classification for the on-demand ports check. Given the PID currently\n * listening on a service port (`null` when nothing is) and the set of PIDs in\n * the live session's tmux process tree:\n * - `null` listener \u2192 `dead` (the service isn't running)\n * - listener in the session \u2192 `owned` (healthy \u2014 the session's own svc)\n * - listener outside it \u2192 `foreign` (a real squatter)\n * Mid-session the session's services are *supposed* to hold their ports, so a\n * naive \"occupied \u21D2 squatted\" test misreports a healthy session (MESH-2015).\n */\nexport function classifyPortListener(\n listenerPid: number | null,\n sessionPids: ReadonlySet<number>,\n): PortOwnership {\n if (listenerPid === null) return \"dead\";\n return sessionPids.has(listenerPid) ? \"owned\" : \"foreign\";\n}\n\n/**\n * Pure: expand tmux pane PIDs to the full set of PIDs in their process\n * subtrees, using the output of `ps -eo pid=,ppid=` (each line \"PID PPID\").\n * The roots themselves are included; unparseable lines are skipped.\n */\nexport function collectSessionPids(\n panePids: number[],\n psOut: string,\n): Set<number> {\n const children = new Map<number, number[]>();\n for (const line of psOut.trim().split(\"\\n\")) {\n const [pidStr, ppidStr] = line.trim().split(/\\s+/);\n const pid = Number(pidStr);\n const ppid = Number(ppidStr);\n if (!Number.isInteger(pid) || !Number.isInteger(ppid)) continue;\n const kids = children.get(ppid) ?? [];\n kids.push(pid);\n children.set(ppid, kids);\n }\n const result = new Set<number>();\n const queue = panePids.filter((p) => Number.isInteger(p));\n while (queue.length > 0) {\n const pid = queue.shift() as number;\n if (result.has(pid)) continue;\n result.add(pid);\n for (const child of children.get(pid) ?? []) queue.push(child);\n }\n return result;\n}\n\n/** Identify the process squatting a port; null if it can't be determined. */\nfunction whoHasPort(port: number): { pid: number; command: string } | null {\n try {\n const lsof = execFileSync(\"lsof\", [\"-ti\", `:${port}`], {\n encoding: \"utf8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n });\n const pid = lsof.trim().split(\"\\n\")[0]?.trim();\n if (!pid) return null;\n let ps = \"\";\n try {\n ps = execFileSync(\"ps\", [\"-o\", \"comm=\", \"-p\", pid], {\n encoding: \"utf8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n });\n } catch {\n /* ps failed \u2014 parsePortSquatter falls back to \"unknown\" */\n }\n return parsePortSquatter(lsof, ps);\n } catch {\n return null;\n }\n}\n\n/**\n * Gather every PID in the live session's tmux process trees (pane PIDs plus\n * their descendants). Used to tell the session's own service processes apart\n * from foreign squatters. Returns an empty set when tmux/ps are unavailable or\n * the session has no panes \u2014 the caller then treats occupied ports as\n * unidentified rather than owned.\n */\nfunction sessionProcessTree(sessionName: string): Set<number> {\n let panePids: number[];\n try {\n const out = execFileSync(\n \"tmux\",\n [\"list-panes\", \"-s\", \"-t\", sessionName, \"-F\", \"#{pane_pid}\"],\n { encoding: \"utf8\", stdio: [\"ignore\", \"pipe\", \"ignore\"] },\n );\n panePids = out\n .trim()\n .split(\"\\n\")\n .map((l) => Number(l.trim()))\n .filter((n) => Number.isInteger(n));\n } catch {\n return new Set();\n }\n if (panePids.length === 0) return new Set();\n let psOut = \"\";\n try {\n psOut = execFileSync(\"ps\", [\"-eo\", \"pid=,ppid=\"], {\n encoding: \"utf8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n });\n } catch {\n // No process table \u2014 the pane PIDs themselves are still session-owned.\n return new Set(panePids);\n }\n return collectSessionPids(panePids, psOut);\n}\n\nexport const tmuxCheck: Check = {\n id: \"tmux\",\n title: \"tmux\",\n phases: [\"preflight\", \"ondemand\"],\n async run() {\n try {\n execFileSync(\"which\", [\"tmux\"], { stdio: \"ignore\" });\n return { status: \"ok\", summary: \"installed\" };\n } catch {\n return {\n status: \"error\",\n summary: \"tmux is not installed\",\n remediation: \"brew install tmux\",\n };\n }\n },\n};\n\nexport const portsCheck: Check = {\n id: \"ports\",\n title: \"Ports\",\n phases: [\"preflight\", \"ondemand\"],\n async run(ctx) {\n const services = ctx.sessionState?.devOutput.services;\n if (!services || Object.keys(services).length === 0) {\n // Preflight (no session): ports are validated at allocation/launch time.\n return {\n status: \"ok\",\n summary: \"no session \u2014 ports are checked at allocation time\",\n };\n }\n // Mid-session the session's OWN services should be listening on their\n // allocated ports. Classify each port against the session's process tree so\n // healthy self-owned ports don't read as squatters (MESH-2015).\n const sessionPids = sessionProcessTree(ctx.sessionName);\n const foreign: string[] = []; // held by a process outside the session\n const dead: string[] = []; // nothing listening \u2014 service died/isn't up\n const unknown: string[] = []; // occupied but the owner couldn't be resolved\n for (const [name, svc] of Object.entries(services)) {\n const free = await isPortFree(svc.port);\n const who = free ? null : whoHasPort(svc.port);\n const ownership = classifyPortListener(who?.pid ?? null, sessionPids);\n if (ownership === \"owned\") continue;\n if (ownership === \"foreign\") {\n foreign.push(`${name} :${svc.port} held by ${who!.command} (pid ${who!.pid})`);\n continue;\n }\n // `dead` from the helper (null listener pid): either the port is\n // genuinely free (service down) or it's occupied but the owner couldn't\n // be resolved via lsof.\n if (free) {\n dead.push(`${name} :${svc.port} not listening`);\n } else {\n unknown.push(`${name} :${svc.port} in use (owner unknown)`);\n }\n }\n const total = Object.keys(services).length;\n if (foreign.length === 0 && dead.length === 0 && unknown.length === 0) {\n return {\n status: \"ok\",\n summary: `all ${total} service port(s) owned by this session`,\n };\n }\n const parts: string[] = [];\n if (foreign.length) parts.push(`${foreign.length} squatted by another process`);\n if (dead.length) parts.push(`${dead.length} not listening (service down)`);\n if (unknown.length) parts.push(`${unknown.length} in use by an unidentified process`);\n const remediation =\n foreign.length > 0\n ? \"stop the squatting process (or its SSH tunnel), then `mesh dev restart <svc>`\"\n : dead.length > 0\n ? \"restart the stopped service: `mesh dev restart <svc>`\"\n : \"identify the port owner (`lsof -i :<port>`), then `mesh dev restart <svc>`\";\n return {\n // A real squatter or a down service is actionable \u2192 error; an\n // unidentifiable occupant alone is only a warning.\n status: foreign.length > 0 || dead.length > 0 ? \"error\" : \"warn\",\n summary: `service ports: ${parts.join(\", \")}`,\n detail: [...foreign, ...dead, ...unknown].join(\"; \"),\n remediation,\n };\n },\n};\n\n// ============================================================================\n// Check: config staleness (config-staleness)\n// ============================================================================\n\n/** True when the stack config file changed after the session was launched. */\nexport function isConfigStale(\n configMtimeMs: number,\n startedAtIso: string,\n): boolean {\n return configMtimeMs > Date.parse(startedAtIso);\n}\n\nexport const configStalenessCheck: Check = {\n // Preflight runs *at* launch, so nothing can be stale-relative-to-launch yet\n // \u2014 this only makes sense mid-session.\n id: \"config-staleness\",\n title: \"Config freshness\",\n phases: [\"ondemand\"],\n async run(ctx) {\n const state = ctx.sessionState;\n if (!state) {\n return { status: \"ok\", summary: \"no session \u2014 config read fresh at launch\" };\n }\n const configPath = path.join(ctx.appRoot, `Pulumi.${ctx.stack}.yaml`);\n if (!fs.existsSync(configPath)) {\n return {\n status: \"ok\",\n summary: `no Pulumi.${ctx.stack}.yaml to compare`,\n };\n }\n const mtimeMs = fs.statSync(configPath).mtimeMs;\n if (isConfigStale(mtimeMs, state.startedAt)) {\n return {\n status: \"warn\",\n summary: `Pulumi.${ctx.stack}.yaml changed since launch \u2014 a restart won't pick this up`,\n detail: `config mtime ${new Date(mtimeMs).toISOString()} > session start ${state.startedAt}`,\n remediation: `mesh deploy up --stack ${ctx.stack} && mesh dev`,\n };\n }\n return { status: \"ok\", summary: \"stack config unchanged since launch\" };\n },\n};\n\nexport const worktreeCheck: Check = {\n id: \"worktree\",\n title: \"Worktree\",\n phases: [\"preflight\", \"ondemand\"],\n async run(ctx) {\n const services = ctx.sessionState?.devOutput.services;\n if (!services) {\n return { status: \"ok\", summary: \"no session \u2014 worktree checked at launch\" };\n }\n let repoRoot: string;\n try {\n repoRoot = execFileSync(\"git\", [\"rev-parse\", \"--show-toplevel\"], {\n cwd: ctx.appRoot,\n encoding: \"utf8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n }).trim();\n } catch {\n return {\n status: \"warn\",\n summary: \"could not resolve git worktree root for the app\",\n };\n }\n const foreign = Object.entries(services)\n .filter(([, svc]) => svc.src && !sharesWorktreeRoot(svc.src, repoRoot))\n .map(([name, svc]) => `${name} \u2192 ${svc.src}`);\n if (foreign.length === 0) {\n return {\n status: \"ok\",\n summary: `all services resolve under ${repoRoot}`,\n };\n }\n return {\n status: \"warn\",\n summary: `${foreign.length} service(s) resolve outside this worktree \u2014 you may be running another worktree's code`,\n detail: foreign.join(\"; \"),\n remediation: \"relaunch from this worktree: `mesh dev` (re-reads stack output paths)\",\n };\n },\n};\n\n// ============================================================================\n// Checks: tunnels + temporal (connectivity)\n// ============================================================================\n\n/** Resolve `true` iff a TCP connection to host:port succeeds within `timeoutMs`. */\nexport function canConnect(\n host: string,\n port: number,\n timeoutMs = 800,\n): Promise<boolean> {\n return new Promise((resolve) => {\n const socket = new net.Socket();\n let settled = false;\n const done = (ok: boolean) => {\n if (settled) return;\n settled = true;\n socket.destroy();\n resolve(ok);\n };\n socket.setTimeout(timeoutMs);\n socket.once(\"connect\", () => done(true));\n socket.once(\"timeout\", () => done(false));\n socket.once(\"error\", () => done(false));\n socket.connect(port, host);\n });\n}\n\nfunction isLocalHost(host: string): boolean {\n return host === \"localhost\" || host === \"127.0.0.1\" || host === \"::1\";\n}\n\nexport const tunnelsCheck: Check = {\n // On-demand only: pre-launch the tunnels don't exist yet, and dialing the\n // VPC endpoints they'll use would false-positive on an SSM-only machine.\n id: \"tunnels\",\n title: \"Tunnels\",\n phases: [\"ondemand\"],\n async run(ctx) {\n const tunnels = ctx.sessionState?.devOutput.tunnels;\n if (!tunnels || Object.keys(tunnels).length === 0) {\n return { status: \"ok\", summary: \"no tunnels in this session\" };\n }\n // Only dial the SSM-forwarded (localhost) tunnels \u2014 those are the ones that\n // die with \"broken pipe \u2192 ECONNREFUSED\". VPC-direct tunnels are reachable\n // only over VPN and would false-positive here.\n const local = Object.entries(tunnels).filter(([, t]) => isLocalHost(t.host));\n if (local.length === 0) {\n return {\n status: \"ok\",\n summary: `${Object.keys(tunnels).length} tunnel(s), all VPC-direct (not dialed)`,\n };\n }\n const dead: string[] = [];\n for (const [name, t] of local) {\n if (!(await canConnect(t.host, t.port))) dead.push(`${name} (${t.host}:${t.port})`);\n }\n if (dead.length === 0) {\n return { status: \"ok\", summary: `${local.length} SSM tunnel(s) live` };\n }\n return {\n status: \"error\",\n summary: `${dead.length} SSM tunnel(s) down`,\n detail: dead.join(\"; \"),\n remediation: \"relaunch to re-establish tunnels: `mesh dev`\",\n };\n },\n};\n\nexport const temporalCheck: Check = {\n // On-demand only: reachability depends on the session's tunnel being up.\n id: \"temporal\",\n title: \"Temporal\",\n phases: [\"ondemand\"],\n async run(ctx) {\n const state = ctx.sessionState;\n const t = state?.devOutput.tunnels[\"temporal\"];\n if (!state || !t) {\n return { status: \"ok\", summary: \"no temporal tunnel in this session\" };\n }\n const addr = `${t.host}:${t.port}`;\n if (!(await canConnect(t.host, t.port))) {\n return {\n status: \"error\",\n summary: `Temporal frontend unreachable at ${addr}`,\n remediation: \"tunnel likely down \u2014 relaunch: `mesh dev`\",\n };\n }\n const p = state.devOutput.platform;\n const app = state.devOutput.app;\n if (!p || !app) {\n return { status: \"ok\", summary: `frontend reachable at ${addr} (namespace unknown)` };\n }\n const namespace = `${p.tenant}-${p.env}-${app}`;\n try {\n const { Connection } = await import(\"@temporalio/client\");\n const connection = await Connection.connect({\n address: addr,\n connectTimeout: \"3s\",\n });\n try {\n await connection.workflowService.describeNamespace({ namespace });\n return { status: \"ok\", summary: `frontend reachable; namespace ${namespace} present` };\n } finally {\n await connection.close().catch(() => {});\n }\n } catch (err) {\n const code = (err as { code?: number }).code;\n // gRPC status: 5 NOT_FOUND, 7 PERMISSION_DENIED, 16 UNAUTHENTICATED.\n if (code === 5) {\n return {\n status: \"error\",\n summary: `namespace ${namespace} not found on the server`,\n remediation: `verify the app is deployed to this env (mesh deploy up --stack ${ctx.stack})`,\n };\n }\n if (code === 7 || code === 16) {\n return {\n status: \"ok\",\n summary: `frontend reachable; namespace ${namespace} auth-gated (not verified)`,\n };\n }\n return {\n status: \"warn\",\n summary: \"frontend reachable but namespace check errored\",\n detail: err instanceof Error ? err.message : String(err),\n };\n }\n },\n};\n\n// ============================================================================\n// Registry + runner\n// ============================================================================\n\n/** All checks, in display order. */\nexport const ALL_CHECKS: Check[] = [\n tmuxCheck,\n credsCheck,\n registryCheck,\n configStalenessCheck,\n portsCheck,\n worktreeCheck,\n tunnelsCheck,\n temporalCheck,\n];\n\n/**\n * Run the full on-demand doctor against a prebuilt context, print the report,\n * and return the aggregate status. The caller (the `mesh dev doctor`\n * subcommand) owns process exit.\n */\nexport async function runDoctor(\n ctx: DoctorContext,\n opts: { json: boolean },\n): Promise<CheckStatus> {\n const results = await runChecks(ctx, \"ondemand\", ALL_CHECKS);\n const status = aggregateStatus(results.map((r) => r.result));\n if (opts.json) {\n console.log(renderJson(results));\n } else {\n console.log(renderHuman(results));\n console.log(`\\n${ICONS[status]} overall: ${status}`);\n }\n return status;\n}\n", "/**\n * Per-worktree identity for collision-free concurrent `mesh dev` (MESH-2013).\n *\n * Running `mesh dev` in several git worktrees at once collides on ports, tmux\n * session names, tmpdir session state, and env-file dirs \u2014 because every one of\n * those derives from the app's Pulumi project name, which is identical across\n * worktrees. This module derives ONE deterministic token per worktree (from its\n * path) that the dev launcher threads through all of those so worktrees can't\n * step on each other.\n *\n * TASK QUEUES are unique by construction \u2014 `taskQueueSuffix` is `-${token}` and\n * the token carries the 4-hex path hash. SESSION NAMES are not: the tmux name is\n * `${projectName}-${slug}` (slug only), and the state file + env dir derive from\n * it, so two linked worktrees whose basenames sanitize to the same slug (e.g.\n * `.worktrees/MESH-2375` and `~/scratch/mesh-2375`) share all three. PORTS are\n * not either: the block is a hash bucketed into NUM_PORT_BLOCKS-1 slots and is\n * additionally scoped by app \u2014 see `withAppScopedPortBlock` below for what that\n * does and does not guarantee.\n *\n * The PRIMARY checkout (the repo's main working tree) keeps its historical\n * behavior \u2014 empty token, port block 0 (preferred ports), no session suffix \u2014\n * so existing muscle memory is preserved. Only LINKED worktrees get offsets.\n *\n * Pure helpers (`sanitizeSlug`, `worktreeHash`, `portBlockFor`, `blockBasePort`)\n * are git-free and unit-tested; `resolveWorktreeIdentity` shells to git via an\n * injectable runner so it can be tested without a real repo.\n */\nimport { execFileSync } from \"node:child_process\";\nimport * as crypto from \"node:crypto\";\nimport * as path from \"node:path\";\n\n/** Number of distinct port blocks (block 0 reserved for the primary checkout). */\nexport const NUM_PORT_BLOCKS = 64;\n/** First port of block 1; block 0 uses the app's preferred ports, not this range. */\nexport const PORT_BLOCK_BASE = 40000;\n/** Ports reserved per worktree block (split into service + tunnel sub-ranges). */\nexport const PORT_BLOCK_SIZE = 40;\n/** Service ports occupy `[base, base+SERVICE_SUBRANGE)`; tunnels take the rest. */\nexport const PORT_BLOCK_SERVICE_SUBRANGE = 24;\n\nexport interface WorktreeIdentity {\n /** Absolute path to this worktree's root (git top-level). */\n worktreeRoot: string;\n /** True for the repo's primary checkout; false for a linked `git worktree`. */\n isPrimary: boolean;\n /** Human-readable sanitized basename of the worktree root (e.g. \"design-registry\"). */\n slug: string;\n /** 4 hex chars of sha256(worktreeRoot) \u2014 disambiguates same-named worktrees. */\n hash: string;\n /** \"\" for the primary checkout; else `${slug}-${hash}`. */\n token: string;\n /** 0 for primary (preferred ports); 1..NUM_PORT_BLOCKS-1 for linked worktrees. */\n portBlock: number;\n /** \"\" for primary; else `-${token}` \u2014 appended to Temporal/Nexus task queues (Tier 2). */\n taskQueueSuffix: string;\n}\n\n/** Lowercase, hyphenate, strip non-alphanumerics; never empty. */\nexport function sanitizeSlug(name: string): string {\n const s = name\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n return s || \"wt\";\n}\n\n/** Stable 4-hex-char fingerprint of a worktree's absolute path. */\nexport function worktreeHash(worktreeRoot: string): string {\n return crypto.createHash(\"sha256\").update(worktreeRoot).digest(\"hex\").slice(0, 4);\n}\n\n/**\n * Map a worktree hash to a port block. Primary \u2192 0 (preferred ports).\n * Linked \u2192 deterministic 1..NUM_PORT_BLOCKS-1 (stable across runs for the same\n * worktree path, so ports don't drift between launches).\n */\nexport function portBlockFor(hash: string, isPrimary: boolean): number {\n if (isPrimary) return 0;\n const n = parseInt(hash, 16);\n return 1 + (n % (NUM_PORT_BLOCKS - 1));\n}\n\n/** First port of a block (block 0 has no dedicated range \u2014 callers use preferred ports). */\nexport function blockBasePort(block: number): number {\n return PORT_BLOCK_BASE + block * PORT_BLOCK_SIZE;\n}\n\n/**\n * Identity whose PORT BLOCK is derived from (worktree, app) \u2014 every non-port\n * field stays worktree-scoped. A repo can hold several apps whose `mesh dev`\n * sessions run CONCURRENTLY (e.g. scu-mesh-apps' plaid-token-manager +\n * plaid-reporting); with a per-worktree block they draw the same ports, and\n * the availability probe alone races services that are still booting and\n * haven't bound yet \u2014 both sessions allocated 41800 in the wild. Same\n * philosophy as the per-worktree blocks of MESH-2013.\n *\n * NOT disjoint by construction: `portBlockFor` buckets a hash into\n * NUM_PORT_BLOCKS-1 slots, so two (worktree, app) pairs CAN land on the same\n * block \u2014 and app-scoping raises the entity count from #worktrees to\n * #worktrees x #apps, which makes that likelier. Sibling apps in one worktree\n * (the case this fixes) are disjoint by default; the in-block probe and the\n * ephemeral fallback in `allocatePorts` remain the backstop for a collision.\n *\n * Primary checkouts keep preferred-port semantics (block 0) \u2014 sibling apps\n * there still share preferred ports and rely on that probe.\n */\nexport function withAppScopedPortBlock(wt: WorktreeIdentity, appRoot: string): WorktreeIdentity {\n if (wt.isPrimary) return wt;\n const appHash = worktreeHash(`${wt.worktreeRoot}#${path.resolve(appRoot)}`);\n return { ...wt, portBlock: portBlockFor(appHash, false) };\n}\n\n/**\n * Stack name for `mesh stack init --worktree` (MESH-2013 Slice 3): append the\n * worktree token so concurrent worktrees deploy to distinct stacks. The SSM\n * export paths (`apps/{app}/stacks/{stack}/...`), Temporal namespace\n * (`{tenant}-{stack}-{app}`), and Nexus endpoint name all derive from the stack\n * name, so one discriminator isolates all three. The primary checkout has an\n * empty token \u2192 the base name is returned unchanged (it IS the canonical stack).\n */\n/** Max chars of the worktree slug that reach a stack name. Deploy-time surfaces\n * (Temporal namespace `{tenant}-{stack}-{app}`, Nexus endpoint names) have\n * provider length limits, so we cap the human-readable slug here; the 4-hex hash\n * still guarantees uniqueness. (The local-only token \u2014 tmux/ports \u2014 is uncapped.) */\nexport const STACK_SLUG_MAX = 16;\n\nexport function worktreeStackName(baseName: string, wt: WorktreeIdentity): string {\n if (!wt.token) return baseName;\n const cappedSlug = wt.slug.slice(0, STACK_SLUG_MAX).replace(/-+$/, \"\");\n return `${baseName}-${cappedSlug}-${wt.hash}`;\n}\n\n/**\n * True when `stackName` would collide across worktrees: we're in a LINKED\n * worktree (non-empty token) but the stack name doesn't carry that token \u2014 so a\n * concurrent `pulumi up` from another worktree on the same name hits identical\n * SSM export paths / Temporal namespace. Drives the `mesh deploy` warning.\n */\nexport function stackNeedsWorktreeIsolation(stackName: string, wt: WorktreeIdentity): boolean {\n // The 4-hex hash is the stable discriminator present in every worktree stack\n // name (`worktreeStackName` ends with `-${hash}`), and survives the slug cap \u2014\n // so match on it rather than the full (uncapped) token.\n return !!wt.token && !stackName.endsWith(`-${wt.hash}`);\n}\n\ntype GitRunner = (args: string[], cwd: string) => string;\n\nconst defaultGitRunner: GitRunner = (args, cwd) =>\n execFileSync(\"git\", args, { cwd, encoding: \"utf-8\", stdio: [\"ignore\", \"pipe\", \"ignore\"] }).trim();\n\n/**\n * Resolve the worktree identity for a given cwd. Returns a primary-checkout\n * identity (token \"\", block 0) when not inside a git repo, so non-repo/edge\n * cases degrade to today's behavior rather than throwing.\n */\nexport function resolveWorktreeIdentity(\n cwd: string = process.cwd(),\n gitRunner: GitRunner = defaultGitRunner,\n): WorktreeIdentity {\n let worktreeRoot: string;\n let isPrimary = true;\n try {\n worktreeRoot = path.resolve(gitRunner([\"rev-parse\", \"--show-toplevel\"], cwd));\n // The common git dir is `<primary-worktree>/.git`; its parent is the primary\n // checkout. A linked worktree's top-level differs from that parent.\n const commonDir = gitRunner([\"rev-parse\", \"--git-common-dir\"], cwd);\n const primaryRoot = path.resolve(path.dirname(path.resolve(cwd, commonDir)));\n isPrimary = worktreeRoot === primaryRoot;\n } catch {\n // Not a git repo (or git unavailable) \u2014 behave as the primary checkout.\n return {\n worktreeRoot: path.resolve(cwd),\n isPrimary: true,\n slug: sanitizeSlug(path.basename(path.resolve(cwd))),\n hash: worktreeHash(path.resolve(cwd)),\n token: \"\",\n portBlock: 0,\n taskQueueSuffix: \"\",\n };\n }\n\n const slug = sanitizeSlug(path.basename(worktreeRoot));\n const hash = worktreeHash(worktreeRoot);\n const token = isPrimary ? \"\" : `${slug}-${hash}`;\n return {\n worktreeRoot,\n isPrimary,\n slug,\n hash,\n token,\n portBlock: portBlockFor(hash, isPrimary),\n taskQueueSuffix: token ? `-${token}` : \"\",\n };\n}\n", "/**\n * `mesh dev __token-server <port> <context>` \u2014 the producer side of the\n * self-refreshing dev-user token seam (MESH-2039).\n *\n * `mesh dev` launches this in its own tmux window. On each GET it mints a\n * currently-valid dev-user token (via the existing `getValidToken` refresh\n * path, which silently re-mints from the refresh token and rewrites the shared\n * cache) and returns it on loopback. Consumers poll it (agent-app-kit's\n * dev-user-token provider) so local apps survive past the ~1h Zitadel horizon\n * without a `mesh dev` restart. Bound to 127.0.0.1 only; dev-only.\n */\n\nimport * as http from \"node:http\";\nimport { getValidToken, readCredentials, decodeJwtPayload } from \"./login.js\";\nimport { logInfo, logWarn } from \"../utils/log.js\";\n\nexport interface TokenServerDeps {\n getValidToken: (context: string) => Promise<string | null>;\n readCredentials: (\n context: string,\n ) => { accessToken: string; expiresAt: string; email?: string } | null;\n decodeJwtPayload: (jwt: string) => Record<string, unknown>;\n}\n\n/**\n * Pure request handler. 200 with the fresh token pair on success; 503 when the\n * token can't be minted (refresh token lapsed \u2014 the MESH-2035 boundary), which\n * consumers treat as \"keep last good / fall back to the static env snapshot\".\n */\nexport async function handleTokenRequest(\n context: string,\n deps: TokenServerDeps,\n): Promise<{ status: number; body: unknown }> {\n const idToken = await deps.getValidToken(context);\n const creds = idToken ? deps.readCredentials(context) : null;\n if (!idToken || !creds) return { status: 503, body: { error: \"token-unavailable\" } };\n const payload = deps.decodeJwtPayload(idToken);\n return {\n status: 200,\n body: {\n idToken,\n accessToken: creds.accessToken,\n sub: (payload.sub as string) ?? undefined,\n email: creds.email ?? (payload.email as string) ?? undefined,\n expiresAt: creds.expiresAt,\n },\n };\n}\n\n/**\n * Refresh the served token this far before it actually expires, so a consumer\n * polling on its own cadence (~60s) always fetches a token that outlives its\n * next poll \u2014 closing the ~once-per-hour self-healing 401 window.\n */\nconst REFRESH_MARGIN_MS = 120_000;\n\n/** Start the loopback token server. Never resolves (runs until the window dies). */\nexport async function startTokenServer(port: number, context: string): Promise<void> {\n const deps: TokenServerDeps = {\n getValidToken: (c) => getValidToken(c, { marginMs: REFRESH_MARGIN_MS }),\n readCredentials,\n decodeJwtPayload,\n };\n const server = http.createServer((_req, res) => {\n void (async () => {\n try {\n const { status, body } = await handleTokenRequest(context, deps);\n res.writeHead(status, { \"content-type\": \"application/json\" });\n res.end(JSON.stringify(body));\n } catch (e) {\n res.writeHead(500, { \"content-type\": \"application/json\" });\n res.end(JSON.stringify({ error: (e as Error).message }));\n }\n })();\n });\n server.on(\"error\", (e) => logWarn(`token-server error: ${e.message}`));\n await new Promise<void>((resolve) => server.listen(port, \"127.0.0.1\", resolve));\n logInfo(`dev-user token-server on http://127.0.0.1:${port} (context ${context})`);\n await new Promise(() => {}); // run forever\n}\n", "/**\n * mesh dev \u2014 Pulumi-output-driven local development orchestrator\n *\n * Reads `pulumi stack output dev --json` to discover services and VPC endpoints,\n * then launches each service's dev command in a tmux window.\n * Requires VPN connection for direct access to VPC resources.\n *\n * Usage:\n * mesh dev Start all services, attach tmux\n * mesh dev --headless Start without attaching\n * mesh dev --kill Stop everything\n * mesh dev --status Show service health (--json for structured)\n * mesh dev logs <service> Tail a service's output\n * mesh dev restart <svc> Restart a single service\n */\n\nimport { execFileSync, spawn, spawnSync } from 'child_process';\nimport * as fs from 'fs';\nimport * as net from 'net';\nimport * as os from 'os';\nimport * as path from 'path';\nimport { Command, Option } from 'commander';\nimport { SecretsManagerClient, GetSecretValueCommand } from '@aws-sdk/client-secrets-manager';\nimport {\n logInfo,\n logSuccess,\n logError,\n logWarn,\n isVpnConnected,\n getTailscaleInfo,\n headscaleDnsConfig,\n registerDnsRecords,\n unregisterDnsRecords,\n readDnsRecords,\n getPlatformBastionInfo,\n} from '../utils/index.js';\nimport type { DnsRecord, HeadscaleDnsConfig } from '../utils/index.js';\nimport {\n derivePlatformContext,\n renderCredentialProcessProfile,\n resolveAwsCredentials,\n resolveStableMeshBin,\n selectRoleForCaller,\n type ResolvedAwsCreds,\n} from '../utils/aws-auth.js';\nimport { readCredentials, getContextConfig, probeCredentials, getValidToken } from './login.js';\nimport { resolveVpnJoinBroker, mintPreAuthKey } from '../utils/vpn-join.js';\nimport { credProbeToPreflightError } from '../utils/pulumi-run.js';\nimport {\n startTailscaleTunnels,\n tailscaleAvailable,\n daemonState as tailscaleDaemonState,\n readTunnelState as readTailscaleState,\n readDaemonMeta as readTailscaleDaemonMeta,\n} from '../utils/tailscale.js';\nimport { pulumiStackOutput, readStackConfig } from '../utils/pulumi.js';\nimport {\n ensureKubeconfig,\n resolveHubPlatformName,\n sessionKubeconfigPath,\n} from '../utils/kubeconfig.js';\nimport { resolveTemporalAuth } from '../utils/temporal-auth.js';\nimport { probeTcpReachable, probeConnectionHolds } from '../utils/reachability.js';\nimport { fingerprintWorkflowSource } from '../utils/workflow-fingerprint.js';\nimport { buildLaunchCommand, envFileName, waitForPort, writeEnvFile } from './dev-launch.js';\nimport { buildLocalDevOutput, detectLocalTenant, ensureLocalPlatformRunning, hasStackBacking, localAppNamespace } from './local/dev-local.js';\nimport { ensureAppTenantAuth, registerLocalApp } from './local/auth-provision.js';\nimport { localAwsEnv, ensureTemporalNamespace } from './local/seed.js';\nimport {\n composeExternalUp,\n composeExternalsDown,\n externalMode,\n localProbesRemove,\n parseExternalsSelection,\n readLocalMocks,\n seedLocalMock,\n type ComposeExternalRef,\n type ExternalMode,\n type LocalMockDecl,\n} from './local/mocks.js';\nimport { logShipperPath } from './local/dev-local.js';\nimport { writeDevCompose, dockerDevUp, dockerDevDown, dockerDevPs, dockerDevLogs, dockerDevRestart } from './local/docker-runner.js';\nimport { MeshCliError } from '../utils/errors.js';\nimport { resolveStackOption } from '../utils/stack-flag.js';\nimport { rewriteClusterHostsToLocal } from './peer-addressing.js';\nimport {\n ALL_CHECKS,\n aggregateStatus,\n renderHuman,\n runChecks,\n runDoctor,\n type DoctorContext,\n} from './dev-doctor.js';\nimport {\n resolveWorktreeIdentity,\n withAppScopedPortBlock,\n blockBasePort,\n PORT_BLOCK_SERVICE_SUBRANGE,\n type WorktreeIdentity,\n} from '../utils/worktree-identity.js';\n\n// ============================================================================\n// Types\n// ============================================================================\n\ninterface DevEnvVar {\n value: string;\n /** If set, env var value uses the named tunnel's host:port */\n tunnel?: string;\n}\n\ninterface DevService {\n src: string;\n port: number;\n command: string[];\n env?: Record<string, DevEnvVar>;\n}\n\n/** VPC-accessible endpoint for VPN direct access */\ninterface DevTunnel {\n /** VPC hostname (RDS endpoint, NLB hostname, etc.) */\n host: string;\n /** Port number */\n port: number;\n}\n\ninterface DevSecret {\n /** Secrets Manager secret name */\n secretName: string;\n /** Maps secret JSON keys \u2192 env var names to inject into services */\n envMapping: Record<string, string>;\n}\n\nexport interface DevOutput {\n /**\n * Platform context. `tenant` is the APP tenant (Temporal namespace auth +\n * encoding key). `name` is the HUB platform name (bastion + headscale DNS,\n * which live in the hub for shared tenants); falls back to \"mesh\".\n */\n platform?: { tenant: string; name?: string; env: string };\n /** App name (e.g., \"hub\") */\n app?: string;\n /** Pulumi stack name (e.g., \"dev\", \"feature-xyz\") */\n stack?: string;\n services: Record<string, DevService>;\n tunnels: Record<string, DevTunnel>;\n /** Secrets to resolve from Secrets Manager at dev startup */\n secrets?: Record<string, DevSecret>;\n}\n\ninterface DevOptions {\n app?: string;\n stage?: string;\n headless?: boolean;\n kill?: boolean;\n status?: boolean;\n json?: boolean;\n session?: string;\n profile?: string;\n local?: boolean;\n /** true = all declared externals; string = comma-separated subset of\n * name[=mode] entries (mode \u2208 mock|local|remote overrides the decl). */\n mock?: boolean | string;\n /** Preferred spelling of --mock (same values). */\n externals?: boolean | string;\n /** local-mode process runner: 'tmux' (default) or 'docker' */\n runner?: string;\n dryRun?: boolean;\n transport?: string;\n force?: boolean;\n}\n\n/**\n * tmux session name for a dev launch. The primary checkout keeps the historical\n * `${projectName}-dev`; linked worktrees get a `${projectName}-${slug}` so two\n * worktrees of the same app don't share (and kill) each other's session, state,\n * and env-file dir (MESH-2013).\n */\nfunction deriveSessionName(projectName: string, wt: WorktreeIdentity): string {\n return wt.isPrimary ? `${projectName}-dev` : `${projectName}-${wt.slug}`;\n}\n\n/**\n * Render the resolved per-worktree plan (`mesh dev --dry-run`): identity,\n * session/state/env paths, and the port assignment \u2014 everything that must be\n * collision-free across concurrent worktrees, without launching anything.\n */\nfunction printDevPlan(\n sessionName: string,\n appRoot: string,\n wt: WorktreeIdentity,\n devOutput: DevOutput,\n): void {\n const kind = wt.isPrimary ? 'primary checkout' : `linked worktree (block ${wt.portBlock})`;\n console.log(`\\nmesh dev plan \u2014 ${kind}\\n`);\n console.log(` worktree root : ${wt.worktreeRoot}`);\n console.log(` app root : ${appRoot}`);\n console.log(` token : ${wt.token || '(none \u2014 primary)'}`);\n console.log(` tmux session : ${sessionName}`);\n console.log(` session state : ${getSessionStatePath(sessionName)}`);\n console.log(` env dir : ${getSessionEnvDir(sessionName)}`);\n const tq = wt.taskQueueSuffix\n ? `<app-task-queue>${wt.taskQueueSuffix}`\n : '<app-task-queue> (primary \u2014 unchanged)';\n console.log(` task queue : ${tq}`);\n console.log(`\\n services (port \u00B7 resolved source dir):`);\n const locals = Object.entries(devOutput.services).filter(\n ([, s]) => (s.port ?? 0) >= 0 && s.command && s.command.length > 0,\n );\n if (locals.length === 0) {\n console.log(` (none \u2014 all services are deployed/K8s)`);\n } else {\n const monorepoRoot = findMonorepoRoot();\n const wtWithSep = wt.worktreeRoot.endsWith(path.sep) ? wt.worktreeRoot : wt.worktreeRoot + path.sep;\n for (const [name, s] of locals) {\n const dir = path.resolve(appRoot, rebaseServiceSrc(s.src, monorepoRoot));\n const outside = dir !== wt.worktreeRoot && !dir.startsWith(wtWithSep);\n const port = s.port > 0 ? `:${s.port}` : '(no port)';\n console.log(` ${name.padEnd(18)} ${port.padEnd(7)} ${dir}${outside ? ' \u26A0 OUTSIDE worktree' : ''}`);\n }\n }\n console.log('');\n}\n\n// ============================================================================\n// Session state & port allocation\n// ============================================================================\n\nexport interface SessionState {\n appRoot: string;\n stack: string;\n devOutput: DevOutput;\n startedAt: string;\n /** 'tmux' (default) or 'docker' (mesh dev --runner docker, local mode) */\n runner?: 'tmux' | 'docker';\n /** Compose-mode external services (mesh dev --externals) this session brought\n * up \u2014 torn down (volumes kept) on `mesh dev --kill`. */\n composeExternals?: ComposeExternalRef[];\n /** Prometheus file_sd probe targets this session's externals registered \u2014\n * removed on `mesh dev --kill` so the Hub stops showing uptime for a\n * session that isn't running. Recorded as paths so `--kill --session`\n * works without resolving an app root. */\n externalProbeFiles?: string[];\n /**\n * Content fingerprint of the workflow source (agent-sdk / interpreter /\n * agent-contracts) at launch. Compared on relaunch/restart to warn before the\n * worker replays in-flight conversations against changed workflow code\n * (MESH-2017). Absent for sessions launched before this field existed.\n */\n workflowFingerprint?: string;\n}\n\nfunction getSessionStatePath(sessionName: string): string {\n const dir = path.join(os.tmpdir(), 'mesh-dev-sessions');\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\n return path.join(dir, `${sessionName}.json`);\n}\n\nfunction saveSessionState(sessionName: string, state: SessionState): void {\n fs.writeFileSync(getSessionStatePath(sessionName), JSON.stringify(state, null, 2));\n}\n\nfunction loadSessionState(sessionName: string): SessionState | null {\n const filePath = getSessionStatePath(sessionName);\n if (!fs.existsSync(filePath)) return null;\n try {\n return JSON.parse(fs.readFileSync(filePath, 'utf-8')) as SessionState;\n } catch {\n return null;\n }\n}\n\n/**\n * Relaunch safety (MESH-2017): if the workflow source changed since this session\n * launched, restarting the worker replays any in-flight conversations against the\n * NEW code \u2014 a replay-incompatible change strands them. Warn and require `--force`.\n *\n * Silent no-op when there's no prior session, no stored fingerprint (pre-feature\n * session), or nothing changed \u2014 so a restart of unchanged code never nags.\n * Returns `true` if the caller should ABORT (changed && !force).\n */\n/** Pure: did the workflow source change since launch (\u2192 risk of stranding)? */\nexport function workflowChanged(prior: string | undefined, current: string): boolean {\n return Boolean(prior) && Boolean(current) && current !== prior;\n}\n\nfunction workflowChangeWouldStrand(\n priorState: SessionState | null,\n appRoot: string,\n force: boolean,\n): boolean {\n const prior = priorState?.workflowFingerprint;\n if (!prior) return false;\n const current = fingerprintWorkflowSource(appRoot, priorState?.devOutput?.services);\n if (!workflowChanged(prior, current)) return false;\n logWarn(\n 'Workflow code changed since this session started.\\n' +\n ' Restarting the worker replays any in-flight conversations against the NEW code \u2014\\n' +\n ' a replay-incompatible change strands them (they get stuck and become unviewable).\\n' +\n ' Keep it replay-compatible: gate the change with wf.patched() and regenerate the replay\\n' +\n ' goldens (see the temporal-workflow-safety skill), or accept the risk.',\n );\n if (force) {\n logWarn(' Proceeding anyway (--force).');\n return false;\n }\n logError(' Refusing to restart the worker. Re-run with --force once the change is replay-safe.');\n return true;\n}\n\n/**\n * Per-session directory holding one sourceable env file per service\n * (`<service>.env.sh`, mode 0600). Written at launch; `mesh dev restart`\n * sources the same file so a restarted service gets a byte-identical env.\n */\nfunction getSessionEnvDir(sessionName: string): string {\n return path.join(os.tmpdir(), 'mesh-dev-sessions', sessionName);\n}\n\nfunction getServiceEnvFilePath(sessionName: string, serviceName: string): string {\n return path.join(getSessionEnvDir(sessionName), envFileName(serviceName));\n}\n\nfunction removeSessionState(sessionName: string): void {\n try {\n fs.unlinkSync(getSessionStatePath(sessionName));\n } catch {}\n try {\n fs.rmSync(getSessionEnvDir(sessionName), { recursive: true, force: true });\n } catch {}\n}\n\n/**\n * Check whether a TCP port is available \u2014 probing the way services actually bind.\n *\n * This used to bind `127.0.0.1` only, and that made it blind to exactly the\n * processes it exists to find. Node's `listen(port)` (and `@hono/node-server`,\n * which every agent-api uses) binds the WILDCARD address `::` in dual-stack mode,\n * holding the port on every interface \u2014 yet a probe bound to `127.0.0.1` still\n * succeeds against such a holder. So the check returned `true` for a port already\n * held by a prior `mesh dev` service, `allocatePorts` kept the preferred port, and\n * the service then died on `EADDRINUSE` at its real bind.\n *\n * Observed 2026-07-31: the `studio-api` pane died on `EADDRINUSE :::40161` while a\n * stale agent-api from an earlier boot kept serving on the same port, so the Studio\n * UI drove a process from a previous session's configuration and the conversation\n * list came back empty. Reproduced in isolation \u2014 holder on `::`, loopback probe\n * reports free, real bind fails (MESH-2590).\n *\n * Both addresses are probed: the wildcard catches all-interface holders, and the\n * loopback probe still catches a loopback-only squatter. A false \"busy\" is cheap \u2014\n * `allocatePorts` simply picks another port \u2014 while a false \"free\" crashes the\n * service, so this deliberately errs toward busy.\n */\nexport async function isPortFree(port: number): Promise<boolean> {\n const bindSucceeds = (host?: string): Promise<boolean> =>\n new Promise((resolve) => {\n const server = net.createServer();\n server.once('error', () => resolve(false));\n const onListening = () => server.close(() => resolve(true));\n if (host === undefined) server.listen(port, onListening);\n else server.listen(port, host, onListening);\n });\n\n // Wildcard first: it is how the services bind, so it is the probe that matters.\n if (!(await bindSucceeds())) return false;\n return bindSucceeds('127.0.0.1');\n}\n\n/**\n * Ask the OS for an ephemeral free port.\n */\nasync function findFreePort(): Promise<number> {\n return new Promise((resolve, reject) => {\n const server = net.createServer();\n server.once('error', reject);\n server.listen(0, '127.0.0.1', () => {\n const { port } = server.address() as net.AddressInfo;\n server.close(() => resolve(port));\n });\n });\n}\n\n/** Resolve true if something is accepting connections on 127.0.0.1:port. */\nfunction isPortListening(port: number): Promise<boolean> {\n return new Promise((resolve) => {\n const s = new net.Socket();\n let done = false;\n const fin = (ok: boolean) => {\n if (done) return;\n done = true;\n s.destroy();\n resolve(ok);\n };\n s.setTimeout(300);\n s.once('connect', () => fin(true));\n s.once('timeout', () => fin(false));\n s.once('error', () => fin(false));\n s.connect(port, '127.0.0.1');\n });\n}\n\n/**\n * Rewrite a service's OWN listen-port env var(s) from `oldPort` to `newPort`\n * when `allocatePorts` reassigns its port (e.g. a worktree block). Matches any\n * port-ish var (`PORT` or `*_PORT`, e.g. `VCS_PORT`/`AGENT_API_PORT`) whose value\n * is exactly the old port \u2014 so a service that reads its own env var still binds\n * the reassigned port instead of its deploy-time default (which would collide\n * with another worktree/session on that default). The name + exact-value match\n * keeps this from touching cross-service references or unrelated vars.\n * Mutates `service.env`. Pure otherwise \u2014 exported for unit testing. (MESH-2088)\n */\nexport function rewriteOwnServicePort(service: DevService, oldPort: number, newPort: number): void {\n for (const [key, spec] of Object.entries(service.env ?? {})) {\n if ((key === 'PORT' || key.endsWith('_PORT')) && spec.value === String(oldPort)) {\n spec.value = String(newPort);\n }\n }\n}\n\n/**\n * Clone devOutput and assign each service a local port.\n *\n * The PRIMARY checkout keeps the app's preferred ports (falling back to an\n * OS-ephemeral port only if one is busy). LINKED worktrees draw from a reserved\n * port block keyed on (worktree, app) \u2014 MESH-2013 for the worktree axis, #2889\n * for the app axis \u2014 so concurrent sessions don't collide, where the\n * `EADDRINUSE on 8080/8081/9000` class only happened because every worktree\n * reused the same preferred ports.\n *\n * Disjoint by DEFAULT, not by construction: the block is a hash bucket, so two\n * (worktree, app) pairs can share one. The in-block scan below plus the\n * ephemeral fallback are the backstop; MESH-2375 tracks making it deterministic.\n */\n\nasync function allocatePorts(devOutput: DevOutput, worktree: WorktreeIdentity): Promise<DevOutput> {\n const allocated = JSON.parse(JSON.stringify(devOutput)) as DevOutput;\n const usedPorts = new Set<number>();\n const portRemaps = new Map<number, number>();\n\n const blockBase = worktree.isPrimary ? 0 : blockBasePort(worktree.portBlock);\n let blockCursor = 0; // next unused index within the service sub-range\n\n for (const [name, service] of Object.entries(allocated.services)) {\n if (service.port <= 0) continue;\n // Skip deployed services (no dev command) \u2014 they run in K8s, no local port.\n if (!service.command || service.command.length === 0) continue;\n const preferred = service.port;\n\n let target = -1;\n if (worktree.isPrimary) {\n if (!usedPorts.has(preferred) && (await isPortFree(preferred))) {\n target = preferred;\n } else {\n target = await findFreePort();\n logWarn(`Port ${preferred} busy for service '${name}', using ${target}`);\n }\n } else {\n // Reserved block: next free port in [blockBase, blockBase+SERVICE_SUBRANGE).\n for (let i = blockCursor; i < PORT_BLOCK_SERVICE_SUBRANGE; i++) {\n const candidate = blockBase + i;\n if (!usedPorts.has(candidate) && (await isPortFree(candidate))) {\n target = candidate;\n blockCursor = i + 1;\n break;\n }\n }\n if (target < 0) {\n // Block exhausted or contended \u2014 degrade to an OS-ephemeral port.\n target = await findFreePort();\n logWarn(`Worktree port block exhausted for '${name}', using ${target}`);\n }\n }\n\n if (target !== preferred) {\n // Rewrite the service's OWN port env var(s) \u2014 not just a var literally\n // named `PORT`. Without this, a service reading `VCS_PORT`/`AGENT_API_PORT`\n // keeps its deploy-time default and collides across worktrees (MESH-2088).\n rewriteOwnServicePort(service, preferred, target);\n portRemaps.set(preferred, target);\n service.port = target;\n }\n usedPorts.add(target);\n }\n\n // Cross-service URL rewriting: when a service port is reassigned,\n // update any env var in other services that references the old port\n // (e.g., API_URL from a link() pointing to the API's original port).\n rewriteCrossServicePorts(allocated, portRemaps);\n rewriteClusterHostsToLocal(allocated);\n\n return allocated;\n}\n\n/**\n * Rewrite `localhost:${oldPort}` \u2192 `localhost:${newPort}` in EVERY service's env\n * values, for each `oldPort \u2192 newPort` entry in `portRemaps`. Mutates the given\n * `devOutput` in place \u2014 callers pass a clone they own, so this stays safe.\n *\n * Shared by `allocatePorts` (launch-time reallocation) and `mergePinnedPorts`\n * (refresh-time re-pinning) so both apply identical cross-service rewrites.\n */\nfunction rewriteCrossServicePorts(devOutput: DevOutput, portRemaps: Map<number, number>): void {\n if (portRemaps.size === 0) return;\n for (const service of Object.values(devOutput.services)) {\n if (!service.env) continue;\n for (const envVar of Object.values(service.env)) {\n for (const [oldPort, newPort] of portRemaps) {\n if (envVar.value.includes(`localhost:${oldPort}`)) {\n envVar.value = envVar.value.replace(`localhost:${oldPort}`, `localhost:${newPort}`);\n }\n }\n }\n }\n}\n\n/**\n * Merge a session's PINNED ports/tunnels into a freshly-read DevOutput.\n *\n * `mesh dev restart <svc> --refresh-env` re-reads `pulumi stack output` to pick\n * up config/deploy changes, but the running session already allocated local\n * ports (`allocatePorts`) and opened SSM tunnels. Re-reading the raw stack\n * output would carry the DEPLOYED (pre-allocation) ports, so writing those into\n * the env file would point the service \u2014 and its peers \u2014 at the wrong ports and\n * break the live tunnels.\n *\n * This returns `fresh` (so new/changed non-port env values win) but overrides:\n * - EVERY service present in both `fresh` and `pinned` keeps its pinned/\n * allocated PORT (both `service.port` and `service.env.PORT.value`) \u2014 not\n * just the refreshed one, so a regenerated service's peer references land on\n * the session-allocated ports, and\n * - every tunnel present in `pinned` with the pinned host:port (the live SSM\n * endpoints); tunnels that exist only in `fresh` survive untouched.\n *\n * It then re-applies BOTH of the peer-addressing rewrites `allocatePorts` does \u2014\n * there are two now, and naming only one here is how they drift apart:\n * - PORT: for each service whose port differs between `fresh` (preferred) and\n * `pinned` (allocated), `localhost:${freshPort}` \u2192 `localhost:${pinnedPort}`\n * across EVERY service's env (e.g. a `ui`'s `API_URL` pointing at `api`).\n * - HOST: an in-cluster address for a service running LOCALLY becomes its local\n * one. `pulumi stack output` carries cluster hosts verbatim, so a refresh\n * without this restores exactly the value MESH-2597 exists to remove.\n *\n * Pure: deep-clones and never mutates its arguments.\n */\nexport function mergePinnedPorts(fresh: DevOutput, pinned: DevOutput): DevOutput {\n const merged = JSON.parse(JSON.stringify(fresh)) as DevOutput;\n\n // Pinned tunnels win (live SSM/VPC endpoints); fresh-only tunnels survive.\n const pinnedTunnels = JSON.parse(JSON.stringify(pinned.tunnels ?? {})) as Record<\n string,\n DevTunnel\n >;\n merged.tunnels = { ...(merged.tunnels ?? {}), ...pinnedTunnels };\n\n // Pin EVERY service's allocated port (never re-allocate). Track fresh\u2192pinned\n // port remaps so peer references (localhost:<freshPort>) can be rewritten.\n const portRemaps = new Map<number, number>();\n for (const [name, mergedSvc] of Object.entries(merged.services ?? {})) {\n const pinnedSvc = pinned.services?.[name];\n if (!pinnedSvc || typeof pinnedSvc.port !== 'number') continue;\n const freshPort = mergedSvc.port;\n mergedSvc.port = pinnedSvc.port;\n if (mergedSvc.env?.PORT) {\n mergedSvc.env.PORT.value = String(pinnedSvc.port);\n }\n if (typeof freshPort === 'number' && freshPort > 0 && freshPort !== pinnedSvc.port) {\n portRemaps.set(freshPort, pinnedSvc.port);\n }\n }\n\n // Re-apply cross-service URL rewrite (mirrors allocatePorts): peer references\n // to a preferred port become references to the session-allocated port.\n rewriteCrossServicePorts(merged, portRemaps);\n // BOTH rewrites, or `--refresh-env` undoes the other one. This path re-reads\n // `pulumi stack output`, which carries in-cluster hosts verbatim, so without\n // this a refresh restores `AGENT_API_INTERNAL_URL` to\n // `http://studio-api.<ns>.svc.cluster.local:8080` for a service running locally\n // \u2014 reintroducing MESH-2597 on the command whose entire purpose is refreshing\n // env.\n rewriteClusterHostsToLocal(merged);\n\n return merged;\n}\n\n// ============================================================================\n// Pulumi helpers\n// ============================================================================\n\n/**\n * Find the monorepo root by walking up from cwd looking for the root\n * package.json (has \"workspaces\" or the well-known repo markers).\n */\nfunction findMonorepoRoot(): string | null {\n let dir = process.cwd();\n const root = path.parse(dir).root;\n\n while (dir !== root) {\n // Look for pnpm-workspace.yaml (pnpm monorepo) or .git (repo root)\n if (\n fs.existsSync(path.join(dir, 'pnpm-workspace.yaml')) ||\n fs.existsSync(path.join(dir, 'turbo.json'))\n ) {\n return dir;\n }\n // .git as fallback \u2014 but only if it's a directory (not a worktree file)\n const gitPath = path.join(dir, '.git');\n if (fs.existsSync(gitPath)) {\n return dir;\n }\n dir = path.dirname(dir);\n }\n return null;\n}\n\n/**\n * Discover Pulumi apps in the monorepo.\n * Scans:\n * {tenants,tests/tenants}/<tenant>/apps/<app>/Pulumi.yaml\n * apps/<app>/Pulumi.yaml (flat layout, tenant from stack config)\n */\nfunction discoverApps(monorepoRoot: string): Array<{\n name: string;\n tenant: string;\n appPath: string;\n relativePath: string;\n stacks: string[];\n}> {\n const apps: Array<{\n name: string;\n tenant: string;\n appPath: string;\n relativePath: string;\n stacks: string[];\n }> = [];\n\n // Helper: extract stacks and add an app entry\n function addApp(appDir: string, tenant: string) {\n const projectName = getProjectName(appDir);\n const stacks = fs\n .readdirSync(appDir)\n .filter((f) => f.startsWith('Pulumi.') && f.endsWith('.yaml') && f !== 'Pulumi.yaml')\n .map((f) => f.replace(/^Pulumi\\./, '').replace(/\\.yaml$/, ''));\n\n apps.push({\n name: projectName,\n tenant,\n appPath: appDir,\n relativePath: path.relative(monorepoRoot, appDir),\n stacks,\n });\n }\n\n // 1. Tenant-scoped: {tenants,tests/tenants}/<tenant>/apps/<app>/\n const searchDirs = ['tenants', 'tests/tenants'];\n\n for (const searchDir of searchDirs) {\n const base = path.join(monorepoRoot, searchDir);\n if (!fs.existsSync(base)) continue;\n\n for (const tenant of fs.readdirSync(base)) {\n const appsDir = path.join(base, tenant, 'apps');\n if (!fs.existsSync(appsDir) || !fs.statSync(appsDir).isDirectory()) continue;\n\n for (const app of fs.readdirSync(appsDir)) {\n const appDir = path.join(appsDir, app);\n if (!fs.existsSync(path.join(appDir, 'Pulumi.yaml'))) continue;\n addApp(appDir, tenant);\n }\n }\n }\n\n // 2. Flat layout: apps/<app>/ (tenant read from first stack config)\n const flatAppsDir = path.join(monorepoRoot, 'apps');\n if (fs.existsSync(flatAppsDir) && fs.statSync(flatAppsDir).isDirectory()) {\n for (const app of fs.readdirSync(flatAppsDir)) {\n const appDir = path.join(flatAppsDir, app);\n if (!fs.statSync(appDir).isDirectory()) continue;\n if (!fs.existsSync(path.join(appDir, 'Pulumi.yaml'))) continue;\n\n // Read tenant from first stack config's mesh:tenant\n let tenant = 'unknown';\n const stackConfigs = fs\n .readdirSync(appDir)\n .filter((f) => f.startsWith('Pulumi.') && f.endsWith('.yaml') && f !== 'Pulumi.yaml');\n if (stackConfigs.length > 0) {\n try {\n const content = fs.readFileSync(path.join(appDir, stackConfigs[0]!), 'utf-8');\n const tenantMatch = content.match(/mesh:tenant:\\s*(\\S+)/);\n if (tenantMatch) tenant = tenantMatch[1]!;\n } catch {}\n }\n\n addApp(appDir, tenant);\n }\n }\n\n return apps;\n}\n\n/**\n * Find the Pulumi app root by walking up from cwd looking for Pulumi.yaml.\n */\nfunction findAppRoot(appPath?: string): string {\n if (appPath) {\n // Resolve relative to cwd or monorepo root\n const resolved = path.resolve(appPath);\n if (fs.existsSync(path.join(resolved, 'Pulumi.yaml'))) return resolved;\n\n // Try relative to monorepo root\n const mono = findMonorepoRoot();\n if (mono) {\n const fromMono = path.resolve(mono, appPath);\n if (fs.existsSync(path.join(fromMono, 'Pulumi.yaml'))) return fromMono;\n }\n\n logError(`No Pulumi.yaml found at: ${appPath}`);\n process.exit(1);\n }\n\n let dir = process.cwd();\n const root = path.parse(dir).root;\n\n while (dir !== root) {\n if (fs.existsSync(path.join(dir, 'Pulumi.yaml'))) {\n return dir;\n }\n dir = path.dirname(dir);\n }\n\n return process.cwd();\n}\n\n/**\n * Read the Pulumi project name from Pulumi.yaml.\n */\nfunction getProjectName(appRoot: string): string {\n const yamlPath = path.join(appRoot, 'Pulumi.yaml');\n if (!fs.existsSync(yamlPath)) return path.basename(appRoot);\n\n const content = fs.readFileSync(yamlPath, 'utf-8');\n const match = content.match(/^name:\\s*(.+)$/m);\n return match?.[1]?.trim() ?? path.basename(appRoot);\n}\n\n/**\n * Detect the current Pulumi stack from:\n * 1. --stage flag\n * 2. MESH_STAGE env var\n * 3. `pulumi stack --show-name` (currently-selected stack)\n * 4. Pulumi.<stack>.yaml files in the app root (if exactly one, use it)\n */\nfunction detectStack(appRoot: string, stageArg?: string): string {\n if (stageArg) return stageArg;\n if (process.env.MESH_STAGE) return process.env.MESH_STAGE;\n\n try {\n const result = execFileSync('pulumi', ['stack', '--show-name'], {\n cwd: appRoot,\n encoding: 'utf-8',\n stdio: ['ignore', 'pipe', 'ignore'],\n }).trim();\n if (result) return result;\n } catch {\n // Fall through\n }\n\n // Infer from Pulumi.<stack>.yaml config files\n try {\n const files = fs\n .readdirSync(appRoot)\n .filter((f) => f.startsWith('Pulumi.') && f.endsWith('.yaml') && f !== 'Pulumi.yaml');\n if (files.length === 1) {\n const match = files[0]!.match(/^Pulumi\\.(.+)\\.yaml$/);\n if (match?.[1]) {\n logInfo(`Auto-detected stack from ${files[0]}`);\n return match[1];\n }\n }\n } catch {\n // Fall through\n }\n\n return 'dev';\n}\n\n/**\n * Build the `--stack <name>` args for Pulumi commands.\n * Newer Pulumi versions require fully-qualified names (organization/project/stack)\n * with `--stack`. If the stack is already selected, we can omit the flag entirely.\n */\nfunction stackArgs(appRoot: string, stack: string): string[] {\n // Check if the requested stack is already the selected one \u2014 if so, skip --stack\n try {\n const selected = execFileSync('pulumi', ['stack', '--show-name'], {\n cwd: appRoot,\n encoding: 'utf-8',\n stdio: ['ignore', 'pipe', 'ignore'],\n }).trim();\n if (selected === stack) return [];\n } catch {\n // ignore\n }\n\n // Try selecting the stack first (works with short names), then omit --stack\n try {\n execFileSync('pulumi', ['stack', 'select', stack], {\n cwd: appRoot,\n encoding: 'utf-8',\n stdio: ['ignore', 'pipe', 'ignore'],\n });\n return [];\n } catch {\n // Fall through \u2014 pass --stack and hope the name is fully qualified\n }\n\n return ['--stack', stack];\n}\n\n/**\n * Read the dev output from Pulumi stack.\n * Tries `app` output first (new env.register() format), falls back to `dev`.\n */\n/**\n * Thrown by `getDevOutput` when no readable Pulumi stack output exists (usually a\n * fresh app that hasn't been `stack init` + `deploy`ed yet). Typed so each caller\n * presents it in its OWN context: only the launch path can conclude \"nothing to\n * run\" and print first-run guidance; the `--refresh-env`/restart handlers must\n * keep the running session's env untouched (MESH-2097). Carries the underlying\n * read error so an auth/network/JSON failure isn't misdiagnosed as \"fresh app\".\n */\nclass MissingStackOutputError extends Error {\n constructor(public readonly stackName: string, cause?: unknown) {\n super(`No Pulumi stack output for '${stackName}'`, { cause });\n this.name = 'MissingStackOutputError';\n }\n}\n\nfunction getDevOutput(appRoot: string, stack: string, awsEnv?: Record<string, string>): DevOutput {\n const sa = stackArgs(appRoot, stack);\n\n // Try new format: export const app = env.register() \u2192 { dev: { ... } }\n try {\n const result = pulumiStackOutput(appRoot, 'app', sa, awsEnv);\n const appOutput = JSON.parse(result) as { dev?: DevOutput };\n if (appOutput.dev) {\n return appOutput.dev;\n }\n } catch {\n // Fall through to legacy format\n }\n\n // Legacy format: export const dev = ...\n try {\n const result = pulumiStackOutput(appRoot, 'dev', sa, awsEnv);\n return JSON.parse(result) as DevOutput;\n } catch (err) {\n // No readable stack output. Throw a TYPED error so each caller decides how to\n // present it (MESH-2097): the launch path prints first-run guidance + exits;\n // the --refresh-env/restart handlers keep the running session untouched.\n // (process.exit() here previously hijacked control flow past those fail-closed\n // catches, and a bare `throw` escaped as an uncaught node stacktrace.)\n throw new MissingStackOutputError(stack, err);\n }\n}\n\n// ============================================================================\n// tmux helpers\n// ============================================================================\n\nfunction hasTmux(): boolean {\n try {\n execFileSync('which', ['tmux'], { stdio: 'ignore' });\n return true;\n } catch {\n return false;\n }\n}\n\nfunction sessionExists(name: string): boolean {\n try {\n execFileSync('tmux', ['has-session', '-t', name], { stdio: 'ignore' });\n return true;\n } catch {\n return false;\n }\n}\n\nfunction killSession(name: string): boolean {\n try {\n execFileSync('tmux', ['kill-session', '-t', name], { stdio: 'ignore' });\n return true;\n } catch {\n return false;\n }\n}\n\nconst AWS_STATIC_CREDENTIAL_ENV_KEYS = [\n 'AWS_ACCESS_KEY_ID',\n 'AWS_SECRET_ACCESS_KEY',\n 'AWS_SESSION_TOKEN',\n 'AWS_WEB_IDENTITY_TOKEN_FILE',\n 'AWS_ROLE_ARN',\n] as const;\n\nfunction applyAwsProfileOverride(profile: string): void {\n process.env.AWS_PROFILE = profile;\n for (const key of AWS_STATIC_CREDENTIAL_ENV_KEYS) {\n delete process.env[key];\n }\n}\n\n/**\n * Collect AWS credentials from the current environment.\n */\nfunction getAwsEnvVars(): Record<string, string> {\n const result: Record<string, string> = {};\n const vars = [\n 'AWS_PROFILE',\n 'AWS_ACCESS_KEY_ID',\n 'AWS_SECRET_ACCESS_KEY',\n 'AWS_SESSION_TOKEN',\n 'AWS_REGION',\n 'AWS_DEFAULT_REGION',\n ];\n\n for (const name of vars) {\n const value = process.env[name];\n if (value) result[name] = value;\n }\n return result;\n}\n\n/**\n * Build the AWS env vars to hand to long-lived child services (ui, api,\n * ai-assistant) and SSM tunnels.\n *\n * For the AWS SSO credential path, returns AWS_PROFILE + AWS_REGION only so\n * the AWS SDK's default provider chain can auto-refresh credentials from the\n * SSO cache (~8h session) as short-lived STS tokens expire. Without this,\n * child processes inherit a frozen STS triple and start throwing\n * ExpiredTokenException ~1h into a dev session.\n *\n * For the Zitadel web-identity path, when `opts` is supplied we write an AWS\n * config file whose `credential_process` re-invokes `mesh login \u2026 --credential-process`,\n * so the AWS SDK's default provider chain auto-refreshes the underlying STS\n * triple (the `mesh login` process re-issues the Zitadel token as needed).\n * This removes the ~1h forced `mesh dev` restart. When `opts` is absent we\n * fall back to the frozen STS triple (used by CI/`environment` and any caller\n * that doesn't thread the context/role through).\n *\n * For the remaining non-SSO paths (CI/CD env keys, or no deployer role),\n * returns the explicit STS triple \u2014 there is no profile to refresh from. The\n * user must restart `mesh dev` when those tokens expire.\n */\nexport function buildChildAwsEnv(\n awsEnv: Record<string, string>,\n method: ResolvedAwsCreds['method'] | 'ambient',\n profile: string | undefined,\n opts?: { context: string; roleArn: string; sessionScratchDir: string; meshBin: string },\n): Record<string, string> {\n const result: Record<string, string> = {};\n if (awsEnv.AWS_REGION) result.AWS_REGION = awsEnv.AWS_REGION;\n if (awsEnv.AWS_DEFAULT_REGION) result.AWS_DEFAULT_REGION = awsEnv.AWS_DEFAULT_REGION;\n\n if (method === 'sso' && profile) {\n result.AWS_PROFILE = profile;\n return result;\n }\n\n // Zitadel path with a credential_process profile: hand children a profile\n // that self-refreshes via `mesh login`, never a frozen triple.\n if (method === 'zitadel' && opts) {\n const sanitizedContext = opts.context.replace(/[^A-Za-z0-9_-]/g, '-');\n const profileName = `mesh-dev-${sanitizedContext}`;\n const configPath = path.join(opts.sessionScratchDir, 'aws-config');\n const region = awsEnv.AWS_REGION ?? awsEnv.AWS_DEFAULT_REGION ?? '';\n fs.mkdirSync(opts.sessionScratchDir, { recursive: true });\n fs.writeFileSync(\n configPath,\n renderCredentialProcessProfile({\n profileName,\n context: opts.context,\n roleArn: opts.roleArn,\n region,\n meshBin: opts.meshBin,\n }),\n { mode: 0o600 },\n );\n const out: Record<string, string> = {\n AWS_PROFILE: profileName,\n AWS_CONFIG_FILE: configPath,\n };\n if (region) out.AWS_REGION = region;\n return out;\n }\n\n for (const key of ['AWS_ACCESS_KEY_ID', 'AWS_SECRET_ACCESS_KEY', 'AWS_SESSION_TOKEN'] as const) {\n if (awsEnv[key]) result[key] = awsEnv[key]!;\n }\n if (profile && !result.AWS_ACCESS_KEY_ID) {\n result.AWS_PROFILE = profile;\n }\n return result;\n}\n\n/**\n * Resolve a service's source dir onto the CURRENT worktree (MESH-2013).\n *\n * `mesh dev` reads the service `src` from `pulumi stack output`. Two shapes exist:\n * - New (post relative-src fix in infra-components): a monorepo-RELATIVE dir\n * like `packages/agent-sdk` \u2192 just resolve it against this worktree's root.\n * - Legacy: an ABSOLUTE path baked at the deploying `pulumi up`, e.g.\n * `/\u2026/mesh-platform/.worktrees/streaming-ui-builder/packages/agent-sdk`. The\n * old logic stripped only up to `/mesh-platform/`, keeping the\n * `.worktrees/<name>/` segment \u2014 so it re-rooted to a *sibling worktree* that\n * also exists, silently running the wrong worktree's code. We now reduce to\n * the monorepo-relative portion (dropping any `.worktrees/<name>/`) and\n * re-root here, so a stack deployed from any worktree runs from THIS one.\n */\nfunction rebaseServiceSrc(src: string, monorepoRoot: string | null): string {\n if (!monorepoRoot) return src;\n const rel = monorepoRelativeSrc(src);\n if (rel === null) return src;\n const rebased = path.join(monorepoRoot, rel);\n return fs.existsSync(rebased) ? rebased : src;\n}\n\n/**\n * Reduce a service `src` to its monorepo-relative form (pure; no filesystem).\n * - relative (`./packages/x` or `packages/x`) \u2192 normalized `packages/x`\n * - legacy absolute (`/\u2026/mesh-platform[/.worktrees/<name>]/packages/x`) \u2192\n * `packages/x` (drops the repo root AND any deploying-worktree segment)\n * Returns null when an absolute path has no recognizable monorepo marker.\n */\nexport function monorepoRelativeSrc(src: string): string | null {\n if (!path.isAbsolute(src)) return src.replace(/^\\.\\//, '') || '.';\n // Match the LAST `/mesh-platform` at a segment boundary \u2014 covers the repo root\n // itself (nothing follows \u2192 '.'), a nested `.worktrees/<name>/`, and normal\n // subpaths. A path ending at the repo root (e.g. a service whose src IS the\n // monorepo root) previously slipped through and stayed absolute (MESH-2069).\n const m = src.match(/^.*\\/mesh-platform(?:\\/(.*))?$/);\n if (!m) return null;\n const rest = (m[1] ?? '').replace(/^\\.worktrees\\/[^/]+(?:\\/|$)/, '');\n return rest === '' ? '.' : rest;\n}\n\n/**\n * Resolve env vars for a service, rewriting tunnel references to VPC endpoints.\n */\nfunction getServiceEnvVars(\n service: DevService,\n tunnels: Record<string, DevTunnel>,\n): Record<string, string> {\n const result: Record<string, string> = {};\n\n if (service.env) {\n for (const [key, spec] of Object.entries(service.env)) {\n let value = spec.value;\n\n if (spec.tunnel) {\n const tunnel = tunnels[spec.tunnel];\n if (tunnel) {\n // Rewrite to VPC endpoint (VPN provides direct access)\n try {\n const url = new URL(value);\n if (url.hostname) {\n url.hostname = tunnel.host;\n url.port = String(tunnel.port);\n value = url.toString();\n } else {\n value = `${tunnel.host}:${tunnel.port}`;\n }\n } catch {\n value = `${tunnel.host}:${tunnel.port}`;\n }\n }\n }\n\n result[key] = value;\n }\n }\n return result;\n}\n\n/**\n * Set env vars on a tmux session. New windows inherit them.\n *\n * Use for truly shared vars (AWS creds, secrets). For per-service\n * vars like PORT, use envPrefix() instead to avoid cross-service leaks.\n */\nfunction setTmuxEnv(sessionName: string, vars: Record<string, string>): void {\n for (const [key, value] of Object.entries(vars)) {\n execFileSync('tmux', ['set-environment', '-t', sessionName, key, value], { stdio: 'ignore' });\n }\n}\n\n/**\n * Build an `env K=V \u2026` prefix string for per-service env vars.\n *\n * This scopes variables to the process instead of polluting the\n * tmux session environment (where the last service's PORT would\n * leak to every other service on restart).\n */\nfunction envPrefix(vars: Record<string, string>): string {\n const entries = Object.entries(vars);\n if (entries.length === 0) return '';\n const parts = entries.map(([k, v]) => `${k}=${shellEscape(v)}`);\n return `env ${parts.join(' ')} `;\n}\n\n/** Escape a value for shell interpolation. */\nfunction shellEscape(s: string): string {\n // If the value is safe, return as-is\n if (/^[a-zA-Z0-9_./:@=+,-]+$/.test(s)) return s;\n // Otherwise single-quote it, escaping any embedded single quotes\n return `'${s.replace(/'/g, \"'\\\\''\")}'`;\n}\n\n// ============================================================================\n// Secret resolution\n// ============================================================================\n\n/**\n * Resolve secrets from Secrets Manager and return env var key\u2192value pairs.\n * VPN provides direct access \u2014 no URL rewriting needed.\n */\nasync function resolveSecrets(secrets: Record<string, DevSecret>): Promise<Record<string, string>> {\n const client = new SecretsManagerClient({});\n const resolved: Record<string, string> = {};\n\n for (const [name, secret] of Object.entries(secrets)) {\n try {\n const response = await client.send(\n new GetSecretValueCommand({ SecretId: secret.secretName }),\n );\n if (!response.SecretString) continue;\n\n const values = JSON.parse(response.SecretString) as Record<string, string>;\n\n for (const [secretKey, envVar] of Object.entries(secret.envMapping)) {\n const value = values[secretKey];\n if (value === undefined) continue;\n resolved[envVar] = value;\n }\n\n logSuccess(`Secret resolved: ${name} (${secret.secretName})`);\n } catch (err) {\n logWarn(\n `Could not resolve secret '${name}' (${secret.secretName}): ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }\n\n return resolved;\n}\n\n\n/**\n * Resolve the Temporal encoding key from the K8s secret in the app namespace.\n *\n * The Pulumi-generated devEncodingKey is a placeholder that differs from the\n * deployed key, causing decryption failures when the local worker encounters\n * existing Temporal payloads. Reading the real key from K8s ensures local dev\n * can decrypt data created by deployed workers.\n *\n * Returns the encoding key value, or undefined if not available.\n */\nfunction resolveTemporalEncodingKey(\n tenant: string,\n env: string,\n appName: string,\n): string | undefined {\n const namespace = `${tenant}-${env}-${appName}`;\n const secretName = `${namespace}-temporal-encoding-key`;\n try {\n const b64 = execFileSync(\n 'kubectl',\n [\n 'get',\n 'secret',\n secretName,\n '-n',\n namespace,\n '-o',\n 'jsonpath={.data.TEMPORAL_ENCODING_KEY}',\n ],\n { encoding: 'utf-8', timeout: 10_000, stdio: ['pipe', 'pipe', 'pipe'] },\n ).trim();\n\n if (b64) {\n const key = Buffer.from(b64, 'base64').toString('utf-8');\n logSuccess(`Temporal encoding key resolved from K8s secret (${secretName})`);\n return key;\n }\n } catch {\n // Non-fatal \u2014 secret may not exist yet or kubectl may not have access\n }\n return undefined;\n}\n\n/**\n * Re-resolve the session-level Temporal auth vars the SAME way launch does\n * (see startServices): kubeconfig from SSM, M2M auth, encoding key from the\n * K8s secret, and TEMPORAL_ADDRESS from the (pinned) tunnel. Used by\n * `mesh dev restart --refresh-env` so a regenerated env file carries the live\n * resolved values, not the dev-output placeholders (which would desync payload\n * encryption between services).\n */\nasync function resolveTemporalAuthVars(\n sessionName: string,\n devOutput: DevOutput,\n): Promise<Record<string, string>> {\n const tenant = devOutput.platform?.tenant ?? 'mesh';\n const platformEnv = devOutput.platform?.env ?? 'dev';\n // Hub platform name \u2014 the EKS export lives under it, not under a hardcoded\n // \"mesh\" (MESH-2515); same axis as the bastion resolution.\n const platformName = resolveHubPlatformName(devOutput.platform);\n\n const kubeconfigPath = await ensureKubeconfig(platformName, platformEnv, sessionName, {\n onError: ({ parameter, error }) =>\n logWarn(\n `EKS cluster resolve failed (${parameter}): ${error instanceof Error ? `${error.name}: ${error.message}` : String(error)}`,\n ),\n });\n if (kubeconfigPath) {\n process.env.KUBECONFIG = kubeconfigPath;\n setTmuxEnv(sessionName, { KUBECONFIG: kubeconfigPath });\n } else if (!process.env.KUBECONFIG) {\n // ensureKubeconfig couldn't re-resolve the cluster from SSM (transient /\n // stale creds). Fall back to the session kubeconfig written at launch so the\n // kubectl calls below don't default to ~/.kube/config \u2014 which macOS TCC\n // denies for shells without Full Disk Access (\"operation not permitted\").\n const existing = sessionKubeconfigPath(sessionName);\n if (fs.existsSync(existing)) {\n // Set only this process's env \u2014 deliberately NOT setTmuxEnv: this is a\n // best-effort fallback to a possibly-stale last-good kubeconfig, so we use\n // it for the kubectl calls below without persisting it into the session\n // (a later successful re-resolve is the one that should win the session).\n process.env.KUBECONFIG = existing;\n }\n }\n\n let temporalAuthVars: Record<string, string> = {};\n if (devOutput.tunnels['temporal']) {\n // Deliberately NOT `platformName` from above: the Temporal-auth fallback is\n // `?? tenant` (dedicated tenants may run their own Temporal), while the EKS\n // fallback is `?? 'mesh'`. Whether that difference is correct is MESH-2551;\n // don't \"fix\" either default to match the other without reading it.\n temporalAuthVars = await resolveTemporalAuth(tenant, platformEnv, devOutput.platform?.name ?? tenant);\n\n const appName = devOutput.app ?? '';\n if (appName) {\n const encodingKey = resolveTemporalEncodingKey(tenant, platformEnv, appName);\n if (encodingKey) {\n temporalAuthVars.TEMPORAL_ENCODING_KEY = encodingKey;\n }\n }\n\n const temporalTunnel = devOutput.tunnels['temporal'];\n temporalAuthVars.TEMPORAL_ADDRESS = tunnelClientAddress(temporalTunnel);\n }\n return temporalAuthVars;\n}\n\n/**\n * Resolve the dev-user identity vars (DEV_USER_*) from cached `mesh login`\n * credentials for the platform context (e.g. 'mesh.dev'). Credentials are\n * stored under the platform context, not the tenant name \u2014 all tenants share\n * the same Zitadel instance.\n *\n * Services (e.g., Hub UI) use these as a fallback when the real oauth2-proxy\n * `X-Forwarded-*` request headers are absent:\n * DEV_USER_ID - subject from idToken, matches conversation ownership\n * DEV_USER_EMAIL - user email from idToken\n * DEV_USER_ID_TOKEN - full idToken JWT (profile claims, authorization hint)\n * DEV_USER_ACCESS_TOKEN - full accessToken JWT (has project:roles claim)\n *\n * Returned vars must be overlaid onto each service's env FILE (not just the\n * tmux session env): the dev output may carry a placeholder value (e.g. hub\n * ui's DEV_USER_ACCESS_TOKEN=\"dev-local\"), and the sourced per-service env\n * file wins over the session env, so a session-env-only injection gets\n * clobbered and every tenant-scoped Hub view silently 401s.\n */\nfunction resolveDevUserVars(devOutput: DevOutput): Record<string, string> {\n const credContext = devOutput.platform\n ? devOutput.platform.tenant === 'local'\n ? 'local'\n : `mesh.${devOutput.platform.env}`\n : null;\n if (!credContext) return {};\n const meshCreds = readCredentials(credContext);\n if (!meshCreds?.idToken) return {};\n const vars: Record<string, string> = { DEV_USER_ID_TOKEN: meshCreds.idToken };\n try {\n const payload = JSON.parse(\n Buffer.from(meshCreds.idToken.split('.')[1]!, 'base64url').toString(),\n );\n if (payload.sub) vars.DEV_USER_ID = payload.sub;\n if (payload.email) vars.DEV_USER_EMAIL = payload.email;\n } catch {\n /* ignore decode errors */\n }\n if (meshCreds.accessToken) {\n vars.DEV_USER_ACCESS_TOKEN = meshCreds.accessToken;\n }\n return vars;\n}\n\n// ============================================================================\n// SSM tunnel fallback (when VPN is not connected)\n// ============================================================================\n\n/**\n * Base port for SSM tunnels. Preferred ports use 20000 + original_port to\n * avoid collisions with dev services (1000-9999 range). If the preferred\n * port is already reserved or occupied, mesh dev walks upward until it finds\n * an available port.\n *\n * Examples:\n * PostgreSQL 5432 \u2192 25432\n * Temporal 7233 \u2192 27233\n * Temporal UI 8080 \u2192 28080\n */\nconst SSM_TUNNEL_BASE_PORT = 20000;\n\n/** How long to wait for an SSM tunnel's local port to accept TCP before failing. */\nconst TUNNEL_READY_TIMEOUT_MS = 60_000;\n\n/**\n * Build the client-facing `host:port` for an SSM tunnel.\n *\n * The `aws ssm start-session` port-forwarder binds IPv4 `127.0.0.1` only.\n * Advertising `localhost` lets Node/grpc-js resolve to IPv6 `::1` first, which\n * the tunnel isn't listening on \u2014 so e.g. the Temporal gRPC client fails with\n * `ECONNREFUSED ::1:<port>` and the Hub's Automations/workflow lists never load.\n * Maps the literal `localhost` (how tunnels are advertised today) to `127.0.0.1`\n * so clients hit the bound listener. Any other host \u2014 VPN-direct VPC endpoints,\n * or a different loopback literal like `::1`/`127.0.0.1` \u2014 passes through unchanged.\n */\nexport function tunnelClientAddress(tunnel: { host: string; port: number }): string {\n const host = tunnel.host === 'localhost' ? '127.0.0.1' : tunnel.host;\n return `${host}:${tunnel.port}`;\n}\n\n/** One tunnel's live health, resolved by a TCP dial of its client address. */\nexport interface TunnelHealth {\n name: string;\n /** Client-facing `host:port` (see {@link tunnelClientAddress}). */\n address: string;\n reachable: boolean;\n}\n\n/**\n * Render the Connections section (live tunnel health) as status-window lines.\n *\n * The status window refreshes every ~2s, so this is where a mid-session tunnel\n * death surfaces (MESH-2016): a dead tunnel shows `\u26A0 \u2026 DOWN` and a SINGLE\n * remediation line explains the `ECONNREFUSED` retry spam the dependent service\n * windows emit \u2014 instead of leaving the operator to decode that spam themselves.\n * Returns `[]` when there are no tunnels (nothing to show).\n */\nexport function formatTunnelHealth(health: TunnelHealth[]): string[] {\n if (health.length === 0) return [];\n const lines = ['Connections:'];\n for (const h of health) {\n const icon = h.reachable ? '\u2713' : '\u26A0';\n const suffix = h.reachable ? '' : ' DOWN';\n lines.push(` ${icon} ${h.name.padEnd(16)} ${h.address}${suffix}`);\n }\n const down = health.filter((h) => !h.reachable).map((h) => h.name);\n if (down.length > 0) {\n const noun = down.length === 1 ? 'tunnel' : 'tunnels';\n lines.push('');\n lines.push(\n ` \u26A0 ${down.length} ${noun} down (${down.join(', ')}) \u2014 dependent services are ` +\n `retrying (ECONNREFUSED spam is expected). Relaunch: mesh dev`,\n );\n }\n return lines;\n}\n\n/** Probe every tunnel's client address in parallel and resolve its health. */\nasync function probeTunnelHealth(\n tunnels: Record<string, { host: string; port: number }>,\n): Promise<TunnelHealth[]> {\n return Promise.all(\n Object.entries(tunnels).map(async ([name, tun]) => ({\n name,\n address: tunnelClientAddress(tun),\n // Dial the SAME address the client uses (localhost\u2192127.0.0.1) so the probe\n // sees exactly what a dependent service would. Use the connection-HOLDS\n // probe, not a bare accept: a forwarder binds its local port even when its\n // upstream leg is dead (a dropped SSM session, or a Tailscale SOCKS bridge\n // dialing a stale port \u2014 MESH-2169), so \"port accepts\" would report a dead\n // tunnel as healthy. Holding briefly catches the accept-then-close teardown.\n reachable: await probeConnectionHolds(\n tun.host === 'localhost' ? '127.0.0.1' : tun.host,\n tun.port,\n 800,\n ),\n })),\n );\n}\n\n/**\n * Probe the routing-critical tunnel of a (Tailscale-rewritten) devOutput and\n * return its name if the forwarder binds but does not ROUTE, else null.\n *\n * Only `temporal` is gated \u2014 it's the load-bearing VPC dependency (services die\n * on a gRPC deadline when it's dead), and keying on it mirrors the vpn-direct\n * reachability gate ({@link gateVpnDirectReachability}). A Tailscale forwarder\n * accepts its local port even when its SOCKS upstream is dead or the joined\n * tailnet doesn't route the VPC; such a forwarder tears the connection down\n * within the grace window, so it fails the connection-HOLDS probe that a bare\n * accept (the readiness gate's `waitForPort`) would pass (MESH-2169/MESH-2268).\n */\nexport async function firstUnroutableTunnel(\n tunnels: Record<string, { host: string; port: number }>,\n): Promise<string | null> {\n const temporal = tunnels['temporal'];\n if (!temporal || temporal.host !== 'localhost') return null;\n const holds = await probeConnectionHolds('127.0.0.1', temporal.port, 800);\n return holds ? null : 'temporal';\n}\n\n/** Compute the preferred local port for an SSM tunnel. */\n/** Tunnel backing for a dev session. */\nexport type Transport = \"ssm\" | \"tailscale\" | \"vpn-direct\";\n\n/** What `startServices` should do for VPC tunnels. */\nexport interface TunnelPlan {\n transport: Transport;\n tailscale?: { tenant: string; env: string; region: string; loginServer: string; socksPort: number; preAuthKey?: string };\n /** True when the user EXPLICITLY asked for this transport (`--transport <x>`),\n * vs an auto-resolved default. An explicit tailscale choice must NOT silently\n * fall back to SSM \u2014 surface the failure so the user can act (MESH-2098). */\n explicit?: boolean;\n}\n\n/**\n * Resolve which tunnel backing `mesh dev` should use.\n *\n * An explicit `--transport` flag wins. Both `auto` and the default (unset)\n * prefer Tailscale when it's available (brew `tailscaled` present), else fall\n * back to the VPN-direct/SSM choice: VPN-direct when the VPN is connected, else\n * SSM when the session-manager plugin is present. Where Tailscale isn't\n * available the behavior is unchanged from before this feature.\n */\nexport function resolveTransport(\n flag: string | undefined,\n ctx: { vpnConnected: boolean; hasSsmPlugin: boolean; tailscaleAvailable: boolean },\n): Transport {\n if (flag === \"tailscale\" || flag === \"ssm\") return flag;\n if (flag !== undefined && flag !== \"auto\") {\n throw new Error(`Invalid --transport '${flag}'. Valid values: auto (default), tailscale, ssm.`);\n }\n const legacy: Transport = ctx.vpnConnected ? \"vpn-direct\" : ctx.hasSsmPlugin ? \"ssm\" : \"vpn-direct\";\n return ctx.tailscaleAvailable ? \"tailscale\" : legacy;\n}\n\n/** Outcome of the reachability gate \u2014 `transport` is what to use, `reason` drives the log. */\nexport type ReachabilityDecision = {\n transport: Transport;\n reason: \"not-vpn-direct\" | \"reachable\" | \"fallback-ssm\" | \"unreachable-no-plugin\";\n};\n\n/**\n * Correct an auto-selected `vpn-direct` transport against ACTUAL reachability of\n * the Temporal VPC endpoint (MESH-2016). `resolveTransport` uses a presence check\n * (any Tailscale/VPN up) that's tailnet-blind \u2014 Tailscale-for-SSH looks connected\n * but doesn't route the mesh VPC. Only `vpn-direct` is reachability-gated (it's\n * never an explicit choice); every other transport passes through unchanged.\n *\n * Pure so the fallback logic is testable independently of the TCP probe.\n */\nexport function reachabilityFallbackTransport(\n transport: Transport,\n temporalReachable: boolean,\n hasSsmPlugin: boolean,\n): ReachabilityDecision {\n if (transport !== \"vpn-direct\") return { transport, reason: \"not-vpn-direct\" };\n if (temporalReachable) return { transport, reason: \"reachable\" };\n if (hasSsmPlugin) return { transport: \"ssm\", reason: \"fallback-ssm\" };\n return { transport, reason: \"unreachable-no-plugin\" };\n}\n\n/**\n * Apply the reachability gate to a (possibly auto-selected) transport: if it's\n * `vpn-direct`, TCP-dial the Temporal VPC endpoint and downgrade to SSM when it's\n * actually unreachable, logging the decision. Returns the effective transport;\n * a no-op for any non-`vpn-direct` transport.\n *\n * Called on BOTH auto-select paths \u2014 the normal resolve result AND the\n * Tailscale\u2192legacy fallback (when no mesh login config exists for the derived\n * context) \u2014 so a `vpn-direct` can never reach `startServices` unprobed\n * (MESH-2016).\n */\nasync function gateVpnDirectReachability(\n transport: Transport,\n devOutput: DevOutput,\n): Promise<Transport> {\n if (transport !== \"vpn-direct\") return transport;\n const temporalTunnel = devOutput.tunnels?.[\"temporal\"];\n if (!temporalTunnel) return transport;\n const { host, port } = temporalTunnel;\n const reachable = await probeTcpReachable(host, port, 1500);\n const decision = reachabilityFallbackTransport(transport, reachable, hasSessionManagerPlugin());\n if (decision.reason === \"reachable\") {\n logInfo(`Transport: VPN-direct \u2014 Temporal VPC endpoint ${host}:${port} is reachable.`);\n } else if (decision.reason === \"fallback-ssm\") {\n logWarn(\n `Transport: VPN reports connected but the Temporal VPC endpoint ${host}:${port} is unreachable ` +\n `(tailnet-blind presence check) \u2014 falling back to SSM tunnels (2XXXX port range; VPN-only features ` +\n `like in-cluster kubectl are unavailable). Pin with --transport=ssm to skip this probe.`,\n );\n } else if (decision.reason === \"unreachable-no-plugin\") {\n logWarn(\n `Transport: Temporal VPC endpoint ${host}:${port} is unreachable and the SSM session-manager ` +\n `plugin is missing \u2014 VPN-direct will likely fail. Fix VPN routing or install the plugin ` +\n `(see: mesh dev doctor).`,\n );\n }\n return decision.transport;\n}\n\n/**\n * Derive the Headscale login-server URL from a login context's issuer\n * (`identity.<env>.<domain>` \u2192 `vpn.<env>.<domain>`). Used for the Tailscale\n * transport's OIDC join. Returns null if the context has no cached login config.\n */\nfunction deriveLoginServer(context: string): string | null {\n const cfg = getContextConfig(context);\n if (!cfg?.issuer) return null;\n try {\n const u = new URL(cfg.issuer);\n const parts = u.hostname.split(\".\");\n parts[0] = \"vpn\";\n return `https://${parts.join(\".\")}`;\n } catch {\n return null;\n }\n}\n\nexport function preferredSsmLocalPort(remotePort: number): number {\n const preferred = SSM_TUNNEL_BASE_PORT + remotePort;\n if (preferred > 65535) {\n throw new Error(\n `Cannot allocate SSM tunnel port for remote port ${remotePort}: preferred local port ${preferred} exceeds 65535`,\n );\n }\n return preferred;\n}\n\n/**\n * Reserve a deterministic local-port candidate for an SSM tunnel.\n *\n * This prevents two tunnels with the same remote port (common for HTTPS\n * endpoints) from being assigned the same localhost port before the AWS CLI\n * has a chance to bind it.\n */\nexport function reserveSsmLocalPortCandidate(\n remotePort: number,\n reservedPorts: Set<number>,\n startAt = preferredSsmLocalPort(remotePort),\n): number {\n for (let port = startAt; port <= 65535; port += 1) {\n if (!reservedPorts.has(port)) {\n reservedPorts.add(port);\n return port;\n }\n }\n throw new Error(\n `Cannot allocate SSM tunnel port for remote port ${remotePort}: no free candidate ports remain`,\n );\n}\n\nasync function allocateSsmLocalPort(\n remotePort: number,\n reservedPorts: Set<number>,\n): Promise<number> {\n let nextCandidate = preferredSsmLocalPort(remotePort);\n\n while (nextCandidate <= 65535) {\n const candidate = reserveSsmLocalPortCandidate(remotePort, reservedPorts, nextCandidate);\n if (await isPortFree(candidate)) {\n return candidate;\n }\n nextCandidate = candidate + 1;\n }\n\n throw new Error(\n `Cannot allocate SSM tunnel port for remote port ${remotePort}: no local ports are available`,\n );\n}\n\n/**\n * Check if the session-manager-plugin is installed (required for SSM tunnels).\n */\nfunction hasSessionManagerPlugin(): boolean {\n try {\n execFileSync('which', ['session-manager-plugin'], { stdio: 'ignore' });\n return true;\n } catch {\n return false;\n }\n}\n\ninterface PlannedSsmTunnel {\n tunnelName: string;\n endpoint: DevTunnel;\n localPort: number;\n}\n\n/**\n * Start SSM port-forwarding tunnels as tmux windows within the dev session.\n *\n * For each tunnel defined in devOutput (e.g., temporal, rds), this:\n * 1. Reads the bastion instance ID and service endpoints from SSM\n * 2. Spawns `aws ssm start-session` in a dedicated tmux window\n * 3. Rewrites devOutput.tunnels to point at localhost:2XXXX\n *\n * Returns the rewritten devOutput with tunnels pointing to localhost.\n */\nasync function startSsmTunnels(sessionName: string, devOutput: DevOutput): Promise<DevOutput> {\n const platformEnv = devOutput.platform?.env ?? 'dev';\n // The bastion is a HUB platform resource (/mesh-platform/<hub>/<env>/platform-bastion),\n // not an app-tenant resource \u2014 devOutput.platform.tenant is the APP tenant (e.g. acme),\n // which for shared tenants has no bastion. Resolve under the platform/hub name; default\n // to \"mesh\" (matching how resolveTemporalAuth reads platform-level params).\n const bastionTenant = devOutput.platform?.name ?? 'mesh';\n\n // Read bastion info from SSM\n const bastion = await getPlatformBastionInfo(bastionTenant, platformEnv).catch(() => null);\n if (!bastion) {\n logError('Could not read platform bastion info from SSM.');\n logInfo('Make sure PlatformBastion is deployed in your platform stack.');\n logInfo(\"If you don't have a bastion, connect via VPN instead: mesh vpn connect\");\n throw new Error('SSM tunnel fallback unavailable: no bastion found');\n }\n\n const rewritten = JSON.parse(JSON.stringify(devOutput)) as DevOutput;\n const tunnelCount = Object.keys(devOutput.tunnels).length;\n\n if (tunnelCount === 0) {\n logInfo('No tunnels defined \u2014 SSM fallback not needed.');\n return rewritten;\n }\n\n logInfo(`Starting ${tunnelCount} SSM tunnel(s) via bastion ${bastion.instanceId}...`);\n\n // Map devOutput tunnel names to bastion service keys\n // devOutput uses names like \"temporal\", \"rds\"; bastion uses \"temporal-frontend\", \"rds\"\n const tunnelToBastionKey: Record<string, string> = {\n temporal: 'temporal-frontend',\n 'temporal-ui': 'temporal-ui',\n rds: 'rds',\n db: 'rds',\n database: 'rds',\n };\n\n // Observability tunnels are non-fatal under SSM fallback \u2014 skip with a warning\n // rather than aborting the dev loop when the bastion doesn't expose them.\n const OPTIONAL_TUNNEL_NAMES = new Set([\n 'loki',\n 'prometheus',\n 'tempo',\n 'pushgateway',\n 'grafana',\n ]);\n\n const missingEndpoints: string[] = [];\n const skippedOptional: string[] = [];\n const reservedPorts = new Set<number>();\n const plannedTunnels: PlannedSsmTunnel[] = [];\n\n for (const [tunnelName] of Object.entries(devOutput.tunnels)) {\n const bastionKey = tunnelToBastionKey[tunnelName] ?? tunnelName;\n const endpoint = bastion.services[bastionKey];\n\n if (!endpoint) {\n // Observability tunnels degrade gracefully under SSM fallback: without\n // them the consuming app's monitoring views (logs/metrics/traces) won't\n // work, but they must not block the core dev loop. Only critical tunnels\n // (temporal, rds, ...) are fatal when the bastion can't reach them.\n if (OPTIONAL_TUNNEL_NAMES.has(tunnelName)) {\n skippedOptional.push(`${tunnelName} (bastion key: ${bastionKey})`);\n } else {\n missingEndpoints.push(`${tunnelName} (bastion key: ${bastionKey})`);\n }\n continue;\n }\n\n plannedTunnels.push({\n tunnelName,\n endpoint,\n localPort: await allocateSsmLocalPort(endpoint.port, reservedPorts),\n });\n }\n\n if (skippedOptional.length > 0) {\n logWarn(\n 'Skipping optional observability tunnel(s) not exposed by the bastion (SSM fallback):',\n );\n for (const skipped of skippedOptional) {\n logInfo(` Skipped: ${skipped}`);\n }\n logInfo(\n ' Monitoring views (logs/metrics/traces) stay unavailable until VPN is connected.',\n );\n }\n\n if (missingEndpoints.length > 0) {\n logError('SSM tunnel fallback cannot cover every required dev tunnel.');\n for (const missing of missingEndpoints) {\n logInfo(` Missing: ${missing}`);\n }\n logInfo(\n ` Available bastion services: ${Object.keys(bastion.services).join(', ') || '(none)'}`,\n );\n logInfo(\n 'Connect VPN instead or deploy/update PlatformBastion with the missing service endpoints.',\n );\n throw new Error('SSM tunnel fallback unavailable: missing bastion endpoints');\n }\n\n for (const { tunnelName, endpoint, localPort } of plannedTunnels) {\n // Create a tmux window for this tunnel\n const windowName = `tunnel-${tunnelName}`;\n const ssmCmd = [\n 'aws',\n 'ssm',\n 'start-session',\n '--target',\n bastion.instanceId,\n '--document-name',\n 'AWS-StartPortForwardingSessionToRemoteHost',\n '--parameters',\n `'${JSON.stringify({\n host: [endpoint.host],\n portNumber: [String(endpoint.port)],\n localPortNumber: [String(localPort)],\n })}'`,\n ].join(' ');\n\n execFileSync('tmux', ['new-window', '-t', sessionName, '-n', windowName]);\n\n // Keep window alive so tunnel errors are visible\n execFileSync(\n 'tmux',\n ['set-option', '-t', `${sessionName}:${windowName}`, 'remain-on-exit', 'on'],\n { stdio: 'ignore' },\n );\n\n execFileSync('tmux', ['send-keys', '-t', `${sessionName}:${windowName}`, ssmCmd, 'Enter']);\n\n // Rewrite the tunnel to point at localhost\n rewritten.tunnels[tunnelName] = {\n host: 'localhost',\n port: localPort,\n };\n\n logSuccess(\n ` ${tunnelName}: localhost:${localPort} \u2192 ${endpoint.host}:${endpoint.port} (via SSM)`,\n );\n }\n\n return rewritten;\n}\n\n/**\n * Update the DevBox host's Caddy reverse proxy config.\n *\n * Generates a Caddyfile so services are accessible at\n * http://{service}.{stack}.{app}.{tenant}-{env}.mesh.local\n * from the developer's Mac (via Tailscale + dnsmasq).\n */\nasync function updateDevboxProxy(devOutput: DevOutput, appRoot: string): Promise<void> {\n const appName = devOutput.app ?? path.basename(appRoot);\n const tenant = devOutput.platform?.tenant ?? 'mesh';\n const env = devOutput.platform?.env ?? 'dev';\n const stack = devOutput.stack ?? 'dev';\n const baseDomain = `${tenant}-${env}.mesh.local`;\n\n // Build hostname \u2192 port map\n const services: Record<string, number> = {};\n for (const [name, service] of Object.entries(devOutput.services)) {\n if (service.port) {\n services[`${name}.${stack}.${appName}.${baseDomain}`] = service.port;\n }\n }\n for (const [name, tunnel] of Object.entries(devOutput.tunnels)) {\n if (tunnel.port) {\n services[`${name}.${stack}.${appName}.${baseDomain}`] = tunnel.port;\n }\n }\n\n if (Object.keys(services).length === 0) return;\n\n // Generate Caddyfile\n const lines = [\n '# Auto-generated by mesh dev \u2014 do not edit manually.',\n '',\n ':8080 {',\n ' respond /health \"OK\" 200',\n '}',\n '',\n ];\n for (const [hostname, port] of Object.entries(services)) {\n lines.push(`http://${hostname} {`);\n lines.push(` reverse_proxy localhost:${port}`);\n lines.push('}');\n lines.push('');\n }\n\n const caddyfile = lines.join('\\n');\n\n // Write to host's /etc/caddy via a throwaway container with a host volume mount.\n // The Docker socket is the HOST's, so -v /etc/caddy mounts the HOST path.\n execFileSync(\n 'docker',\n [\n 'run',\n '--rm',\n '-v',\n '/etc/caddy:/etc/caddy',\n 'busybox',\n 'sh',\n '-c',\n `cat > /etc/caddy/Caddyfile << 'CADDYEOF'\\n${caddyfile}\\nCADDYEOF`,\n ],\n { stdio: 'pipe' },\n );\n\n // Reload Caddy on the host via nsenter into PID 1's mount namespace\n execFileSync(\n 'docker',\n [\n 'run',\n '--rm',\n '--pid=host',\n '--privileged',\n 'busybox',\n 'nsenter',\n '-t',\n '1',\n '-m',\n '--',\n 'caddy',\n 'reload',\n '--config',\n '/etc/caddy/Caddyfile',\n '--adapter',\n 'caddyfile',\n ],\n { stdio: 'pipe' },\n );\n\n logSuccess('DevBox proxy updated:');\n for (const [hostname, port] of Object.entries(services)) {\n logInfo(` http://${hostname} \u2192 localhost:${port}`);\n }\n}\n\n// ============================================================================\n// Subdomain routing (Headscale MagicDNS + Caddy)\n// ============================================================================\n\ninterface SubdomainContext {\n tsHostname: string;\n tsIp: string;\n baseDomain: string; // e.g., \"hub.dev.devcontainer-test.vpn.internal\"\n dnsConfig: HeadscaleDnsConfig;\n}\n\nasync function setupSubdomainRouting(\n devOutput: DevOutput,\n appRoot: string,\n): Promise<SubdomainContext | null> {\n // 1. Get Tailscale info\n const tsInfo = await getTailscaleInfo();\n if (!tsInfo) return null;\n\n const appName = devOutput.app ?? path.basename(appRoot);\n const stack = devOutput.stack ?? 'dev';\n const baseDomain = `${appName}.${stack}.${tsInfo.hostname}.vpn.internal`;\n\n // 2. Derive Headscale DNS config from platform context (same convention as `mesh vpn`)\n const platform = devOutput.platform ?? { tenant: 'mesh', env: 'dev' };\n const dnsConfig = headscaleDnsConfig(platform.name ?? platform.tenant, platform.env);\n\n // 3. Build DNS records for all services + tunnels\n const records: DnsRecord[] = [];\n for (const [name, service] of Object.entries(devOutput.services)) {\n if (service.port) {\n records.push({ name: `${name}.${baseDomain}`, type: 'A', value: tsInfo.ip });\n }\n }\n for (const [name] of Object.entries(devOutput.tunnels)) {\n records.push({ name: `${name}.${baseDomain}`, type: 'A', value: tsInfo.ip });\n }\n\n // 4. Remove stale DNS records (best-effort)\n try {\n unregisterDnsRecords(dnsConfig, baseDomain);\n } catch {\n /* ignore */\n }\n\n // 5. Generate Caddyfile\n const caddyDir = '/tmp/mesh-dev-caddy';\n const caddyfile = path.join(caddyDir, 'Caddyfile');\n if (!fs.existsSync(caddyDir)) fs.mkdirSync(caddyDir, { recursive: true });\n\n // Build Caddy config \u2014 bind directly to the Tailscale IP on port 80.\n // In kernel tun mode, tailscale0 is a real interface so Caddy can listen\n // on it without any tailscale serve layer in between.\n const caddyLines: string[] = [`# mesh-dev: ${appName}/${stack} (${tsInfo.hostname})`, ''];\n for (const [name, service] of Object.entries(devOutput.services)) {\n if (service.port) {\n caddyLines.push(`http://${name}.${baseDomain} {`);\n caddyLines.push(` bind ${tsInfo.ip}`);\n caddyLines.push(` reverse_proxy localhost:${service.port}`);\n caddyLines.push('}');\n caddyLines.push('');\n }\n }\n for (const [name, tunnel] of Object.entries(devOutput.tunnels)) {\n caddyLines.push(`http://${name}.${baseDomain} {`);\n caddyLines.push(` bind ${tsInfo.ip}`);\n caddyLines.push(` reverse_proxy ${tunnel.host}:${tunnel.port}`);\n caddyLines.push('}');\n caddyLines.push('');\n }\n\n fs.writeFileSync(caddyfile, caddyLines.join('\\n'));\n\n // 6. Start or reload Caddy\n let caddyRunning = false;\n try {\n execFileSync('pgrep', ['-f', 'caddy run.*mesh-dev-caddy'], { stdio: 'pipe' });\n caddyRunning = true;\n } catch {\n /* not running */\n }\n\n if (caddyRunning) {\n try {\n execFileSync('caddy', ['reload', '--config', caddyfile, '--adapter', 'caddyfile'], {\n stdio: 'pipe',\n });\n } catch {\n logWarn('Caddy reload failed \u2014 check Caddyfile syntax');\n return null;\n }\n } else {\n try {\n execFileSync('which', ['caddy'], { stdio: 'pipe' });\n } catch {\n logWarn(\n 'Caddy not found. Install for subdomain routing: curl -fsSL https://caddyserver.com/api/download?os=linux&arch=arm64 -o /usr/local/bin/caddy && chmod +x /usr/local/bin/caddy',\n );\n return null;\n }\n const caddy = spawn('caddy', ['run', '--config', caddyfile, '--adapter', 'caddyfile'], {\n stdio: 'ignore',\n detached: true,\n cwd: caddyDir,\n });\n caddy.unref();\n }\n\n // 7. Register DNS records (after Caddy is confirmed running)\n try {\n const existing = readDnsRecords(dnsConfig);\n const allRecords = existing.filter((r) => !r.name.endsWith(baseDomain));\n allRecords.push(...records);\n registerDnsRecords(dnsConfig, allRecords);\n } catch {\n logWarn(\n 'DNS registration failed \u2014 Headscale pod may be unreachable. Dev routing may not work.',\n );\n return null;\n }\n\n return { tsHostname: tsInfo.hostname, tsIp: tsInfo.ip, baseDomain, dnsConfig };\n}\n\n// ============================================================================\n// Core actions\n// ============================================================================\n\n/**\n * Start all services in tmux windows.\n */\nasync function startServices(\n sessionName: string,\n appRoot: string,\n devOutput: DevOutput,\n headless: boolean,\n awsEnv: Record<string, string>,\n tunnelPlan: TunnelPlan = { transport: 'vpn-direct' },\n worktreeRoot?: string,\n taskQueueSuffix = '',\n): Promise<DevOutput> {\n if (!hasTmux()) {\n logError('tmux is required. Install with: brew install tmux');\n process.exit(1);\n }\n\n // Always kill any existing session and recreate for a clean start.\n // Tunnels (if any) are set up as part of this flow below.\n if (sessionExists(sessionName)) {\n logInfo(`Killing existing session: ${sessionName}`);\n killSession(sessionName);\n }\n\n const serviceNames = Object.keys(devOutput.services);\n if (serviceNames.length === 0) {\n logWarn('No services defined in dev output.');\n return devOutput;\n }\n\n // Create tmux session with a status window (always fresh).\n logInfo(`Creating tmux session: ${sessionName}`);\n execFileSync('tmux', ['new-session', '-d', '-s', sessionName, '-n', 'status', '-c', appRoot]);\n\n // Set AWS credentials on the session BEFORE starting anything that needs them\n // (SSM tunnels, services). tmux windows inherit the session environment.\n setTmuxEnv(sessionName, awsEnv);\n\n // Bring up VPC tunnels (rewriting devOutput.tunnels to localhost:PORT) via the\n // chosen backing. Tailscale (shared per-tenant userspace daemon): an explicit\n // `--transport tailscale` now hard-fails on any bring-up error (see below); only\n // an auto-resolved tailscale choice falls back to SSM. vpn-direct needs no tunnels.\n const hasTunnels = Object.keys(devOutput.tunnels).length > 0;\n let effectiveTransport = tunnelPlan.transport;\n if (hasTunnels && effectiveTransport === 'tailscale' && tunnelPlan.tailscale) {\n try {\n const rewritten = await startTailscaleTunnels(devOutput, tunnelPlan.tailscale);\n // Verify the forwarders actually ROUTE, not just bind (MESH-2268). Transport\n // selection picks tailscale on PRESENCE (a tailscaled binary exists), so an\n // auto-selected daemon can come up joined to a tailnet that doesn't route the\n // mesh VPC, or with a dead SOCKS upstream (MESH-2169) \u2014 the forwarder binds\n // its port either way and the bare-accept readiness gate below (waitForPort)\n // would pass it, letting services start and then die on a gRPC deadline.\n // Throw on a dead critical tunnel so the catch below applies the same\n // explicit-hard-fail-vs-auto-SSM-fallback policy as a bring-up failure \u2014 and\n // only commit the rewrite (reassign devOutput) once it holds, so an SSM\n // fallback runs startSsmTunnels on the ORIGINAL, un-rewritten tunnels.\n const dead = await firstUnroutableTunnel(rewritten.tunnels);\n if (dead) {\n throw new Error(\n `forwarder for '${dead}' bound but does not route the VPC ` +\n `(dead SOCKS upstream or non-routing tailnet)`,\n );\n }\n devOutput = rewritten;\n // Announce ONLY after the join + forwarders actually came up \u2014 the previous\n // pre-flight \"Using userspace-Tailscale tunnels\" printed before this even ran,\n // so a fallback still read as success (MESH-2098).\n logInfo('Connected: userspace-Tailscale tunnels for VPC resources (shared per tenant).');\n } catch (err) {\n const reason = err instanceof Error ? err.message : String(err);\n if (tunnelPlan.explicit) {\n // The user explicitly asked for --transport=tailscale. Don't silently\n // override that with SSM \u2014 surface the real reason (often a pending VPN\n // node registration whose URL was printed above) and let them act.\n logError(`Tailscale transport failed: ${reason}`);\n logInfo(\n 'If a VPN registration URL was shown above, open it to authorize this machine, then re-run.',\n );\n logInfo('Or switch backing explicitly: mesh dev --transport ssm');\n // We already killed the prior session and created a fresh (empty) one\n // above; tear it down so an explicit-tailscale failure leaves no orphaned\n // half-session behind.\n killSession(sessionName);\n process.exit(1);\n }\n logWarn(`Tailscale transport unavailable (${reason}) \u2014 falling back to SSM tunnels.`);\n effectiveTransport = 'ssm';\n }\n }\n if (hasTunnels && effectiveTransport === 'ssm') {\n devOutput = await startSsmTunnels(sessionName, devOutput);\n }\n if (hasTunnels && effectiveTransport !== 'vpn-direct') {\n\n // Gate service start on tunnel readiness: poll each tunnel's local port\n // until it accepts TCP. Without this, Temporal-connected services (api,\n // worker, vcs) raced the SSM tunnel and died connection-refused at launch.\n for (const [tName, tunnel] of Object.entries(devOutput.tunnels)) {\n if (tunnel.host !== 'localhost') continue; // not SSM-rewritten\n logInfo(`Waiting for tunnel ${tName} (localhost:${tunnel.port})...`);\n const ready = await waitForPort('localhost', tunnel.port, TUNNEL_READY_TIMEOUT_MS);\n if (!ready) {\n logError(\n `Tunnel '${tName}' did not become ready on localhost:${tunnel.port} within ${TUNNEL_READY_TIMEOUT_MS / 1000}s.`,\n );\n logInfo(` Check the tunnel window for errors: tmux attach -t ${sessionName} (window tunnel-${tName})`);\n logInfo(' Common causes: expired AWS credentials, bastion stopped, session-manager-plugin errors.');\n throw new Error(\n `SSM tunnel '${tName}' not ready on localhost:${tunnel.port} after ${TUNNEL_READY_TIMEOUT_MS / 1000}s`,\n );\n }\n logSuccess(` Tunnel ready: ${tName} (localhost:${tunnel.port})`);\n }\n }\n\n const tunnelNames = Object.keys(devOutput.tunnels);\n\n // Set up subdomain routing if Tailscale is available\n const subdomainCtx = await setupSubdomainRouting(devOutput, appRoot);\n\n // Log VPC connections\n if (tunnelNames.length > 0) {\n const isSSM = Object.values(devOutput.tunnels).some(\n (t) => t.host === 'localhost' && t.port >= SSM_TUNNEL_BASE_PORT,\n );\n logSuccess(isSSM ? 'SSM tunnel connections:' : 'VPN direct connections:');\n for (const [tName, tunnel] of Object.entries(devOutput.tunnels)) {\n if (subdomainCtx) {\n logInfo(` ${tName} \\u2192 http://${tName}.${subdomainCtx.baseDomain}`);\n } else {\n logInfo(` ${tName} \\u2192 ${tunnel.host}:${tunnel.port}`);\n }\n }\n }\n\n // Resolve secrets from Secrets Manager\n let secretEnvVars: Record<string, string> = {};\n if (devOutput.secrets && Object.keys(devOutput.secrets).length > 0) {\n secretEnvVars = await resolveSecrets(devOutput.secrets);\n }\n\n // Resolve Temporal auth credentials from SSM when a temporal endpoint is configured.\n const tenant = devOutput.platform?.tenant ?? 'mesh';\n const platformEnv = devOutput.platform?.env ?? 'dev';\n\n // Write a session-scoped kubeconfig (aws eks get-token) so the kubectl calls\n // below (encoding-key read, temporal-pod env fallback) don't depend on an\n // ambient ~/.kube/config. Best-effort: continue without it if unresolved.\n // The local platform (`mesh start`) has no cluster \u2014 skip entirely.\n const isLocalPlatform = tenant === 'local';\n if (!isLocalPlatform) {\n // Hub platform name \u2014 the EKS export lives under it, not under a hardcoded\n // \"mesh\" (MESH-2515); same axis as the bastion resolution.\n const platformName = resolveHubPlatformName(devOutput.platform);\n const kubeconfigPath = await ensureKubeconfig(platformName, platformEnv, sessionName, {\n onError: ({ parameter, error }) =>\n logWarn(\n `EKS cluster resolve failed (${parameter}): ${error instanceof Error ? `${error.name}: ${error.message}` : String(error)}`,\n ),\n });\n if (kubeconfigPath) {\n process.env.KUBECONFIG = kubeconfigPath;\n setTmuxEnv(sessionName, { KUBECONFIG: kubeconfigPath });\n logSuccess(`Kubeconfig resolved from SSM (hub ${platformName}/${platformEnv}) \u2192 ${kubeconfigPath}`);\n } else {\n logWarn('Could not resolve EKS kubeconfig from SSM; kubectl calls will use ambient config (if any).');\n }\n }\n\n let temporalAuthVars: Record<string, string> = {};\n if (devOutput.tunnels['temporal']) {\n // Deliberately NOT the `?? 'mesh'` fallback the EKS path above uses: the\n // Temporal-auth fallback is `?? tenant` (dedicated tenants may run their\n // own Temporal). Whether that difference is correct is MESH-2551.\n temporalAuthVars = await resolveTemporalAuth(tenant, platformEnv, devOutput.platform?.name ?? tenant);\n\n // Resolve the encoding key from K8s so local dev can decrypt\n // payloads created by deployed workers.\n const appName = devOutput.app ?? '';\n if (appName) {\n const encodingKey = resolveTemporalEncodingKey(tenant, platformEnv, appName);\n if (encodingKey) {\n temporalAuthVars.TEMPORAL_ENCODING_KEY = encodingKey;\n }\n }\n\n // Set TEMPORAL_ADDRESS to the VPC endpoint for direct VPN access (or the\n // pinned loopback address under SSM fallback \u2014 see tunnelClientAddress).\n const temporalTunnel = devOutput.tunnels['temporal'];\n temporalAuthVars.TEMPORAL_ADDRESS = tunnelClientAddress(temporalTunnel);\n }\n\n // Set shared env vars (secrets + temporal auth) on the tmux session.\n // AWS creds were already set earlier (before SSM tunnels started).\n setTmuxEnv(sessionName, secretEnvVars);\n setTmuxEnv(sessionName, temporalAuthVars);\n\n // Inject dev user identity from mesh login credentials so services can\n // emulate the oauth2-proxy auth headers locally.\n //\n // The credentials are stored under the platform context (e.g. 'mesh.dev'),\n // not the tenant name. Use 'mesh' as the platform name since all tenants\n // share the same Zitadel instance.\n //\n // Services (e.g., Hub UI) use these env vars as a fallback when the real\n // oauth2-proxy `X-Forwarded-*` request headers are absent:\n // DEV_USER_ID - subject from idToken, matches conversation ownership\n // DEV_USER_EMAIL - user email from idToken\n // DEV_USER_ID_TOKEN - full idToken JWT (profile claims, authorization hint)\n // DEV_USER_ACCESS_TOKEN - full accessToken JWT (has project:roles claim)\n // Local platform creds live under the `local` context (mesh login local).\n const credContext = devOutput.platform\n ? isLocalPlatform\n ? 'local'\n : `mesh.${devOutput.platform.env}`\n : null;\n const devUserVars = resolveDevUserVars(devOutput);\n if (Object.keys(devUserVars).length > 0) {\n setTmuxEnv(sessionName, devUserVars);\n logSuccess(`Dev user injected from mesh login: ${credContext}`);\n\n // Serve a continuously-fresh dev-user token so services survive past the\n // ~1h Zitadel horizon without a restart (MESH-2039). The static vars above\n // remain the fallback when this URL is absent. App-agnostic: gated on the\n // platform context, not the app \u2014 any `mesh dev` app inherits it.\n const tokenPort = await findFreePort();\n const tokenUrl = `http://127.0.0.1:${tokenPort}`;\n setTmuxEnv(sessionName, { DEV_USER_TOKEN_URL: tokenUrl });\n execFileSync('tmux', ['new-window', '-t', sessionName, '-n', 'token-server']);\n execFileSync(\n 'tmux',\n ['set-option', '-t', `${sessionName}:token-server`, 'remain-on-exit', 'on'],\n { stdio: 'ignore' },\n );\n execFileSync('tmux', [\n 'send-keys',\n '-t',\n `${sessionName}:token-server`,\n `npx mesh dev __token-server ${tokenPort} ${credContext}`,\n 'Enter',\n ]);\n // Best-effort readiness so the first requests land (non-fatal).\n for (let i = 0; i < 15 && !(await isPortListening(tokenPort)); i++) {\n await new Promise((r) => setTimeout(r, 200));\n }\n logSuccess(`Dev-user token-server: ${tokenUrl} (context ${credContext})`);\n } else if (credContext) {\n logWarn(`No mesh login credentials found for '${credContext}'.`);\n logInfo(` Run: mesh login ${credContext}`);\n logInfo(' Hub UI will show unauthenticated state without valid credentials.');\n }\n\n const monorepoRoot = findMonorepoRoot();\n\n for (const [name, service] of Object.entries(devOutput.services)) {\n const cmd = service.command.join(' ');\n\n // Skip services with no dev command (e.g., deployed-only like ApiDocs)\n if (!cmd) {\n logInfo(`Skipped: ${name} (no dev command, deployed to K8s)`);\n continue;\n }\n\n const serviceDir = path.resolve(appRoot, rebaseServiceSrc(service.src, monorepoRoot));\n\n // Wrong-worktree guard (MESH-2013): if `rebaseServiceSrc` couldn't re-root the\n // deploy-time absolute path onto THIS worktree, `serviceDir` can point into a\n // DIFFERENT worktree \u2014 silently running stale code. Refuse rather than launch it.\n if (worktreeRoot && fs.existsSync(serviceDir)) {\n const wtRootWithSep = worktreeRoot.endsWith(path.sep) ? worktreeRoot : worktreeRoot + path.sep;\n if (serviceDir !== worktreeRoot && !serviceDir.startsWith(wtRootWithSep)) {\n logError(\n `Refusing to launch '${name}': its source resolved to ${serviceDir}, ` +\n `outside this worktree (${worktreeRoot}). The stack was likely deployed ` +\n `from another worktree. Re-run \\`mesh deploy up\\` here, or pass --app.`,\n );\n process.exit(1);\n }\n }\n\n // Skip services whose source directory doesn't exist in this worktree.\n // This happens when the Pulumi stack was deployed from a different branch\n // that added a service not yet present here (e.g., hub-worker added on\n // feature/hub-credential-management but absent from feature/app-detail-redesign).\n if (!fs.existsSync(serviceDir)) {\n logWarn(\n `Skipped: ${name} (source directory not found: ${serviceDir}` +\n `${serviceDir !== service.src ? ` \u2014 rebased from ${service.src}` : ''})`,\n );\n continue;\n }\n // Per-service env vars are written to a 0600 env file and `source`d by\n // the launch command, scoping them to the process (no cross-service\n // leaks through the tmux session environment) while keeping the\n // send-keys string short \u2014 inlining the full env used to intermittently\n // exceed what tmux send-keys delivers intact, silently truncating the\n // command so the service never started.\n //\n // Overlay the RESOLVED Temporal vars (real encoding key + tunnel address +\n // M2M auth, fetched from K8s/SSM) on top of the dev-output env. The dev\n // output carries placeholder values from the Agent's Temporal link (e.g.\n // a `dev-encoding-key-*` placeholder), and the per-service env would\n // otherwise shadow the session-level resolved values \u2014 desyncing services\n // that DO carry the placeholder (worker) from those that don't (api),\n // which breaks payload encryption (mismatched encoding keys \u2192 decode null).\n const serviceVars = {\n ...getServiceEnvVars(service, devOutput.tunnels),\n ...temporalAuthVars,\n // Overlay the resolved dev-user identity for the same reason as the\n // Temporal vars: the dev output may carry a placeholder (e.g. hub ui's\n // DEV_USER_ACCESS_TOKEN=\"dev-local\"), and since the sourced env file\n // wins over the tmux session env, the placeholder would clobber the\n // real token injected above \u2014 silently 401ing tenant-scoped Hub views.\n ...devUserVars,\n // Per-worktree Temporal task-queue isolation (MESH-2013 Slice 2): agent\n // workers/apps append this to their task-queue names so concurrent\n // worktrees don't steal each other's workflow tasks. Empty on the primary\n // checkout \u2192 omitted \u2192 unchanged historical behavior.\n ...(taskQueueSuffix ? { MESH_TASK_QUEUE_SUFFIX: taskQueueSuffix } : {}),\n };\n const envFilePath = getServiceEnvFilePath(sessionName, name);\n writeEnvFile(envFilePath, serviceVars);\n\n // Local mode ships the service's stdout to the platform's log pipeline\n // via OTLP (assets/log-shipper.mjs): the OTEL_* vars in the env file\n // carry the hosted k8s_* attribution, so the Hub's logs view covers\n // local runs with zero file plumbing.\n const launchCmd = buildLaunchCommand(\n envFilePath,\n serviceDir,\n cmd,\n service.env?.OTEL_RESOURCE_ATTRIBUTES ? logShipperPath() : undefined,\n );\n\n execFileSync('tmux', ['new-window', '-t', sessionName, '-n', name, '-c', serviceDir]);\n\n // Keep window alive on exit so errors are visible\n execFileSync('tmux', ['set-option', '-t', `${sessionName}:${name}`, 'remain-on-exit', 'on'], {\n stdio: 'ignore',\n });\n\n execFileSync('tmux', ['send-keys', '-t', `${sessionName}:${name}`, launchCmd, 'Enter']);\n\n // Log the ACTUAL launch dir (`serviceDir`, after the worktree rebase), not the\n // raw deploy-time `service.src` \u2014 printing the pre-rebase path made a correctly\n // re-rooted service look like it was running from a different (stale) worktree.\n logSuccess(`Started: ${name} (${serviceDir}, port ${service.port})`);\n }\n\n // Generate reverse proxy config for DevBox hostname-based routing.\n if (process.env.DEVCONTAINER === '1') {\n try {\n await updateDevboxProxy(devOutput, appRoot);\n } catch (e) {\n logWarn(`Could not update devbox proxy: ${(e as Error).message}`);\n }\n }\n\n // Run live status updates in the status window\n const statusCmd = `watch -n2 -t npx mesh dev --status --session '${sessionName}'`;\n execFileSync('tmux', ['send-keys', '-t', `${sessionName}:status`, statusCmd, 'Enter']);\n\n console.log('');\n logSuccess(`Dev session started: ${sessionName}`);\n console.log('');\n\n if (tunnelNames.length > 0) {\n console.log('Connections (VPN direct):');\n for (const tName of tunnelNames) {\n const t = devOutput.tunnels[tName]!;\n if (subdomainCtx) {\n console.log(` ${tName.padEnd(20)} http://${tName}.${subdomainCtx.baseDomain}`);\n } else {\n console.log(` ${tName.padEnd(20)} ${t.host}:${t.port}`);\n }\n }\n console.log('');\n }\n\n console.log('Services:');\n for (const name of serviceNames) {\n const s = devOutput.services[name]!;\n const hasCmd = s.command && s.command.length > 0;\n if (hasCmd) {\n if (subdomainCtx && s.port) {\n console.log(` ${name.padEnd(20)} http://${name}.${subdomainCtx.baseDomain}`);\n } else {\n const addr = s.port ? `http://localhost:${s.port}` : '(no port)';\n console.log(` ${name.padEnd(20)} ${addr}`);\n }\n } else {\n console.log(` ${name.padEnd(20)} (deployed)`);\n }\n }\n\n console.log('');\n\n if (!headless) {\n logInfo('Attaching to tmux session...');\n if (process.env.TMUX) {\n spawnSync('tmux', ['switch-client', '-t', sessionName], { stdio: 'inherit' });\n } else {\n spawnSync('tmux', ['attach', '-t', sessionName], { stdio: 'inherit' });\n }\n } else {\n console.log(`Attach with: tmux attach -t ${sessionName}`);\n console.log(`Stop with: mesh dev --kill`);\n console.log('');\n }\n\n // Return the (possibly SSM-tunnel-rewritten) devOutput so the caller can\n // persist it in session state for --status / restart.\n return devOutput;\n}\n\n/**\n * Show status of running services.\n */\nasync function showStatus(\n sessionName: string,\n devOutput: DevOutput,\n asJson: boolean,\n): Promise<void> {\n if (!sessionExists(sessionName)) {\n if (asJson) {\n console.log(JSON.stringify({ running: false, session: sessionName }));\n } else {\n logInfo(`No active session: ${sessionName}`);\n }\n return;\n }\n\n // Get tmux window list\n let windows: string[] = [];\n try {\n const raw = execFileSync(\n 'tmux',\n ['list-windows', '-t', sessionName, '-F', '#{window_name} #{pane_dead}'],\n { encoding: 'utf-8' },\n );\n windows = raw.trim().split('\\n');\n } catch {\n // Session might have disappeared\n }\n\n const windowStatus: Record<string, string> = {};\n for (const line of windows) {\n const [name, dead] = line.split(' ');\n if (name) windowStatus[name] = dead === '1' ? 'exited' : 'running';\n }\n\n const tunnelNames = Object.keys(devOutput.tunnels);\n // Live-probe each tunnel so a mid-session tunnel death shows as DOWN here\n // (this render runs every ~2s in the status window) \u2014 MESH-2016.\n const tunnelHealth = await probeTunnelHealth(devOutput.tunnels);\n const healthByName = new Map(tunnelHealth.map((h) => [h.name, h]));\n\n if (asJson) {\n const services: Record<string, object> = {};\n for (const [name, svc] of Object.entries(devOutput.services)) {\n services[name] = {\n status: windowStatus[name] ?? 'unknown',\n port: svc.port,\n src: svc.src,\n };\n }\n const tunnels: Record<string, object> = {};\n for (const [name, tun] of Object.entries(devOutput.tunnels)) {\n tunnels[name] = {\n host: tun.host,\n port: tun.port,\n reachable: healthByName.get(name)?.reachable ?? false,\n };\n }\n console.log(\n JSON.stringify({ running: true, session: sessionName, services, tunnels }, null, 2),\n );\n } else {\n console.log('\\u2500\\u2500 mesh dev \\u2500\\u2500');\n console.log('');\n console.log(`Session: ${sessionName}`);\n\n if (tunnelNames.length > 0) {\n console.log('');\n for (const line of formatTunnelHealth(tunnelHealth)) console.log(line);\n }\n\n console.log('');\n console.log('Services:');\n for (const [name, svc] of Object.entries(devOutput.services)) {\n const hasCmd = svc.command && svc.command.length > 0;\n if (!hasCmd) {\n console.log(` \u2601 ${name.padEnd(16)} deployed ${svc.src}`);\n continue;\n }\n const status = windowStatus[name] ?? 'unknown';\n const icon = status === 'running' ? '\u25CF' : status === 'exited' ? '\u2717' : '?';\n const addr = svc.port ? `:${svc.port}` : '';\n console.log(` ${icon} ${name.padEnd(16)} ${status.padEnd(10)} ${addr.padEnd(8)} ${svc.src}`);\n }\n console.log('');\n console.log('Commands:');\n console.log(' mesh dev restart <s> Restart a service');\n console.log(' mesh dev logs <s> Tail service logs');\n console.log(' mesh dev --kill Stop everything');\n console.log('');\n console.log('tmux: Ctrl+b n/p switch windows, d detach');\n }\n}\n\n/**\n * Restart a single service window.\n */\nasync function restartService(\n sessionName: string,\n serviceName: string,\n appRoot: string,\n devOutput: DevOutput,\n awsEnv: Record<string, string>,\n opts?: { refreshEnv?: boolean; stack?: string; sessionState?: SessionState | null },\n): Promise<void> {\n let service = devOutput.services[serviceName];\n if (!service) {\n logError(`Unknown service: ${serviceName}`);\n logInfo(`Available: ${Object.keys(devOutput.services).join(', ')}`);\n process.exit(1);\n }\n\n if (!sessionExists(sessionName)) {\n logError(`No active session: ${sessionName}. Run 'mesh dev' first.`);\n process.exit(1);\n }\n\n // --refresh-env: regenerate this service's env file from CURRENT stack/SSM\n // outputs BEFORE killing the running process, so a failed read leaves the\n // good env file (and the running service) untouched (fail-closed).\n if (opts?.refreshEnv) {\n if (!opts.stack) {\n logError('--refresh-env: no stack resolved; keeping existing env and NOT restarting.');\n return;\n }\n // The session's allocated devOutput pins the ports/tunnels to reuse.\n const pinned = opts.sessionState?.devOutput ?? devOutput;\n let fresh: DevOutput;\n try {\n fresh = getDevOutput(appRoot, opts.stack, awsEnv);\n } catch (err) {\n logError(\n `--refresh-env: failed to read stack output for '${opts.stack}'. Keeping the existing env file for '${serviceName}' and NOT restarting.`,\n );\n logInfo(String((err as Error)?.message ?? err));\n return;\n }\n const merged = mergePinnedPorts(fresh, pinned);\n const mergedService = merged.services[serviceName];\n if (!mergedService) {\n logError(\n `--refresh-env: service '${serviceName}' is absent from the fresh stack output. Keeping the existing env file and NOT restarting.`,\n );\n return;\n }\n const temporalAuthVars = await resolveTemporalAuthVars(sessionName, merged);\n // Recompute the per-worktree suffix (deterministic from the worktree path,\n // so it matches what launch wrote) \u2014 a restarted service must keep polling\n // this worktree's isolated task queue (MESH-2013 Slice 2).\n const { taskQueueSuffix } = resolveWorktreeIdentity(appRoot);\n const serviceVars = {\n ...getServiceEnvVars(mergedService, merged.tunnels),\n ...temporalAuthVars,\n // Same overlay as launch: without it, --refresh-env rewrites the env\n // file from dev output and its DEV_USER_* placeholders clobber the real\n // token from `mesh login` (the \"restart silently 401s the Hub\" trap).\n ...resolveDevUserVars(merged),\n ...(taskQueueSuffix ? { MESH_TASK_QUEUE_SUFFIX: taskQueueSuffix } : {}),\n };\n writeEnvFile(getServiceEnvFilePath(sessionName, serviceName), serviceVars);\n // Relaunch from the refreshed service definition (command/src may have changed).\n service = mergedService;\n logSuccess(`Regenerated env for '${serviceName}' from current stack/SSM outputs.`);\n }\n\n const target = `${sessionName}:${serviceName}`;\n\n // Kill the current pane process and respawn\n try {\n execFileSync('tmux', ['respawn-pane', '-k', '-t', target], { stdio: 'ignore' });\n } catch {\n // Window might not exist yet\n logError(`Window '${serviceName}' not found in session.`);\n process.exit(1);\n }\n\n // Refresh shared env (AWS creds may have rotated) on the session.\n setTmuxEnv(sessionName, awsEnv);\n\n const cmd = service.command.join(' ');\n\n // Source the SAME env file written at launch \u2014 it is the session's env\n // contract for this service, guaranteeing a byte-identical environment.\n // Reconstructing env here has historically diverged from launch (e.g.\n // TEMPORAL_ENCODING_KEY drift \u2192 \"cannot decrypt payload\" / missing key \u2192\n // \"Unknown encoding: binary/encrypted\").\n const envFilePath = getServiceEnvFilePath(sessionName, serviceName);\n let restartCmd: string;\n if (fs.existsSync(envFilePath)) {\n const serviceDir = path.resolve(appRoot, rebaseServiceSrc(service.src, findMonorepoRoot()));\n // Keep the local log pipeline attached across restarts.\n restartCmd = buildLaunchCommand(\n envFilePath,\n serviceDir,\n cmd,\n service.env?.OTEL_RESOURCE_ATTRIBUTES ? logShipperPath() : undefined,\n );\n } else {\n logWarn(\n `No launch env file for '${serviceName}' (${envFilePath}) \u2014 session predates env-file launches.`,\n );\n logWarn('Falling back to reconstructed env; restart `mesh dev` for a faithful environment.');\n const serviceVars = getServiceEnvVars(service, devOutput.tunnels);\n restartCmd = `${envPrefix(serviceVars)}${cmd}`;\n }\n execFileSync('tmux', ['send-keys', '-t', target, restartCmd, 'Enter']);\n\n logSuccess(`Restarted: ${serviceName}`);\n}\n\n/**\n * Capture and display logs from a service window.\n */\nfunction showLogs(sessionName: string, serviceName: string, tail: number): void {\n if (!sessionExists(sessionName)) {\n logError(`No active session: ${sessionName}. Run 'mesh dev' first.`);\n process.exit(1);\n }\n\n const target = `${sessionName}:${serviceName}`;\n\n try {\n const result = execFileSync('tmux', ['capture-pane', '-t', target, '-p', '-S', `-${tail}`], {\n encoding: 'utf-8',\n });\n process.stdout.write(result);\n } catch {\n logError(`Could not capture logs for '${serviceName}'.`);\n logInfo('Is the service name correct? Check with: mesh dev --status');\n process.exit(1);\n }\n}\n\n// ============================================================================\n// Command registration\n// ============================================================================\n\n/**\n * Assemble a {@link DoctorContext} for the current app/stack/session, resolving\n * the deployer role the same way the `restart`/launch paths do (default role +\n * Zitadel-claim admin selection). Used by `mesh dev doctor`.\n */\nfunction buildDoctorContext(\n appRoot: string,\n stack: string,\n sessionName: string,\n): DoctorContext {\n const state = loadSessionState(sessionName);\n const defaultDeployerRole = readStackConfig(appRoot, stack, 'mesh:deployerRole');\n const adminDeployerRole = readStackConfig(appRoot, stack, 'mesh:adminDeployerRole');\n const platformContext = derivePlatformContext(appRoot, stack);\n let deployerRole = defaultDeployerRole;\n if (defaultDeployerRole) {\n const meshCreds = platformContext ? readCredentials(platformContext) : null;\n const idToken =\n meshCreds && new Date(meshCreds.expiresAt) > new Date() ? meshCreds.idToken : null;\n deployerRole = selectRoleForCaller(idToken, {\n defaultRole: defaultDeployerRole,\n adminRole: adminDeployerRole ?? undefined,\n });\n }\n return {\n appRoot,\n stack,\n sessionName,\n deployerRole,\n platformContext,\n credMethod: null,\n sessionState: state,\n };\n}\n\nexport function registerDevCommand(program: Command): void {\n const dev = program\n .command('dev')\n .description('Start local dev environment (reads Pulumi stack outputs)')\n .option('--app <path>', 'Path to a Pulumi app (relative to monorepo root or cwd)')\n .option('--stack <stack>', 'Pulumi stack name (default: auto-detect)')\n .addOption(new Option('--stage <stack>', 'Deprecated alias for --stack').hideHelp())\n .option('--headless', 'Start without attaching to tmux')\n .option('--kill', 'Kill existing dev session')\n .option('--status', 'Show service status')\n .option('--json', 'Output status as JSON (with --status)')\n .option(\n '--session <name>',\n 'Override the tmux session name (auto-derived per git worktree by default \u2014 omit to keep concurrent worktrees isolated)',\n )\n .option('--dry-run', 'Print the resolved worktree/session/port plan and exit without launching')\n .option('--force', 'Relaunch even if workflow code changed since launch (may strand in-flight conversations)')\n .option('--profile <name>', 'AWS SSO profile to use (e.g., mesh-dev)')\n .addOption(\n new Option(\n '--transport <mode>',\n 'Tunnel backing (default: auto \u2014 Tailscale when available, else SSM/VPN)',\n ).choices(['auto', 'ssm', 'tailscale']),\n )\n .option(\n '--local',\n 'Run against the local Mesh platform from `mesh start` (no AWS, no VPN, no Pulumi state). Auto-selected when the app has no Pulumi.yaml.',\n )\n .option(\n '--externals [names]',\n \"Also realize the app's declared external services (package.json \u2192 mesh.externals): all of them, or a comma-separated subset of name[=mode] entries. Modes: mock (emulate \u2014 OpenAPI spec via Prism, or a mock process), local (a local version via docker compose, e.g. a vendor DB replica), remote (connect to the actual service \u2014 vendor sandbox credentials, or the external configured in the app's tenant environment). name=mode overrides the declaration's default for this run (e.g. plaid-db=remote). Each realization seeds the ExternalService credential secret so resolveCredentials() runs unchanged. Local mode only.\",\n )\n .option('--mock [names]', 'Alias for --externals.')\n .option(\n '--runner <runner>',\n \"Process runner for local mode: 'tmux' (default \u2014 dev machines) or 'docker' (CI/headless: services run as a docker compose project with host networking; Linux semantics).\",\n 'tmux',\n );\n\n // Hidden: the dev-user token-server (MESH-2039). Launched into its own tmux\n // window by the dev launcher; serves a continuously-fresh dev-user token.\n dev\n .command('__token-server <port> <context>', { hidden: true })\n .action(async (port: string, context: string) => {\n const { startTokenServer } = await import('./dev-token-server.js');\n await startTokenServer(Number(port), context);\n });\n\n // Default action: start or show status\n dev.action(async (options: DevOptions) => {\n // An explicit --profile must win over stale shell-exported STS credentials.\n // The AWS SDK/CLI prefer AWS_ACCESS_KEY_ID over AWS_PROFILE, so clear any\n // static credentials before resolving the deployer role.\n if (options.profile) {\n applyAwsProfileOverride(options.profile);\n }\n\n // Fast-path: --status/--kill with explicit --session can skip app root resolution\n if (options.session && (options.status || options.kill)) {\n const sessionName = options.session;\n if (loadSessionState(sessionName)?.runner === 'docker') {\n if (options.kill) {\n dockerDevDown(sessionName);\n composeExternalsDown(loadSessionState(sessionName)?.composeExternals);\n localProbesRemove(loadSessionState(sessionName)?.externalProbeFiles);\n removeSessionState(sessionName);\n logSuccess(`Killed docker dev session: ${sessionName}`);\n } else {\n console.log(dockerDevPs(sessionName));\n }\n return;\n }\n if (options.kill) {\n composeExternalsDown(loadSessionState(sessionName)?.composeExternals);\n localProbesRemove(loadSessionState(sessionName)?.externalProbeFiles);\n // Clean up DNS records for this app\n try {\n const devOutput = loadSessionState(sessionName)?.devOutput;\n if (devOutput) {\n const tsInfo = await getTailscaleInfo();\n if (tsInfo) {\n const appName = devOutput.app ?? sessionName.replace(/-dev$/, '');\n const stack = devOutput.stack ?? 'dev';\n const baseDomain = `${appName}.${stack}.${tsInfo.hostname}.vpn.internal`;\n const platform = devOutput.platform ?? { tenant: 'mesh', env: 'dev' };\n unregisterDnsRecords(headscaleDnsConfig(platform.name ?? platform.tenant, platform.env), baseDomain);\n }\n }\n } catch {\n /* best effort */\n }\n\n if (sessionExists(sessionName)) {\n killSession(sessionName);\n logSuccess(`Killed session: ${sessionName}`);\n } else {\n logInfo(`No active session: ${sessionName}`);\n }\n removeSessionState(sessionName);\n return;\n }\n // --status with --session: use state file, no Pulumi needed\n const state = loadSessionState(sessionName);\n if (state) {\n await showStatus(sessionName, state.devOutput, !!options.json);\n return;\n }\n // No state \u2014 fall through to normal flow\n }\n\n const appRoot = findAppRoot(options.app);\n const projectName = getProjectName(appRoot);\n // Port block scoped to (worktree, app): concurrent sibling-app sessions\n // must draw disjoint ports (probing races slow boots). Scoped once here so\n // local and tethered modes resolve the SAME plan \u2014 every other field stays\n // worktree-scoped, so session naming and task queues are unaffected.\n const worktree = withAppScopedPortBlock(resolveWorktreeIdentity(appRoot), appRoot);\n const sessionName = options.session ?? deriveSessionName(projectName, worktree);\n\n // --kill\n if (options.kill) {\n composeExternalsDown(loadSessionState(sessionName)?.composeExternals);\n localProbesRemove(loadSessionState(sessionName)?.externalProbeFiles);\n if (loadSessionState(sessionName)?.runner === 'docker') {\n dockerDevDown(sessionName);\n removeSessionState(sessionName);\n logSuccess(`Killed docker dev session: ${sessionName}`);\n return;\n }\n // Tailscale VPN tunnels are machine-global + shared across sessions, so\n // they persist on purpose after a kill. Capture the tenant before state\n // is removed so we can point at the explicit stop below.\n const killTsTenant = loadSessionState(sessionName)?.devOutput.platform?.name ?? 'mesh';\n // Clean up DNS records for this app\n try {\n const devOutput = loadSessionState(sessionName)?.devOutput;\n if (devOutput) {\n const tsInfo = await getTailscaleInfo();\n if (tsInfo) {\n const appName = devOutput.app ?? projectName;\n const stack = devOutput.stack ?? 'dev';\n const baseDomain = `${appName}.${stack}.${tsInfo.hostname}.vpn.internal`;\n const platform = devOutput.platform ?? { tenant: 'mesh', env: 'dev' };\n unregisterDnsRecords(headscaleDnsConfig(platform.name ?? platform.tenant, platform.env), baseDomain);\n }\n }\n } catch {\n /* best effort */\n }\n\n if (sessionExists(sessionName)) {\n killSession(sessionName);\n logSuccess(`Killed session: ${sessionName}`);\n } else {\n logInfo(`No active session: ${sessionName}`);\n }\n removeSessionState(sessionName);\n if (readTailscaleState(killTsTenant)) {\n logInfo(\n `VPN tunnels persist across sessions \u2014 stop them with: mesh vpn tunnel down --tenant ${killTsTenant}`,\n );\n }\n return;\n }\n\n // \u2500\u2500 Local mode (design \u00A75.2) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Explicit --local, or auto when the app has no Pulumi program at all\n // (hasStackBacking also checks the monorepo ROOT \u2014 apps like apps/hub\n // deploy via a root program and must keep the tethered default).\n // Synthesizes DevOutput from repo conventions and wires services to the\n // `mesh start` platform: no AWS credentials, no VPN, no Pulumi state.\n const localMode = !!options.local || !hasStackBacking(appRoot);\n if (localMode) {\n // Read-only status query: report and exit BEFORE any side effect\n // (platform boot, Zitadel provisioning, registry writes) \u2014 parity\n // with the tethered path's early --status short-circuit.\n if (options.status) {\n const state = loadSessionState(sessionName);\n if (state?.runner === 'docker') {\n console.log(dockerDevPs(sessionName));\n return;\n }\n const statusOutput =\n state?.devOutput ??\n (buildLocalDevOutput(appRoot, detectLocalTenant(appRoot), { mocks: {} }) as unknown as DevOutput);\n showStatus(sessionName, statusOutput, !!options.json);\n return;\n }\n\n const dockerRunner = options.runner === 'docker';\n if (!dockerRunner && !hasTmux()) {\n logError('tmux is not installed. Fix: brew install tmux (or use --runner docker)');\n process.exit(1);\n }\n await ensureLocalPlatformRunning();\n const localTenant = detectLocalTenant(appRoot);\n logInfo(`Project: ${projectName}, Stack: local (mesh start platform)`);\n\n // --externals (alias --mock): resolve the requested subset of the\n // app's declared externals (package.json \u2192 mesh.externals). Entries\n // are name[=mode] \u2014 an explicit mode overrides the declaration's\n // default for this run (materialized onto the decl so every\n // downstream externalMode() call agrees). Mock-mode externals join\n // the same orchestration as services named mock-{name}; all\n // realizations get their credential secret seeded after ports are\n // final.\n const externalsRequest = options.externals ?? options.mock;\n let selectedMocks: Record<string, LocalMockDecl> = {};\n // The externals the developer NAMED (empty for the bare flag, which\n // selects everything declared). Failing to realize one of these is\n // fatal; failing to realize one the developer never asked for by name\n // only costs that external.\n const requestedExplicitly = new Set<string>();\n if (externalsRequest) {\n const declared = readLocalMocks(appRoot);\n let requested: string[];\n let overrides = new Map<string, ExternalMode>();\n if (externalsRequest === true) {\n requested = Object.keys(declared);\n } else {\n ({ names: requested, overrides } = parseExternalsSelection(String(externalsRequest)));\n for (const name of requested) requestedExplicitly.add(name);\n }\n const unknown = requested.filter((name) => !declared[name]);\n if (unknown.length > 0) {\n throw new MeshCliError(\n `Unknown external(s): ${unknown.join(', ')} \u2014 declared in package.json mesh.externals: ${Object.keys(declared).join(', ') || '(none)'}`,\n { remediation: { docs: 'package.json \u2192 \"mesh\": { \"externals\": { \u2026 } }' } },\n );\n }\n if (requested.length === 0) {\n logWarn('No externals declared (package.json \u2192 mesh.externals) \u2014 continuing without.');\n }\n selectedMocks = Object.fromEntries(\n requested.map((name) => [\n name,\n overrides.has(name) ? { ...declared[name]!, mode: overrides.get(name)! } : declared[name]!,\n ]),\n );\n // Validate every declaration's resolved mode up front \u2014 a bad decl\n // (or an override the decl can't satisfy) should fail here, not\n // after half the orchestration is up.\n for (const [name, decl] of Object.entries(selectedMocks)) externalMode(name, decl);\n }\n\n const rawDevOutput = buildLocalDevOutput(appRoot, localTenant, {\n mocks: selectedMocks,\n }) as unknown as DevOutput;\n\n // --dry-run (worktree-plan parity with tethered mode): print the\n // resolved session/port plan and exit before any side effect \u2014\n // no Zitadel provisioning, no registry writes, no launch.\n if (options.dryRun) {\n printDevPlan(sessionName, appRoot, worktree, await allocatePorts(rawDevOutput, worktree));\n // Non-service realizations (local/remote) don't appear in the port\n // plan \u2014 list them so the dry run shows the whole picture.\n for (const [name, decl] of Object.entries(selectedMocks)) {\n const mode = externalMode(name, decl);\n if (mode === 'local') {\n console.log(` external ${name.padEnd(18)} local \u2014 docker compose (${decl.compose}) \u2192 localhost:${decl.port}`);\n } else if (mode === 'remote') {\n console.log(` external ${name.padEnd(18)} remote \u2014 actual service credentials (no local process)`);\n }\n }\n return;\n }\n\n // Auto-provision the app tenant's auth config (approved Zitadel\n // tenant-auth pattern: org per tenant \u2192 project per app \u2192 application\n // per service + credential secret). Best-effort: the dev loop still\n // works if Zitadel isn't seeded yet.\n try {\n const tenant = localTenant;\n const app = rawDevOutput.app ?? projectName;\n logInfo(`Provisioning auth config for tenant '${tenant}', app '${app}'\u2026`);\n const services = Object.keys(rawDevOutput.services);\n // Mocks are stand-ins, not services of the app \u2014 no Zitadel\n // application for them (the registry still lists them for the Hub).\n const authServices = services.filter((name) => !name.startsWith('mock-'));\n // App-declared project roles (package.json \u2192 mesh.auth.roles): created\n // on the project and granted to the local `{app}-m2m` caller, so\n // role-scoped services (roles claim \u2192 scopes) accept its tokens.\n let authRoles: string[] = [];\n try {\n const appPkg = JSON.parse(\n fs.readFileSync(path.join(appRoot, 'package.json'), 'utf-8'),\n );\n if (Array.isArray(appPkg?.mesh?.auth?.roles)) {\n authRoles = appPkg.mesh.auth.roles.filter((r: unknown) => typeof r === 'string');\n }\n } catch {\n // no package.json / unparsable \u2014 roles stay empty\n }\n await ensureAppTenantAuth({ tenant, app, services: authServices, roles: authRoles });\n // The app's own Temporal namespace ({tenant}-{env}-{app}) \u2014 the same\n // name the cloud provisioner creates and the Hub's per-app workflow\n // view resolves.\n await ensureTemporalNamespace(localAppNamespace(tenant, app));\n } catch (err) {\n logWarn(\n `Auth auto-provisioning skipped: ${err instanceof Error ? err.message : err}` +\n ` \u2014 if the local Zitadel predates seeding, run: mesh stop --destroy && mesh start`,\n );\n }\n\n const devOutput = await allocatePorts(rawDevOutput, worktree);\n\n // Register AFTER allocatePorts: the registry must carry the ports the\n // services actually listen on, or StackPort/Hub (and anything reading\n // /mesh-platform/\u2026/stacks/local) points at dead URLs.\n try {\n await registerLocalApp({\n tenant: localTenant,\n app: devOutput.app ?? projectName,\n services: Object.keys(devOutput.services),\n ports: Object.fromEntries(\n Object.entries(devOutput.services).map(([name, svc]) => [name, svc.port]),\n ),\n // ExternalService.link() parity: consuming services carry the\n // external names, so the Hub shows consumers + per-app uptime.\n links: Object.values(selectedMocks)\n .map((decl) => decl.external)\n .filter((n): n is string => !!n),\n });\n } catch (err) {\n logWarn(`Local registry registration skipped: ${err instanceof Error ? err.message : err}`);\n }\n\n // Wire realizations AFTER ports are final: realize each declaration\n // by mode, then seed the external's credential secret and register it\n // in the Hub \u2014 the app's resolveCredentials() path runs unchanged.\n // mock \u2192 mock-{name} service URL (Prism / mock process)\n // local \u2192 docker compose up -d --wait, endpoint from decl.port\n // remote \u2192 actual-service credentials seeded (inline, or pulled\n // from the app's tenant environment)\n const composeExternals: ComposeExternalRef[] = [];\n const externalProbeFiles: string[] = [];\n for (const [name, decl] of Object.entries(selectedMocks)) {\n const mode = externalMode(name, decl);\n try {\n let probeFile: string | undefined;\n if (mode === 'local') {\n logInfo(`Starting docker external '${name}' (${decl.compose})\u2026`);\n // undefined = adopted a realization another checkout owns \u2014\n // not recorded, so --kill leaves it running.\n const composeRef = await composeExternalUp(appRoot, sessionName, name, decl);\n if (composeRef) composeExternals.push(composeRef);\n probeFile = await seedLocalMock({\n tenant: localTenant,\n app: devOutput.app ?? projectName,\n name,\n decl,\n endpoint: { url: `http://localhost:${decl.port}`, host: 'localhost', port: decl.port! },\n });\n } else if (mode === 'remote') {\n probeFile = await seedLocalMock({\n tenant: localTenant,\n app: devOutput.app ?? projectName,\n name,\n decl,\n });\n } else {\n const mockService = devOutput.services[`mock-${name}`];\n if (!mockService) continue;\n probeFile = await seedLocalMock({\n tenant: localTenant,\n app: devOutput.app ?? projectName,\n name,\n decl,\n endpoint: {\n url: `http://localhost:${mockService.port}`,\n host: 'localhost',\n port: mockService.port,\n },\n });\n }\n if (probeFile) externalProbeFiles.push(probeFile);\n } catch (err) {\n // A remote external the developer didn't name costs only itself:\n // the bare `--externals` selects everything declared, and a\n // machine with no AWS identity (or no vendor key in the shell)\n // must still get its mock and local externals \u2014 that's the\n // zero-access local loop. Naming it keeps the failure fatal.\n if (mode === 'remote' && !requestedExplicitly.has(name) && err instanceof MeshCliError) {\n logWarn(\n `External '${name}': skipped \u2014 ${err.message}` +\n ` (re-run with \\`mesh dev --externals ${name}=remote\\` to make this fatal).`,\n );\n continue;\n }\n if (err instanceof MeshCliError) throw err; // bad decl / missing env var / failed remote pull \u2014 hard stop\n if (mode === 'local') {\n // The app's services depend on this external \u2014 starting them\n // against a dead dependency helps nobody.\n throw new MeshCliError(\n `Docker external '${name}' failed to start: ${err instanceof Error ? err.message : err}`,\n { remediation: { command: `docker compose -f ${decl.compose} up # debug it directly` } },\n );\n }\n logWarn(`External '${name}' credential seeding failed: ${err instanceof Error ? err.message : err}`);\n }\n }\n\n if (dockerRunner) {\n // C2: render the same DevOutput as a docker compose project.\n const composePath = writeDevCompose(\n sessionName,\n appRoot,\n devOutput.services as Record<string, { src: string; port: number; command: string[]; env?: Record<string, { value: string }> }>,\n );\n logInfo(`Docker runner: ${composePath}`);\n dockerDevUp(sessionName);\n saveSessionState(sessionName, {\n appRoot,\n stack: 'local',\n devOutput,\n startedAt: new Date().toISOString(),\n runner: 'docker',\n composeExternals,\n externalProbeFiles,\n });\n console.log('');\n logSuccess(`Dev session started (docker): ${sessionName}`);\n console.log('');\n console.log('Services:');\n for (const [name, service] of Object.entries(devOutput.services)) {\n console.log(` ${name.padEnd(20)} http://localhost:${service.port}`);\n }\n console.log('');\n console.log(`Status with: mesh dev --status --session '${sessionName}'`);\n console.log('Stop with: mesh dev --kill');\n return;\n }\n\n const finalDevOutput = await startServices(\n sessionName,\n appRoot,\n devOutput,\n !!options.headless,\n localAwsEnv(), // ministack wiring \u2014 the only \"AWS\" children need\n { transport: 'vpn-direct' }, // local mode: no tunnels\n );\n saveSessionState(sessionName, {\n appRoot,\n stack: 'local',\n devOutput: finalDevOutput,\n startedAt: new Date().toISOString(),\n runner: 'tmux',\n composeExternals,\n externalProbeFiles,\n });\n return;\n }\n\n if (options.mock || options.externals) {\n logWarn(\n '--externals/--mock is local-mode only for now (tethered dev outputs do not carry external declarations yet \u2014 MESH-1885). Continuing without them.',\n );\n }\n\n const stack = detectStack(appRoot, resolveStackOption(options));\n logInfo(`Project: ${projectName}, Stack: ${stack}`);\n\n // Detect if the user accidentally ran `mesh dev` from the monorepo root\n // instead of an app directory. The monorepo root has a Pulumi.yaml but\n // no services/apps to run. Standalone apps (create-app scaffolds) ARE\n // their own workspace root \u2014 an api/ or worker/ package right here means\n // this is an app, not a monorepo root.\n const monorepoRoot = findMonorepoRoot();\n const looksLikeStandaloneApp = ['api', 'worker', 'web'].some((dir) =>\n fs.existsSync(path.join(appRoot, dir, 'package.json')),\n );\n if (monorepoRoot && path.resolve(appRoot) === path.resolve(monorepoRoot) && !looksLikeStandaloneApp) {\n logError(`mesh dev should be run from an app directory, not the monorepo root.\\n`);\n logInfo('Try:');\n logInfo(' cd apps/hub && mesh dev');\n logInfo('');\n logInfo('Or specify the app path:');\n logInfo(' mesh dev --app apps/hub');\n logInfo('');\n logInfo('List available apps:');\n logInfo(' mesh dev list');\n process.exit(1);\n }\n\n // \u2500\u2500 Prerequisite checks \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Check all prerequisites upfront so the user gets one clear list of\n // what needs fixing, rather than failing one step at a time.\n const issues: string[] = [];\n const profileHint = options.profile ?? process.env.AWS_PROFILE ?? 'mesh-dev';\n\n // AWS role + credential resolution.\n // The stack can declare two role ARNs:\n // - `mesh:deployerRole` \u2014 the default per-tenant deployer\n // - `mesh:adminDeployerRole` \u2014 optional admin variant assumed when the\n // caller's Zitadel JWT carries an admin-tier role (e.g.\n // `mesh.platform:admin`). selectRoleForCaller picks between them.\n // tmux + credential validation/diagnosis is handled below by the shared\n // doctor preflight so `mesh dev` and `mesh dev doctor` agree.\n const platformContext = derivePlatformContext(appRoot, stack);\n const defaultDeployerRole = readStackConfig(appRoot, stack, 'mesh:deployerRole');\n const adminDeployerRole = readStackConfig(appRoot, stack, 'mesh:adminDeployerRole');\n let deployerRole: string | null = defaultDeployerRole;\n if (defaultDeployerRole) {\n const meshCreds = platformContext ? readCredentials(platformContext) : null;\n const idToken = meshCreds && new Date(meshCreds.expiresAt) > new Date() ? meshCreds.idToken : null;\n deployerRole = selectRoleForCaller(idToken, {\n defaultRole: defaultDeployerRole,\n adminRole: adminDeployerRole ?? undefined,\n });\n if (adminDeployerRole && deployerRole === adminDeployerRole) {\n logInfo(`Caller has admin Zitadel role \u2014 assuming ${deployerRole.split('/').pop()} (admin variant)`);\n }\n }\n let awsEnv: Record<string, string>;\n let credMethod: ResolvedAwsCreds['method'] | 'ambient' = 'ambient';\n // Method fed to the doctor context: the resolved method on success, or\n // `null` on a failed resolution so the `creds` check probes for the exact\n // reason (no-session / expired / assume-denied / stale-env-override).\n let credMethodForDoctor: ResolvedAwsCreds['method'] | 'ambient' | null = 'ambient';\n if (deployerRole) {\n const resolved = await resolveAwsCredentials(deployerRole, appRoot, stack);\n if (!resolved) {\n awsEnv = {};\n credMethodForDoctor = null;\n } else {\n awsEnv = resolved.env;\n credMethod = resolved.method;\n credMethodForDoctor = resolved.method;\n }\n } else {\n awsEnv = getAwsEnvVars();\n credMethodForDoctor = 'ambient';\n }\n\n // 3. VPN or SSM fallback\n const vpnConnected = await isVpnConnected();\n // `let`: the auto-selected `vpn-direct` may be downgraded to `ssm` below by a\n // reachability probe once devOutput's Temporal endpoint is known (MESH-2016).\n let transport = resolveTransport(options.transport, {\n vpnConnected,\n hasSsmPlugin: hasSessionManagerPlugin(),\n tailscaleAvailable: tailscaleAvailable(),\n });\n if (options.transport === 'tailscale' && !tailscaleAvailable()) {\n issues.push(\n ' \\u2718 --transport=tailscale but the tailscaled binary is missing.\\n' +\n ' Fix: brew install tailscale',\n );\n }\n if (transport === 'ssm') {\n if (hasSessionManagerPlugin()) {\n if (!vpnConnected) {\n logWarn('VPN not connected \\u2014 will use SSM port-forwarding tunnels for VPC resources.');\n }\n logInfo(\n ' Tunnels use the 2XXXX port range (e.g., PostgreSQL on 25432, Temporal on 27233).',\n );\n logInfo(' Limitations: no kubectl exec into pods, no internal ingress/ALB access.');\n logInfo(' For full VPC access, connect VPN: mesh vpn connect');\n } else {\n issues.push(\n ' \\u2718 VPN is not connected and session-manager-plugin is not installed.\\n' +\n ' Option 1 (VPN): mesh vpn connect\\n' +\n ' Option 2 (SSM): brew install --cask session-manager-plugin\\n' +\n ' Option 3 (Tailscale): mesh dev --transport=tailscale',\n );\n }\n } else if (transport === 'tailscale') {\n // The daemon bring-up + join happen in startServices; announce success there,\n // not here \u2014 otherwise a fallback to SSM still reads as \"using Tailscale\"\n // (MESH-2098). A pending node registration prints its own URL during the join.\n logInfo('Bringing up userspace-Tailscale tunnels for VPC resources (shared per tenant)\u2026');\n }\n\n // Shared doctor preflight: the same checks as `mesh dev doctor`, so launch\n // and on-demand diagnosis name failures identically. Errors block launch;\n // warnings (config/worktree) print and proceed.\n const preflightCtx: DoctorContext = {\n appRoot,\n stack,\n sessionName,\n deployerRole,\n platformContext,\n credMethod: credMethodForDoctor,\n sessionState: null,\n };\n const preflight = await runChecks(preflightCtx, 'preflight', ALL_CHECKS);\n const preflightReport = renderHuman(preflight);\n if (preflightReport) console.log(preflightReport);\n const preflightStatus = aggregateStatus(preflight.map((r) => r.result));\n if (preflightStatus === 'error' || issues.length > 0) {\n logError('\\nPrerequisites not met. Fix the above before running mesh dev, then retry: mesh dev');\n for (const issue of issues) console.log(issue);\n process.exit(1);\n }\n\n // \u2500\u2500 Credentials resolved, inject into environment \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Ensure AWS_REGION is set from the Pulumi stack config. Without this, AWS\n // SDK clients (SSM, Secrets Manager) would default to us-east-1.\n const awsRegion = readStackConfig(appRoot, stack, 'aws:region');\n if (awsRegion && !awsEnv.AWS_REGION) {\n awsEnv.AWS_REGION = awsRegion;\n }\n Object.assign(process.env, awsEnv);\n\n // Build the env that long-lived child services (ui, api, ai-assistant) and\n // SSM tunnels will see. When credentials came from AWS SSO, prefer passing\n // AWS_PROFILE + AWS_REGION so the AWS SDK v3 default provider chain can\n // auto-refresh from the SSO cache (~8h session) as short-lived STS tokens\n // expire. Without this, the hub API starts throwing ExpiredTokenException\n // about an hour in and tenants disappear from the UI. For non-SSO paths\n // (Zitadel JWT, CI/CD env keys) there is no profile to fall back to, so\n // pass the STS keys directly and accept that the user must restart\n // `mesh dev` when they expire.\n // For the Zitadel deployer path, hand children a self-refreshing\n // credential_process profile (context + role from the resolution above,\n // written into this session's scratch dir) instead of a frozen STS triple.\n const zitadelOpts =\n credMethod === 'zitadel' && deployerRole\n ? (() => {\n const context = derivePlatformContext(appRoot, stack);\n return context\n ? {\n context,\n roleArn: deployerRole,\n sessionScratchDir: getSessionEnvDir(sessionName),\n meshBin: resolveStableMeshBin(process.argv[1]),\n }\n : undefined;\n })()\n : undefined;\n const childAwsEnv = buildChildAwsEnv(awsEnv, credMethod, profileHint, zitadelOpts);\n\n let rawDevOutput: DevOutput;\n try {\n rawDevOutput = getDevOutput(appRoot, stack, awsEnv);\n } catch (err) {\n if (err instanceof MissingStackOutputError) {\n // Only the launch path can conclude \"nothing to run\" \u2014 print the\n // forward-chaining first-run fix and exit cleanly (MESH-2097). The\n // suggested commands carry --stack because the bare forms error right\n // after `stack init` (matching stack.ts's next-step output).\n logError(`No Pulumi stack output for '${stack}' \u2014 mesh dev has nothing to run.`);\n logInfo('If this is a new app, initialize and materialize it first:');\n logInfo(' mesh stack init # create your personal dev stack');\n logInfo(` mesh deploy up --stack ${stack} --yes # produce the app output mesh dev reads`);\n logInfo(`Then: mesh dev --stage ${stack} (the stack must export an \\`app\\` or \\`dev\\` output.)`);\n logInfo('No deployed stack yet? Run against the local platform: mesh dev --local (needs `mesh start`).');\n // Surface the underlying read error so an auth/network/JSON failure isn't\n // silently misdiagnosed as \"fresh app\" with zero forensics.\n const cause = (err.cause as Error | undefined)?.message;\n if (cause) logInfo(`(underlying stack-read error: ${cause})`);\n process.exit(1);\n }\n throw err;\n }\n\n // --status \u2014 use persisted state (has allocated ports), fall back to raw\n if (options.status) {\n const state = loadSessionState(sessionName);\n await showStatus(sessionName, state?.devOutput ?? rawDevOutput, !!options.json);\n return;\n }\n\n // Allocate dynamic ports (avoid collisions with other running apps).\n // devOutput is passed by value and may be rewritten inside startServices\n // if SSM tunnels are used (to point tunnels at localhost:2XXXX).\n const devOutput = await allocatePorts(rawDevOutput, worktree);\n\n // Reachability gate (MESH-2016): the transport chosen above used a PRESENCE\n // check (isVpnConnected \u2192 \"is any Tailscale/VPN up\"), which is tailnet-blind \u2014\n // Tailscale-for-SSH looks connected but doesn't route the mesh VPC. Now that\n // devOutput is known, probe the real Temporal VPC endpoint and downgrade an\n // auto-selected vpn-direct to SSM when it's unreachable.\n transport = await gateVpnDirectReachability(transport, devOutput);\n\n // --dry-run: show the resolved worktree/session/port plan, launch nothing.\n if (options.dryRun) {\n printDevPlan(sessionName, appRoot, worktree, devOutput);\n return;\n }\n\n // Build the tunnel plan for the chosen transport. For Tailscale, resolve the\n // shared per-tenant daemon context (tenant = hub platform name, since the\n // bastion is a hub resource); reuse the daemon's SOCKS port if it's already up.\n let tunnelPlan: TunnelPlan = { transport };\n if (transport === 'tailscale') {\n const tsTenant = devOutput.platform?.name ?? 'mesh';\n const tsEnv = devOutput.platform?.env ?? 'dev';\n const tsContext = derivePlatformContext(appRoot, stack) ?? `${tsTenant}.${tsEnv}`;\n const loginServer = deriveLoginServer(tsContext);\n if (!loginServer) {\n // Implicit selection (auto/unset) must degrade to the legacy transport,\n // not dead-end. Only an explicit --transport=tailscale may hard-error.\n const msg = `No login config for context '${tsContext}' \u2014 run: mesh login ${tsContext}`;\n if (options.transport === 'tailscale') {\n logError(msg);\n process.exit(1);\n }\n const legacy: Transport = vpnConnected\n ? 'vpn-direct'\n : hasSessionManagerPlugin()\n ? 'ssm'\n : 'vpn-direct';\n // Reachability-gate this legacy fallback too (MESH-2016): otherwise a\n // machine with tailscaled (\u2192 auto picks tailscale) but no mesh login\n // config, with any tailnet up (vpnConnected), would land on an UNPROBED\n // vpn-direct and reproduce the exact ECONNREFUSED this feature fixes.\n const gatedLegacy = await gateVpnDirectReachability(legacy, devOutput);\n logWarn(`${msg} \u2014 falling back to ${gatedLegacy} transport.`);\n tunnelPlan = { transport: gatedLegacy };\n } else {\n const prior = readTailscaleState(tsTenant);\n const daemonUp = tailscaleDaemonState(tsTenant).backendState !== 'Down';\n // Reuse the running daemon's real SOCKS port (daemon.json survives\n // `down`); never mint a fresh one the daemon isn't listening on.\n const socksPort = daemonUp\n ? (readTailscaleDaemonMeta(tsTenant)?.socksPort ?? prior?.socksPort ?? (await findFreePort()))\n : await findFreePort();\n // Zero-touch VPN join (MESH-2099): try to mint a single-use pre-auth key\n // from the platform's VpnJoinBroker so `tailscale up --authkey` joins\n // silently. Any failure leaves preAuthKey undefined \u2192 the interactive\n // browser-relay join (MESH-2098) is used instead.\n let preAuthKey: string | undefined;\n const brokerUrl = resolveVpnJoinBroker(tsContext);\n if (brokerUrl) {\n const minted = await mintPreAuthKey(tsContext, brokerUrl, { getValidToken });\n if (minted?.authKey) {\n preAuthKey = minted.authKey;\n } else {\n logInfo('zero-touch VPN join unavailable, falling back to browser registration');\n }\n }\n tunnelPlan = {\n transport,\n explicit: options.transport === 'tailscale',\n tailscale: {\n tenant: tsTenant,\n env: tsEnv,\n region: awsRegion ?? 'us-east-2',\n loginServer,\n socksPort,\n preAuthKey,\n },\n };\n }\n }\n\n // Relaunch safety (MESH-2017): a relaunch recreates the worker onto current\n // code. If the workflow source changed since this session started, warn before\n // it replays in-flight conversations against it (require --force). Checked\n // BEFORE startServices, which kills+recreates the session.\n if (workflowChangeWouldStrand(loadSessionState(sessionName), appRoot, !!options.force)) {\n process.exit(1);\n }\n\n // Start services. startServices handles tmux session creation, tunnel setup\n // (SSM or Tailscale, per tunnelPlan), and service windows. It returns the\n // final devOutput with tunnels rewritten to localhost ports.\n const finalDevOutput = await startServices(\n sessionName,\n appRoot,\n devOutput,\n !!options.headless,\n childAwsEnv,\n tunnelPlan,\n worktree.worktreeRoot,\n worktree.taskQueueSuffix,\n );\n\n // Persist session state so --status and restart see allocated ports\n // and the final tunnel endpoints (localhost for SSM, VPC for VPN).\n saveSessionState(sessionName, {\n appRoot,\n stack,\n devOutput: finalDevOutput,\n startedAt: new Date().toISOString(),\n workflowFingerprint: fingerprintWorkflowSource(appRoot, finalDevOutput.services),\n });\n });\n\n // Subcommand: logs\n dev\n .command('logs <service>')\n .description('Show logs for a service')\n .option('--tail <lines>', 'Number of lines', '100')\n .action((service: string, opts: { tail: string }) => {\n // --session is on the parent dev command\n const sessionName = dev.opts().session as string | undefined;\n const resolvedSession = sessionName ?? `${getProjectName(findAppRoot())}-dev`;\n if (loadSessionState(resolvedSession)?.runner === 'docker') {\n console.log(dockerDevLogs(resolvedSession, service, parseInt(opts.tail, 10)));\n return;\n }\n if (sessionName) {\n showLogs(sessionName, service, parseInt(opts.tail, 10));\n } else {\n const appRoot = findAppRoot();\n const projectName = getProjectName(appRoot);\n showLogs(`${projectName}-dev`, service, parseInt(opts.tail, 10));\n }\n });\n\n // Subcommand: restart\n dev\n .command('restart <service>')\n .description('Restart a service')\n .option('--stack <stack>', 'Pulumi stack name')\n .addOption(new Option('--stage <stack>', 'Deprecated alias for --stack').hideHelp())\n .option(\n '--refresh-env',\n \"Regenerate this service's env from current stack/SSM outputs before restarting (for config/deploy changes)\",\n )\n .option('--force', 'Restart the worker even if workflow code changed since launch (may strand in-flight conversations)')\n .action(async (service: string, opts: { stage?: string; refreshEnv?: boolean; force?: boolean }) => {\n // Hoisted so the catch can name the right login context (not a hardcoded\n // one) even when a throw happens before cred resolution. MESH-2089.\n let ctx: string | null = null;\n try {\n // --session is on the parent dev command\n const parentSession = dev.opts().session as string | undefined;\n const parentProfile = dev.opts().profile as string | undefined;\n if (parentProfile) {\n applyAwsProfileOverride(parentProfile);\n }\n const appRoot = findAppRoot();\n const projectName = getProjectName(appRoot);\n const sessionName = parentSession ?? `${projectName}-dev`;\n const state = loadSessionState(sessionName);\n if (state?.runner === 'docker') {\n dockerDevRestart(sessionName, service);\n logSuccess(`Restarted: ${service}`);\n return;\n }\n // Relaunch safety (MESH-2017): restarting the WORKER onto changed workflow\n // code strands in-flight conversations; restarting other services (ui/api)\n // doesn't. Gate the worker restart on the workflow-source fingerprint.\n if (/worker/i.test(service) && workflowChangeWouldStrand(state, appRoot, !!opts.force)) {\n process.exit(1);\n }\n const stack = state?.stack ?? detectStack(appRoot, resolveStackOption(opts));\n ctx = derivePlatformContext(appRoot, stack);\n // Resolve credentials BEFORE reading any Pulumi/SSM/kubeconfig output\n // (MESH-2090). With ambient AWS_* cleared (the documented restart\n // hygiene), the parent-side AWS calls the restart path makes \u2014 the\n // getDevOutput fallback below, and under --refresh-env the\n // resolveTemporalAuthVars/ensureKubeconfig calls \u2014 read the default SDK\n // chain (process.env). Resolving first lets us thread the resolved creds\n // into this process's env, and lets the precise login preflight fire\n // before the devOutput fallback (which was the MESH-2089 crash site).\n const defaultDeployerRole = readStackConfig(appRoot, stack, 'mesh:deployerRole');\n const adminDeployerRole = readStackConfig(appRoot, stack, 'mesh:adminDeployerRole');\n let deployerRole = defaultDeployerRole;\n if (defaultDeployerRole) {\n const meshCreds = ctx ? readCredentials(ctx) : null;\n const idToken = meshCreds && new Date(meshCreds.expiresAt) > new Date() ? meshCreds.idToken : null;\n deployerRole = selectRoleForCaller(idToken, {\n defaultRole: defaultDeployerRole,\n adminRole: adminDeployerRole ?? undefined,\n });\n }\n const resolved = deployerRole ? await resolveAwsCredentials(deployerRole, appRoot, stack) : null;\n // Login preflight (MESH-2089): if a deployer role is configured but creds\n // couldn't be resolved AND there are no ambient AWS creds to fall back on,\n // the restart would proceed with no credentials and fail downstream. Name\n // the real problem (e.g. \"run mesh login <ctx> --device\") instead.\n if (deployerRole && !resolved && !process.env.AWS_ACCESS_KEY_ID) {\n const pf = ctx ? credProbeToPreflightError(await probeCredentials(ctx, deployerRole), ctx) : null;\n logError(\n pf?.message ??\n `Couldn't resolve AWS credentials to restart '${service}'. Run: mesh login ${ctx ?? 'mesh.dev'} --device`,\n );\n process.exit(1);\n }\n const baseAwsEnv = resolved?.env ?? getAwsEnvVars();\n // Ensure AWS_REGION is set from stack config so parent-side SDK clients\n // (SSM, EKS) don't default to us-east-1. Mirrors the launch path.\n const awsRegion = readStackConfig(appRoot, stack, 'aws:region');\n if (awsRegion && !baseAwsEnv.AWS_REGION) {\n baseAwsEnv.AWS_REGION = awsRegion;\n }\n // Inject the resolved creds into THIS process's env so the parent-side\n // AWS calls below run credentialed even when ambient AWS_* was cleared\n // (MESH-2090). Mirrors the launch path's inject (see startServices).\n Object.assign(process.env, baseAwsEnv);\n const profileHint = parentProfile ?? process.env.AWS_PROFILE ?? 'mesh-dev';\n const zitadelOpts =\n resolved?.method === 'zitadel' && deployerRole && ctx\n ? {\n context: ctx,\n roleArn: deployerRole,\n sessionScratchDir: getSessionEnvDir(sessionName),\n meshBin: resolveStableMeshBin(process.argv[1]),\n }\n : undefined;\n const awsEnv = buildChildAwsEnv(baseAwsEnv, resolved?.method ?? 'ambient', profileHint, zitadelOpts);\n // Use persisted state (has allocated ports), fall back to raw Pulumi\n // output \u2014 now credentialed via the resolved env (MESH-2090).\n const devOutput = state?.devOutput ?? getDevOutput(appRoot, stack, baseAwsEnv);\n await restartService(sessionName, service, appRoot, devOutput, awsEnv, {\n refreshEnv: !!opts.refreshEnv,\n stack,\n sessionState: state,\n });\n // Re-baseline the workflow fingerprint after a worker restart (MESH-2017):\n // the worker now runs the current code, so a subsequent unchanged restart\n // must NOT nag \u2014 otherwise a good-citizen `--force` earns a session of\n // false warnings, training the reflex this guard exists to prevent.\n if (/worker/i.test(service) && state) {\n saveSessionState(sessionName, {\n ...state,\n workflowFingerprint: fingerprintWorkflowSource(appRoot, state.devOutput?.services),\n });\n }\n } catch (err) {\n // Never crash uncaught (MESH-2089): a cred/kubeconfig/tmux failure should\n // name itself, not dump a bare Node stack. The underlying error is logged\n // so the exact cause is pinned if this recurs.\n logError(`Failed to restart '${service}': ${(err as Error)?.message ?? String(err)}`);\n logInfo(\n `If this is a credential/kubeconfig issue, run \\`mesh login ${ctx ?? '<your platform context>'} --device\\`, ` +\n 'or `mesh dev` to relaunch the session cleanly.',\n );\n process.exit(1);\n }\n });\n\n // Subcommand: doctor \u2014 diagnose the dev session\n dev\n .command('doctor')\n .description(\n 'Diagnose the dev session (creds, tunnels, config, ports, worktree, Temporal) \u2014 names the fix',\n )\n .option('--stack <stack>', 'Pulumi stack name')\n .addOption(new Option('--stage <stack>', 'Deprecated alias for --stack').hideHelp())\n .option('--json', 'Machine-readable output')\n .action(async (opts: { stack?: string; stage?: string; json?: boolean }) => {\n const parentProfile = dev.opts().profile as string | undefined;\n if (parentProfile) {\n applyAwsProfileOverride(parentProfile);\n }\n const appRoot = findAppRoot();\n const projectName = getProjectName(appRoot);\n const sessionName = (dev.opts().session as string | undefined) ?? `${projectName}-dev`;\n const state = loadSessionState(sessionName);\n const stack = state?.stack ?? detectStack(appRoot, resolveStackOption(opts));\n // `--json` may land on either the subcommand or the parent `dev`\n // command (both declare it), so honor both.\n const asJson = !!opts.json || !!(dev.opts().json as boolean | undefined);\n const ctx = buildDoctorContext(appRoot, stack, sessionName);\n const status = await runDoctor(ctx, { json: asJson });\n process.exit(status === 'error' ? 1 : 0);\n });\n\n // Subcommand: list \u2014 discover apps in the monorepo\n dev\n .command('list')\n .description('List Pulumi apps in the monorepo')\n .action(() => {\n // --json is on the parent dev command\n const asJson = dev.opts().json;\n const mono = findMonorepoRoot();\n if (!mono) {\n logError('Could not find monorepo root (pnpm-workspace.yaml or .git)');\n process.exit(1);\n }\n\n const apps = discoverApps(mono);\n\n if (asJson) {\n // Include running state for each app\n const result = apps.map((app) => {\n const sessionName = `${app.name}-dev`;\n return {\n ...app,\n running: sessionExists(sessionName),\n session: sessionName,\n };\n });\n console.log(JSON.stringify(result, null, 2));\n } else {\n if (apps.length === 0) {\n logInfo('No Pulumi apps found.');\n return;\n }\n console.log('Apps in monorepo:');\n console.log('');\n for (const app of apps) {\n const sessionName = `${app.name}-dev`;\n const running = sessionExists(sessionName);\n const icon = running ? '\u25CF' : '\u25CB';\n const stacks = app.stacks.length > 0 ? ` (${app.stacks.join(', ')})` : '';\n console.log(\n ` ${icon} ${app.name.padEnd(24)} ${app.tenant.padEnd(12)} ${app.relativePath}${stacks}`,\n );\n }\n console.log('');\n }\n });\n\n // Subcommand: test-user \u2014 retrieve Temporal test user credentials\n dev\n .command('test-user [name]')\n .description('Get Temporal test user credentials (from Pulumi-managed test users)')\n .option('--tenant <tenant>', 'Tenant name', 'mesh')\n .option('--env <env>', 'Environment', 'dev')\n .option('--region <region>', 'AWS region', 'us-east-2')\n .action(\n async (name: string | undefined, opts: { tenant: string; env: string; region: string }) => {\n const { SSMClient, GetParameterCommand, GetParametersByPathCommand } =\n await import('@aws-sdk/client-ssm');\n const ssm = new SSMClient({ region: opts.region });\n const basePath = `/mesh-platform/${opts.tenant}/${opts.env}/temporal/test-users`;\n\n if (!name) {\n // List all test users\n try {\n const resp = await ssm.send(\n new GetParametersByPathCommand({\n Path: basePath,\n Recursive: true,\n WithDecryption: true,\n }),\n );\n\n if (!resp.Parameters || resp.Parameters.length === 0) {\n logWarn(`No test users found at ${basePath}`);\n logInfo(\n 'Test users are defined in Pulumi config under mesh:temporal.authorization.testUsers',\n );\n logInfo(\"They're only available on dev stacks.\");\n return;\n }\n\n console.log('Temporal test users:');\n console.log('');\n for (const param of resp.Parameters) {\n const userName = param.Name!.split('/').pop()!;\n const creds = JSON.parse(param.Value!) as {\n email: string;\n password: string;\n roles: string[];\n description?: string;\n };\n console.log(` ${userName}`);\n console.log(` Email: ${creds.email}`);\n console.log(` Password: ${creds.password}`);\n console.log(` Roles: ${creds.roles.join(', ')}`);\n if (creds.description) console.log(` Note: ${creds.description}`);\n console.log('');\n }\n logInfo('Login at: https://temporal.dev.mesh-platform.trabian.com');\n } catch (err) {\n logError(\n `Failed to list test users: ${err instanceof Error ? err.message : String(err)}`,\n );\n process.exit(1);\n }\n } else {\n // Get a specific test user\n try {\n const resp = await ssm.send(\n new GetParameterCommand({\n Name: `${basePath}/${name}`,\n WithDecryption: true,\n }),\n );\n\n if (!resp.Parameter?.Value) {\n logError(`Test user '${name}' not found at ${basePath}/${name}`);\n return;\n }\n\n const creds = JSON.parse(resp.Parameter.Value) as {\n email: string;\n password: string;\n roles: string[];\n description?: string;\n };\n // Check if --json is set on parent\n const asJson = dev.opts().json;\n if (asJson) {\n console.log(JSON.stringify(creds, null, 2));\n } else {\n console.log(`Email: ${creds.email}`);\n console.log(`Password: ${creds.password}`);\n console.log(`Roles: ${creds.roles.join(', ')}`);\n if (creds.description) console.log(`Note: ${creds.description}`);\n console.log('');\n logInfo('Login at: https://temporal.dev.mesh-platform.trabian.com');\n }\n } catch (err: any) {\n const msg = err.message ?? String(err);\n if (msg.includes('ParameterNotFound') || err.name === 'ParameterNotFound') {\n logError(`Test user '${name}' not found.`);\n logInfo(`List available users with: mesh dev test-user`);\n } else {\n logError(`Failed to get test user: ${msg}`);\n }\n process.exit(1);\n }\n }\n },\n );\n}\n", "/**\n * Resolve a tenant's VPC tunnel targets from the platform bastion's service\n * map \u2014 the same source `startSsmTunnels` reads \u2014 mapping bastion service keys\n * to the app's tunnel names, resolving each ELB/RDS hostname to its private IP,\n * and assigning collision-free localhost ports via the SSM port convention.\n * (MESH-2040 / Slice 1 of MESH-2014.)\n */\n\nimport { execFileSync } from \"node:child_process\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { reserveSsmLocalPortCandidate, preferredSsmLocalPort } from \"../commands/dev.js\";\nimport { CONFIG_DIR, atomicWriteFileSync } from \"../commands/login.js\";\n\n/** Local-port block width per tenant \u2014 wider than the canonical port span so\n * two tenants' port blocks never overlap. */\nexport const PORT_BLOCK = 3000;\n\n/**\n * Deterministic per-tenant index for local-port offsetting. Reads a machine-global\n * registry (`~/.config/mesh/tailscale/port-registry.json`), seeded `{ mesh: 0 }` so\n * the hub's canonical ports are grandfathered regardless of registration order.\n * Assigns the next index to an unseen tenant and persists it. `registryPath` is\n * injectable for tests.\n */\nexport function tenantPortIndex(tenant: string, registryPath?: string): number {\n const p = registryPath ?? path.join(CONFIG_DIR, \"tailscale\", \"port-registry.json\");\n let reg: Record<string, number>;\n try {\n reg = JSON.parse(fs.readFileSync(p, \"utf8\")) as Record<string, number>;\n } catch {\n reg = { mesh: 0 };\n }\n if (tenant in reg) return reg[tenant]!;\n const idx = Math.max(-1, ...Object.values(reg)) + 1;\n reg[tenant] = idx;\n fs.mkdirSync(path.dirname(p), { recursive: true });\n atomicWriteFileSync(p, JSON.stringify(reg, null, 2), 0o600);\n return idx;\n}\n\nexport interface TunnelTarget {\n /** App-facing tunnel name (e.g. \"temporal\"). */\n name: string;\n /** Local port the forwarder listens on (SSM convention: base + remotePort). */\n localPort: number;\n /** VPC hostname (internal ELB / RDS endpoint). */\n targetHost: string;\n /** Resolved private IP of `targetHost`. */\n targetIp: string;\n /** Port on the VPC service. */\n remotePort: number;\n}\n\n/**\n * Bastion service key \u2192 app tunnel name. Mirrors `tunnelToBastionKey` in dev.ts\n * (inverted): the bastion exposes `temporal-frontend`; the app calls it `temporal`.\n */\nexport const TUNNEL_NAME_BY_BASTION_KEY: Record<string, string> = {\n \"temporal-frontend\": \"temporal\",\n \"temporal-ui\": \"temporal-ui\",\n rds: \"rds\",\n};\n\n/**\n * Build the tunnel target set. `resolveIp` is injected for testability (the\n * command passes `resolveElbIp`). Services not in the name map are skipped;\n * services whose host can't be resolved are skipped (the forwarder needs an IP).\n */\nexport function resolveTunnelTargets(\n services: Record<string, { host: string; port: number }>,\n resolveIp: (host: string) => string | null,\n portOffset = 0,\n): TunnelTarget[] {\n const reserved = new Set<number>();\n const targets: TunnelTarget[] = [];\n for (const [key, svc] of Object.entries(services)) {\n const name = TUNNEL_NAME_BY_BASTION_KEY[key];\n if (!name) continue;\n const targetIp = resolveIp(svc.host);\n if (!targetIp) continue;\n // Per-tenant offset keeps concurrent platform tenants off each other's ports.\n const localPort = reserveSsmLocalPortCandidate(\n svc.port,\n reserved,\n preferredSsmLocalPort(svc.port) + portOffset,\n );\n targets.push({ name, localPort, targetHost: svc.host, targetIp, remotePort: svc.port });\n }\n return targets;\n}\n\n/**\n * Resolve an AWS-internal ELB/RDS hostname to its private IP via a public\n * resolver \u2014 these names publish their private (10.x) address to public DNS\n * but the host's default resolver may not answer for them. Returns null on\n * failure (caller skips that tunnel).\n */\nexport function resolveElbIp(host: string): string | null {\n try {\n const out = execFileSync(\"dig\", [\"+short\", host, \"@1.1.1.1\"], {\n encoding: \"utf8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n });\n const ip = out\n .trim()\n .split(\"\\n\")\n .map((l) => l.trim())\n .find((l) => /^\\d+\\.\\d+\\.\\d+\\.\\d+$/.test(l));\n return ip ?? null;\n } catch {\n return null;\n }\n}\n", "/**\n * A minimal SOCKS5 CONNECT forwarder: listens on a local TCP port and pipes\n * each client connection through a SOCKS5 proxy (no-auth) to a fixed target.\n *\n * Presents the same plain `localhost:PORT` contract the SSM tunnels give today,\n * so an app (e.g. a Temporal gRPC client) connects with no proxy awareness \u2014\n * the SOCKS5 proxy is the userspace-Tailscale daemon (MESH-2040 / MESH-2036).\n */\n\nimport * as net from \"node:net\";\n\n/** `\"10.0.137.203\"` \u2192 `[10,0,137,203]`; throws on anything that isn't IPv4. */\nexport function ipv4ToBytes(ip: string): number[] {\n const parts = ip.split(\".\");\n if (parts.length !== 4) throw new Error(`not an IPv4 address: ${ip}`);\n return parts.map((p) => {\n const n = Number(p);\n if (!Number.isInteger(n) || n < 0 || n > 255 || !/^\\d+$/.test(p)) {\n throw new Error(`not an IPv4 address: ${ip}`);\n }\n return n;\n });\n}\n\n/** SOCKS5 CONNECT request for an IPv4 target (VER, CMD=CONNECT, RSV, ATYP=IPv4, addr, port). */\nexport function socks5ConnectRequest(ip: string, port: number): Buffer {\n return Buffer.from([0x05, 0x01, 0x00, 0x01, ...ipv4ToBytes(ip), (port >> 8) & 0xff, port & 0xff]);\n}\n\nconst SOCKS_REPLY_MESSAGES: Record<number, string> = {\n 0: \"succeeded\",\n 1: \"general SOCKS server failure\",\n 2: \"connection not allowed by ruleset\",\n 3: \"network unreachable\",\n 4: \"host unreachable\",\n 5: \"connection refused\",\n 6: \"TTL expired\",\n 7: \"command not supported\",\n 8: \"address type not supported\",\n};\n\n/** Interpret the SOCKS5 reply code (byte 1 of the CONNECT reply). */\nexport function interpretSocksReply(code: number): { ok: boolean; message: string } {\n return { ok: code === 0, message: SOCKS_REPLY_MESSAGES[code] ?? `unknown SOCKS reply ${code}` };\n}\n\nexport interface ForwarderOptions {\n /** Local TCP port to listen on (0 = ephemeral, useful in tests). */\n listenPort: number;\n socksHost?: string;\n socksPort: number;\n targetIp: string;\n targetPort: number;\n /**\n * Observes server errors \u2014 above all a bind failure (`EADDRINUSE`). The\n * forwarder still never crashes the process, but the error must not be\n * INVISIBLE: an unbound forwarder whose port is held by a foreign process is\n * the silent-dead-tunnel class (MESH-2407), so callers record it and the\n * ownership handshake reports the port as not-listening.\n */\n onError?: (err: NodeJS.ErrnoException) => void;\n}\n\n/**\n * Create (and start) a forwarder server. Each inbound client is spliced to\n * `targetIp:targetPort` via a SOCKS5 CONNECT through `socksHost:socksPort`.\n */\nexport function createForwarder(opts: ForwarderOptions): net.Server {\n const socksHost = opts.socksHost ?? \"127.0.0.1\";\n const server = net.createServer((client) => {\n const up = net.connect(opts.socksPort, socksHost);\n let buf = Buffer.alloc(0);\n let phase = 0; // 0=await method-select, 1=await connect reply, 2=streaming\n up.on(\"connect\", () => up.write(Buffer.from([0x05, 0x01, 0x00]))); // greet, no-auth\n up.on(\"data\", (d) => {\n if (phase === 2) return;\n buf = Buffer.concat([buf, d]);\n if (phase === 0) {\n if (buf.length < 2) return;\n buf = buf.subarray(2);\n phase = 1;\n up.write(socks5ConnectRequest(opts.targetIp, opts.targetPort));\n }\n if (phase === 1) {\n if (buf.length < 10) return;\n const reply = interpretSocksReply(buf[1]!);\n const leftover = buf.subarray(10);\n phase = 2;\n if (!reply.ok) {\n up.destroy();\n client.destroy();\n return;\n }\n if (leftover.length) client.write(leftover);\n client.pipe(up);\n up.pipe(client);\n }\n });\n client.on(\"error\", () => up.destroy());\n up.on(\"error\", () => client.destroy());\n // A cleanly-closed client (clean FIN, no \"error\") must still tear down the\n // upstream SOCKS\u2192target leg \u2014 otherwise a probe that connects then closes\n // strands a real VPC-target connection until the target times out.\n client.on(\"close\", () => up.destroy());\n up.on(\"close\", () => client.destroy());\n });\n // A bind failure (e.g. the port is already held by an SSM tunnel) must not\n // crash the process running this forwarder \u2014 but it must be OBSERVED, not\n // swallowed: the runner records it and ownership checks fail the port.\n // Attach before listen() so the error is caught.\n server.on(\"error\", (err) => opts.onError?.(err));\n server.listen(opts.listenPort, \"127.0.0.1\");\n return server;\n}\n", "/**\n * Ownership contract for the tunnel runner (MESH-2407).\n *\n * Three silent-dead-tunnel incidents in ten days (MESH-2169, MESH-2014, the\n * #2991 re-review) shared one enabler: readiness was inferred from \"something\n * accepts TCP on the port\". That conflates LIVENESS (a listener exists) with\n * OWNERSHIP (the listener is OUR runner, wired to OUR SOCKS upstream). This\n * module is the ownership half of the contract:\n *\n * - The runner that actually binds the forwarder ports writes a MANIFEST\n * (pid, process-group id, a per-run random token, a loopback control port)\n * and answers a one-shot control handshake with that token plus the ports\n * it is listening on \u2014 read from its in-process `net.Server`s, so the\n * answer can't be faked by a foreign listener and probing it opens no\n * SOCKS\u2192VPC data connection.\n * - Callers verify ownership (manifest \u2192 live pid \u2192 control handshake \u2192\n * token/socks-port/port-coverage match) instead of dialing ports. A port\n * that accepts TCP without passing the handshake is a SQUATTER and must be\n * a loud failure, never adopt-and-continue.\n * - Teardown signals process GROUPS recorded here (plus argv-discovered\n * runners), so no kill path can orphan a grandchild with ports still bound.\n */\n\nimport * as crypto from 'node:crypto';\nimport * as fs from 'node:fs';\nimport * as net from 'node:net';\nimport * as path from 'node:path';\nimport { execFileSync } from 'node:child_process';\n\n/** Written by the runner (the process that binds the ports) \u2014 never by callers. */\nexport interface RunnerManifest {\n tenant: string;\n /** Pid of the runner process itself (the port owner), NOT its launcher. */\n pid: number;\n /** Process-group id \u2014 all teardown paths signal `-pgid`, never a bare pid. */\n pgid: number;\n /** Per-run random token; the control handshake must echo it. */\n token: string;\n /** Loopback port answering the one-shot ownership handshake. */\n controlPort: number;\n /** SOCKS port the runner's forwarders dial (must match the live daemon's). */\n socksPort: number;\n /** Forwarder ports the runner is responsible for. */\n ports: number[];\n startedAt: string;\n}\n\n/** What the runner's control endpoint answers with. */\nexport interface ControlResponse {\n token: string;\n tenant: string;\n pid: number;\n socksPort: number;\n /** Ports whose in-process `net.Server` is currently listening. */\n listening: number[];\n /** port \u2192 error code for forwarders that failed to bind (e.g. EADDRINUSE). */\n bindErrors: Record<string, string>;\n}\n\nexport function mintRunnerToken(): string {\n return crypto.randomBytes(16).toString('hex');\n}\n\nexport function readRunnerManifest(file: string): RunnerManifest | null {\n if (!fs.existsSync(file)) return null;\n try {\n return JSON.parse(fs.readFileSync(file, 'utf8')) as RunnerManifest;\n } catch {\n return null;\n }\n}\n\nexport function writeRunnerManifest(file: string, manifest: RunnerManifest): void {\n fs.mkdirSync(path.dirname(file), { recursive: true });\n fs.writeFileSync(file, JSON.stringify(manifest, null, 2), { mode: 0o600 });\n}\n\n/**\n * Remove the manifest \u2014 but only if it is still OURS (`token` matches). A dying\n * runner must not clobber the manifest of a newer runner that already replaced it.\n * Omit `token` for teardown paths that own the whole tenant state.\n */\nexport function clearRunnerManifest(file: string, token?: string): void {\n if (token !== undefined && readRunnerManifest(file)?.token !== token) return;\n try {\n fs.unlinkSync(file);\n } catch {\n /* already gone */\n }\n}\n\n/** Process-group id of a pid via `ps` (macOS/BSD); null when undiscoverable. */\nexport function getProcessGroupId(pid: number): number | null {\n try {\n const out = execFileSync('ps', ['-o', 'pgid=', '-p', String(pid)], {\n encoding: 'utf8',\n stdio: ['ignore', 'pipe', 'ignore'],\n }).trim();\n const pgid = Number(out);\n return Number.isInteger(pgid) && pgid > 0 ? pgid : null;\n } catch {\n return null;\n }\n}\n\n/**\n * Pids of tunnel-runner processes for a tenant, parsed from `ps` output\n * (`pid command` lines). Matches both `__run` and the legacy `__supervise`\n * argv, and skips `exclude` (the calling process, when it IS the runner).\n * Pure for unit tests; `discoverRunnerPids` feeds it live `ps` output.\n */\nexport function parseRunnerPidsFromPs(\n psOutput: string,\n tenant: string,\n exclude?: number,\n): number[] {\n const pids: number[] = [];\n for (const line of psOutput.split('\\n')) {\n if (!/vpn\\s+tunnel\\s+(?:__run|__supervise)\\s+/.test(line)) continue;\n const m = line.trim().match(/^(\\d+)\\s+(.*)$/);\n if (!m) continue;\n const argv = m[2]!.split(/\\s+/);\n // The tenant is the argument right after __run/__supervise \u2014 an exact\n // match, so tenant \"enc\" never matches a runner for tenant \"encore\".\n const i = argv.findIndex((a) => a === '__run' || a === '__supervise');\n if (i === -1 || argv[i + 1] !== tenant) continue;\n const pid = Number(m[1]);\n if (pid !== exclude) pids.push(pid);\n }\n return pids;\n}\n\n/** Live argv discovery of runner pids for a tenant (empty when `ps` fails). */\nexport function discoverRunnerPids(tenant: string, exclude?: number): number[] {\n try {\n const out = execFileSync('ps', ['ax', '-o', 'pid=,command='], {\n encoding: 'utf8',\n stdio: ['ignore', 'pipe', 'ignore'],\n });\n return parseRunnerPidsFromPs(out, tenant, exclude);\n } catch {\n return [];\n }\n}\n\n/**\n * Start the runner's one-shot control endpoint on a loopback ephemeral port.\n * Each connection gets one JSON line (the live payload) and is closed \u2014 no\n * protocol state, nothing routable, and probing it touches no data plane.\n */\nexport function startControlServer(\n payload: () => ControlResponse,\n): Promise<{ server: net.Server; port: number }> {\n return new Promise((resolve, reject) => {\n const server = net.createServer((socket) => {\n socket.on('error', () => {});\n try {\n socket.end(`${JSON.stringify(payload())}\\n`);\n } catch {\n socket.destroy();\n }\n });\n server.on('error', reject);\n server.listen(0, '127.0.0.1', () => {\n resolve({ server, port: (server.address() as net.AddressInfo).port });\n });\n });\n}\n\n/** Dial the control endpoint and parse its one-line JSON answer; null on any failure. */\nexport function queryControl(port: number, timeoutMs = 700): Promise<ControlResponse | null> {\n return new Promise((resolve) => {\n const s = new net.Socket();\n let buf = '';\n let done = false;\n const fin = (v: ControlResponse | null) => {\n if (done) return;\n done = true;\n s.destroy();\n resolve(v);\n };\n s.setTimeout(timeoutMs);\n s.once('timeout', () => fin(null));\n s.once('error', () => fin(null));\n s.on('data', (d) => {\n buf += d.toString();\n });\n s.once('close', () => {\n try {\n fin(JSON.parse(buf) as ControlResponse);\n } catch {\n fin(null);\n }\n });\n s.connect(port, '127.0.0.1');\n });\n}\n\nexport interface OwnershipCheck {\n ok: boolean;\n /** Machine-readable failure reason (\"\" when ok). */\n reason: string;\n /** The control answer, when the handshake got that far. */\n resp?: ControlResponse;\n}\n\nfunction defaultPidAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * The ownership handshake: manifest \u2192 live pid \u2192 control endpoint \u2192 token,\n * SOCKS port, and port coverage all match. Anything less is NOT ours \u2014 the\n * caller must treat an accepting-but-unowned port as a squatter, never reuse it.\n */\nexport async function verifyRunnerOwnership(args: {\n manifest: RunnerManifest | null;\n expectedSocksPort: number;\n expectedPorts: number[];\n isPidAlive?: (pid: number) => boolean;\n query?: (port: number) => Promise<ControlResponse | null>;\n}): Promise<OwnershipCheck> {\n const { manifest } = args;\n if (!manifest) return { ok: false, reason: 'no-manifest' };\n const alive = args.isPidAlive ?? defaultPidAlive;\n if (!alive(manifest.pid)) return { ok: false, reason: 'runner-dead' };\n const resp = await (args.query ?? queryControl)(manifest.controlPort);\n if (!resp) return { ok: false, reason: 'no-control-answer' };\n if (resp.token !== manifest.token) return { ok: false, reason: 'token-mismatch', resp };\n if (resp.socksPort !== args.expectedSocksPort) {\n return { ok: false, reason: 'socks-port-mismatch', resp };\n }\n const listening = new Set(resp.listening);\n const missing = args.expectedPorts.filter((p) => !listening.has(p));\n if (missing.length > 0) {\n return { ok: false, reason: `ports-not-listening:${missing.join(',')}`, resp };\n }\n return { ok: true, reason: '', resp };\n}\n\n/**\n * Poll an ownership check until it passes or `deadlineMs` of wall-clock elapses;\n * returns the last (failing) check otherwise. The deadline bounds TIME, not\n * rounds \u2014 each check can itself cost up to the control-query timeout, so a\n * round-counting loop would multiply the promised deadline several-fold.\n * Retrying also matters for correctness, not just latency: two failure reasons\n * are transient by design (`ports-not-listening:` while the runner's self-heal\n * loop rebinds a forwarder, `no-control-answer` under accept-backlog pressure),\n * and a single-shot sample of a healthy shared runner in one of those windows\n * would tear it down for every concurrent session on the tenant (MESH-2014).\n */\nexport async function pollOwnership(\n check: () => Promise<OwnershipCheck>,\n deadlineMs: number,\n): Promise<OwnershipCheck> {\n let last: OwnershipCheck = { ok: false, reason: 'not-checked' };\n const end = Date.now() + deadlineMs;\n do {\n last = await check();\n if (last.ok) return last;\n await new Promise((r) => setTimeout(r, 250));\n } while (Date.now() < end);\n return last;\n}\n\n/** Best-effort `lsof` description of what holds a port (\"cmd (pid N)\"); null if unknown. */\nexport function describePortOwner(port: number): string | null {\n try {\n const out = execFileSync('lsof', ['-nP', `-iTCP:${port}`, '-sTCP:LISTEN', '-Fcp'], {\n encoding: 'utf8',\n stdio: ['ignore', 'pipe', 'ignore'],\n });\n // -F output: \"p<pid>\\nc<command>\\n\u2026\" per process.\n const pid = out.match(/^p(\\d+)$/m)?.[1];\n const cmd = out.match(/^c(.+)$/m)?.[1];\n if (!pid && !cmd) return null;\n return `${cmd ?? '?'} (pid ${pid ?? '?'})`;\n } catch {\n return null;\n }\n}\n\nexport interface SquattedPort {\n port: number;\n owner: string | null;\n}\n\n/**\n * Of `ports`, the ones something is accepting TCP on. Called AFTER ownership\n * failed / teardown ran, so every hit is a foreign or stale listener.\n */\nexport async function findSquattedPorts(\n ports: number[],\n accepts: (port: number) => Promise<boolean>,\n): Promise<SquattedPort[]> {\n const squatted: SquattedPort[] = [];\n for (const port of ports) {\n if (await accepts(port)) squatted.push({ port, owner: describePortOwner(port) });\n }\n return squatted;\n}\n\n/**\n * The loud-failure text for a squatted tunnel port (`mesh dev doctor` style:\n * what is wrong, why we refuse, exactly what to run). Never adopt-and-continue.\n */\nexport function buildSquatterError(\n tenant: string,\n squatted: SquattedPort[],\n detail?: string,\n): string {\n const lines = squatted.map(\n (s) => ` 127.0.0.1:${s.port} held by ${s.owner ?? 'an unidentified process'}`,\n );\n const first = squatted[0]?.port ?? '<port>';\n return [\n `Tunnel port(s) for tenant '${tenant}' are bound by a process mesh does not own${detail ? ` (${detail})` : ''}:`,\n ...lines,\n ` Refusing to reuse a foreign listener \u2014 traffic would silently flow to the wrong upstream.`,\n ` To fix:`,\n ` mesh vpn -t ${tenant} tunnel down --stop # tear down mesh-owned runners + daemon`,\n ` lsof -nP -iTCP:${first} -sTCP:LISTEN # identify what still holds the port`,\n ` then stop that process and re-run.`,\n // Port blocks are a 63-bucket hash (MESH-2375), so a DIFFERENT tenant's\n // runner can collide onto this block \u2014 in which case the `down` above is a\n // no-op and only lsof identifies the real owner.\n ` (If lsof names another mesh runner, it belongs to a different tenant \u2014 tear that one down instead.)`,\n ].join('\\n');\n}\n", "/**\n * Userspace-Tailscale daemon management + tunnel-session state for\n * `mesh vpn tunnel` (MESH-2040 / Slice 1 of MESH-2014).\n *\n * A per-tenant `tailscaled` runs in userspace-networking mode (brew formula,\n * NOT the GUI app) exposing a SOCKS5 proxy; forwarders bridge `localhost:PORT`\n * to VPC services through it. State lives under `~/.config/mesh/tailscale/<tenant>/`\n * (r+w-granted under safehouse \u2014 see the MESH-2036 spike).\n */\n\nimport * as fs from \"node:fs\";\nimport * as net from \"node:net\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { spawn, execFileSync } from \"node:child_process\";\nimport { CONFIG_DIR, atomicWriteFileSync } from \"../commands/login.js\";\nimport { resolveStableMeshBin } from \"./aws-auth.js\";\nimport { logInfo, logWarn } from \"./log.js\";\nimport { MeshCliError, renderErrorBody } from \"./errors.js\";\nimport { assertSignalablePid } from \"./pid.js\";\nimport type { PidSource } from \"./pid.js\";\nimport { getPlatformBastionInfo } from \"./bastion.js\";\nimport { resolveTunnelTargets, resolveElbIp, tenantPortIndex, PORT_BLOCK } from \"./tailscale-targets.js\";\nimport { createForwarder } from \"./socks-forward.js\";\nimport {\n mintRunnerToken,\n readRunnerManifest,\n writeRunnerManifest,\n clearRunnerManifest,\n getProcessGroupId,\n discoverRunnerPids,\n startControlServer,\n verifyRunnerOwnership,\n pollOwnership,\n findSquattedPorts,\n buildSquatterError,\n} from \"./tunnel-ownership.js\";\nimport type { ControlResponse, OwnershipCheck } from \"./tunnel-ownership.js\";\nimport type { TunnelTarget } from \"./tailscale-targets.js\";\nimport type { DevOutput } from \"../commands/dev.js\";\n\nconst sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));\n\n// ============================================================================\n// Paths\n// ============================================================================\n\nexport function tenantStateDir(tenant: string): string {\n return path.join(CONFIG_DIR, \"tailscale\", tenant);\n}\nexport function socketPath(tenant: string): string {\n return path.join(tenantStateDir(tenant), \"tailscaled.sock\");\n}\nexport function logPath(tenant: string): string {\n return path.join(tenantStateDir(tenant), \"tailscaled.log\");\n}\nexport function statePath(tenant: string): string {\n return path.join(tenantStateDir(tenant), \"tunnel-state.json\");\n}\n/**\n * Daemon-scoped metadata, written by `ensureDaemon` when it actually spawns the\n * daemon. Unlike `tunnel-state.json` (which `down` clears), this survives `down`\n * so a later `up` reuses the RUNNING daemon's SOCKS port instead of minting a\n * fresh one the daemon isn't listening on (which would leave every forwarder\n * dialing a dead port). Also records the daemon pid so `stopDaemon` can kill it.\n */\nexport function daemonMetaPath(tenant: string): string {\n return path.join(tenantStateDir(tenant), \"daemon.json\");\n}\n/**\n * Ownership manifest written by the RUNNER (the process that binds the\n * forwarder ports) \u2014 pid, process-group id, per-run token, control port. The\n * ownership handshake (MESH-2407) verifies against it; teardown signals the\n * recorded process group.\n */\nexport function runnerManifestPath(tenant: string): string {\n return path.join(tenantStateDir(tenant), \"runner.json\");\n}\n\n// ============================================================================\n// Tunnel-session state\n// ============================================================================\n\nexport interface TunnelState {\n tenant: string;\n env: string;\n socksPort: number;\n loginServer: string;\n /** PID of the detached forwarder supervisor (null until spawned). */\n supervisorPid: number | null;\n /** How the runner is supervised. Defaults to \"detached\" when absent. */\n managed?: \"launchd\" | \"detached\";\n startedAt: string;\n tunnels: TunnelTarget[];\n}\n\nexport function readTunnelState(tenant: string): TunnelState | null {\n const p = statePath(tenant);\n if (!fs.existsSync(p)) return null;\n try {\n return JSON.parse(fs.readFileSync(p, \"utf8\")) as TunnelState;\n } catch {\n return null;\n }\n}\n\nexport function writeTunnelState(tenant: string, state: TunnelState): void {\n fs.mkdirSync(tenantStateDir(tenant), { recursive: true });\n atomicWriteFileSync(statePath(tenant), JSON.stringify(state, null, 2), 0o600);\n}\n\nexport function clearTunnelState(tenant: string): void {\n try {\n fs.unlinkSync(statePath(tenant));\n } catch {\n /* already gone */\n }\n}\n\nexport interface DaemonMeta {\n /** The `--socks5-server` port the running daemon actually listens on. */\n socksPort: number;\n /** PID of the detached `tailscaled` process (for `stopDaemon`). */\n pid: number;\n}\n\nexport function readDaemonMeta(tenant: string): DaemonMeta | null {\n const p = daemonMetaPath(tenant);\n if (!fs.existsSync(p)) return null;\n try {\n return JSON.parse(fs.readFileSync(p, \"utf8\")) as DaemonMeta;\n } catch {\n return null;\n }\n}\n\nexport function writeDaemonMeta(tenant: string, meta: DaemonMeta): void {\n fs.mkdirSync(tenantStateDir(tenant), { recursive: true });\n atomicWriteFileSync(daemonMetaPath(tenant), JSON.stringify(meta, null, 2), 0o600);\n}\n\nexport function clearDaemonMeta(tenant: string): void {\n try {\n fs.unlinkSync(daemonMetaPath(tenant));\n } catch {\n /* already gone */\n }\n}\n\n// ============================================================================\n// Daemon status parsing\n// ============================================================================\n\n/** Parse `tailscale status --json` \u2192 the fields we care about. */\nexport function parseDaemonState(statusJson: string): {\n backendState: string;\n selfName?: string;\n} {\n try {\n const j = JSON.parse(statusJson) as { BackendState?: string; Self?: { HostName?: string } };\n return { backendState: j.BackendState ?? \"Unknown\", selfName: j.Self?.HostName };\n } catch {\n return { backendState: \"Unknown\" };\n }\n}\n\n// ============================================================================\n// Binary resolution (macOS / brew \u2014 Slice 1)\n// ============================================================================\n\n/** The brew `tailscaled` (NOT the GUI app, which ships no standalone daemon). */\nexport function tailscaledBinPath(): string {\n return resolveBrewBin(\"tailscaled\");\n}\n/** The brew `tailscale` CLI (prefer it over the GUI shim, which aborts under sandbox). */\nexport function tailscaleBinPath(): string {\n return resolveBrewBin(\"tailscale\");\n}\nfunction resolveBrewBin(name: string): string {\n const brew = `/opt/homebrew/bin/${name}`;\n if (fs.existsSync(brew)) return brew;\n try {\n const p = execFileSync(\"which\", [name], { encoding: \"utf8\", stdio: [\"ignore\", \"pipe\", \"ignore\"] }).trim();\n if (p) return p;\n } catch {\n /* fall through */\n }\n throw new Error(`${name} not found \u2014 install the standalone binary: brew install tailscale`);\n}\n\n// ============================================================================\n// Daemon lifecycle\n// ============================================================================\n\n/** Backend state via the tenant's control socket; \"Down\" when no daemon answers. */\nexport function daemonState(tenant: string): { backendState: string; selfName?: string } {\n if (!fs.existsSync(socketPath(tenant))) return { backendState: \"Down\" };\n try {\n const out = execFileSync(\n tailscaleBinPath(),\n [\"--socket\", socketPath(tenant), \"status\", \"--json\"],\n { encoding: \"utf8\", stdio: [\"ignore\", \"pipe\", \"ignore\"] },\n );\n return parseDaemonState(out);\n } catch {\n return { backendState: \"Down\" };\n }\n}\n\n/**\n * Extract the `--socks5-server` port from a `tailscaled` command line. Pure so\n * it's unit-testable. Accepts both `--socks5-server=127.0.0.1:PORT` and the\n * space-separated form, and a `localhost` host literal. Returns null if absent\n * or malformed.\n */\nexport function parseSocksPortFromArgv(argv: string): number | null {\n const m = argv.match(/--socks5-server[=\\s]+(?:127\\.0\\.0\\.1|localhost):(\\d+)/);\n if (!m) return null;\n const port = Number(m[1]);\n return Number.isInteger(port) && port > 0 && port <= 65535 ? port : null;\n}\n\n/**\n * Find the running userspace `tailscaled` for a tenant by its unique\n * `--socket=<path>` argument, returning its pid and the SOCKS port it ACTUALLY\n * bound (parsed from argv). Authoritative when `daemon.json` is missing or stale\n * (e.g. a daemon left by an older build that predates the meta file). Returns\n * null when no matching process is found or `ps` is unavailable.\n */\nexport function findRunningDaemon(tenant: string): { pid: number; socksPort: number | null } | null {\n const sock = socketPath(tenant);\n let out: string;\n try {\n out = execFileSync(\"ps\", [\"ax\", \"-o\", \"pid=,command=\"], {\n encoding: \"utf8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n });\n } catch {\n return null;\n }\n for (const line of out.split(\"\\n\")) {\n // Match this tenant's daemon by its unique --socket path (skips the ps line,\n // other tenants' daemons, and the GUI app).\n if (!line.includes(\"tailscaled\") || !line.includes(`--socket=${sock}`)) continue;\n const m = line.trim().match(/^(\\d+)\\s+(.*)$/);\n if (!m) continue;\n return { pid: Number(m[1]), socksPort: parseSocksPortFromArgv(m[2]!) };\n }\n return null;\n}\n\n/** True if something accepts TCP on 127.0.0.1:port within `timeoutMs`. */\nexport function portAccepts(port: number, timeoutMs = 400): Promise<boolean> {\n return new Promise((resolve) => {\n const s = new net.Socket();\n let done = false;\n const fin = (v: boolean) => {\n if (done) return;\n done = true;\n s.destroy();\n resolve(v);\n };\n s.setTimeout(timeoutMs);\n s.once(\"connect\", () => fin(true));\n s.once(\"timeout\", () => fin(false));\n s.once(\"error\", () => fin(false));\n s.connect(port, \"127.0.0.1\");\n });\n}\n\n/**\n * Ensure a userspace `tailscaled` is running for the tenant and return the SOCKS\n * port the forwarders should dial. Idempotent \u2014 reuses a live daemon, but\n * RECONCILES the port: a daemon that's up on a different port than requested\n * (older build with no `daemon.json`, or stale meta) would otherwise leave every\n * forwarder dialing a dead port (MESH-2169). Trust `opts.socksPort` only if it\n * truly accepts; else adopt the running daemon's real port; else restart fresh.\n */\nexport async function ensureDaemon(\n tenant: string,\n opts: { region: string; socksPort: number },\n): Promise<number> {\n if (daemonState(tenant).backendState !== \"Down\") {\n // The daemon's SOCKS proxy is only useful on the exact port the forwarders\n // will dial. If the requested port already accepts, record it and use it.\n if (await portAccepts(opts.socksPort)) {\n writeDaemonMeta(tenant, {\n socksPort: opts.socksPort,\n pid: readDaemonMeta(tenant)?.pid ?? findRunningDaemon(tenant)?.pid ?? 0,\n });\n return opts.socksPort;\n }\n // Requested port is dead \u2014 the daemon is on a different one. Discover its\n // real SOCKS port from argv and adopt it (no restart \u2192 no severing other\n // sessions), rewriting daemon.json so future runs read the right port.\n const running = findRunningDaemon(tenant);\n if (running?.socksPort && (await portAccepts(running.socksPort))) {\n writeDaemonMeta(tenant, { socksPort: running.socksPort, pid: running.pid });\n return running.socksPort;\n }\n // Can't discover/verify a working SOCKS port \u2014 the daemon is unusable to us.\n // Tear it down (state dir keeps the node identity \u2192 no re-login) and fall\n // through to a fresh start on opts.socksPort.\n stopDaemon(tenant);\n for (let i = 0; i < 12 && daemonState(tenant).backendState !== \"Down\"; i++) {\n await sleep(250);\n }\n }\n const dir = tenantStateDir(tenant);\n fs.mkdirSync(dir, { recursive: true });\n const log = fs.openSync(logPath(tenant), \"a\");\n try {\n const child = spawn(\n tailscaledBinPath(),\n [\n \"--tun=userspace-networking\",\n `--socket=${socketPath(tenant)}`,\n `--statedir=${dir}`,\n `--socks5-server=127.0.0.1:${opts.socksPort}`,\n \"--port=0\",\n ],\n {\n detached: true,\n stdio: [\"ignore\", log, log],\n env: { ...process.env, AWS_REGION: opts.region },\n },\n );\n child.unref();\n // Persist the socks port + pid so `down` \u2192 `up` reuses this daemon's real\n // port (not a fresh one it isn't listening on) and `stopDaemon` can kill it.\n if (child.pid) writeDaemonMeta(tenant, { socksPort: opts.socksPort, pid: child.pid });\n } finally {\n fs.closeSync(log);\n }\n for (let i = 0; i < 40; i++) {\n await sleep(250);\n if (daemonState(tenant).backendState !== \"Down\") return opts.socksPort;\n }\n throw new Error(`tailscaled did not start for tenant '${tenant}' \u2014 see ${logPath(tenant)}`);\n}\n\n/**\n * Stop the detached `tailscaled` for a tenant (SIGTERM its pid) and remove the\n * socket + daemon metadata. Leaves the Headscale node identity in `tailscaled.state`\n * so a later `up` re-spawns and rejoins without an interactive re-login \u2014 unless\n * the caller logged out first.\n *\n * Best-effort, and that includes a corrupt `daemon.json`: an unsignalable\n * recorded pid is REFUSED (never handed to `kill`) but only warns \u2014 the socket\n * and meta are still cleared. `ensureDaemon` calls this on the UP path to\n * recycle a daemon it can't verify, so throwing here would dead-end\n * `mesh vpn tunnel up` / `mesh dev` on the very file this function deletes.\n * Safe to call when nothing is running.\n */\nexport function stopDaemon(tenant: string): void {\n // Prefer the recorded pid; fall back to discovering it from argv so a daemon\n // left without a daemon.json (older build / cleared meta) can still be killed.\n const meta = readDaemonMeta(tenant) ?? (() => {\n const running = findRunningDaemon(tenant);\n return running ? { socksPort: running.socksPort ?? 0, pid: running.pid } : null;\n })();\n // `ensureDaemon` records `pid: 0` when it adopts a running daemon whose pid it\n // could not attribute, so absent-or-0 is this file's \"no pid known\" sentinel \u2014\n // skip it, don't signal and don't fail. EVERY other unsignalable value (1, a\n // negative, a fraction, a string from a truncated/hand-edited daemon.json) is\n // corruption and must be refused rather than handed to kill. See utils/pid.ts.\n if (meta?.pid) {\n try {\n assertSignalablePid(meta.pid, {\n what: `the VPN daemon pid recorded for tenant '${tenant}'`,\n file: daemonMetaPath(tenant),\n });\n process.kill(meta.pid, \"SIGTERM\");\n } catch (err) {\n // Refusing to SIGNAL is the whole point; refusing to CLEAN UP is not.\n // The unlink + clearDaemonMeta below are what make the corrupt file\n // self-healing, and `ensureDaemon` (the UP path) depends on them. Warn\n // with the `rm` remediation intact and fall through.\n if (err instanceof MeshCliError) logWarn(renderErrorBody(err));\n /* else: ESRCH/EPERM from process.kill \u2014 already gone, as before */\n }\n }\n for (const p of [socketPath(tenant)]) {\n try {\n fs.unlinkSync(p);\n } catch {\n /* already gone */\n }\n }\n clearDaemonMeta(tenant);\n}\n\n/**\n * Build the `tailscale up` argument vector. Pure so it can be unit-tested and so\n * the interactive (browser-register) and zero-touch (pre-auth key) forms differ\n * only by the trailing `--authkey`.\n */\nexport function buildTailscaleUpArgs(opts: {\n socket: string;\n loginServer: string;\n hostname: string;\n preAuthKey?: string;\n}): string[] {\n const args = [\n \"--socket\", opts.socket, \"up\",\n \"--login-server\", opts.loginServer,\n \"--accept-routes\",\n \"--hostname\", opts.hostname,\n ];\n if (opts.preAuthKey) args.push(\"--authkey\", opts.preAuthKey);\n return args;\n}\n\n/**\n * Join the tenant's Headscale tailnet via Zitadel OIDC if not already Running.\n * Prints the device-flow registration URL and polls until registered. When a\n * pre-auth key is supplied the join is non-interactive: no `/register/` URL is\n * emitted, so the scrape/relay is skipped and we just wait for Running.\n */\nexport async function joinHeadscale(\n tenant: string,\n loginServer: string,\n opts: { preAuthKey?: string } = {},\n): Promise<void> {\n if (daemonState(tenant).backendState === \"Running\") return;\n const hostname = `mesh-${tenant}-${os.hostname().split(\".\")[0]}`;\n const child = spawn(\n tailscaleBinPath(),\n buildTailscaleUpArgs({ socket: socketPath(tenant), loginServer, hostname, preAuthKey: opts.preAuthKey }),\n { stdio: [\"ignore\", \"pipe\", \"pipe\"] },\n );\n if (!opts.preAuthKey) {\n let buf = \"\";\n let urlShown = false;\n const capture = (d: Buffer) => {\n buf += d.toString();\n if (urlShown) return;\n const m = buf.match(/https?:\\/\\/\\S+\\/register\\/\\S+/);\n if (m) {\n urlShown = true;\n // Relay the registration URL for headless/SSH machines (there's no local\n // browser to pop). One-time per machine \u2014 the node registration persists.\n logInfo(\n `\\n This machine isn't registered with the platform VPN yet.\\n` +\n ` Open this URL in a browser to authorize it (one-time, sign in with Zitadel):\\n\\n` +\n ` ${m[0]}\\n\\n` +\n ` Waiting for approval (up to 5 min)\u2026`,\n );\n }\n };\n child.stdout.on(\"data\", capture);\n child.stderr.on(\"data\", capture);\n }\n // Poll up to ~5 min \u2014 the join is an interactive browser approval.\n for (let i = 0; i < 600; i++) {\n await sleep(500);\n if (daemonState(tenant).backendState === \"Running\") {\n child.kill();\n return;\n }\n }\n child.kill();\n throw new Error(\n `VPN join not completed for tenant '${tenant}' within 5 min. Re-run \\`mesh vpn tunnel up\\` to resume \u2014 the daemon is still up.`,\n );\n}\n\n/** Log the tenant daemon out of Headscale (disconnect). Daemon process persists. */\nexport function logout(tenant: string): void {\n try {\n execFileSync(tailscaleBinPath(), [\"--socket\", socketPath(tenant), \"logout\"], { stdio: \"ignore\" });\n } catch {\n /* best-effort */\n }\n}\n\n// ============================================================================\n// Forwarder supervisor (shared per tenant) + devOutput rewrite\n// ============================================================================\n\n/**\n * True iff two target sets are identical down to targetIp + remotePort. A live\n * runner pins each forwarder's target at startup, so if the ELB IP rotated (or a\n * port changed) the running forwarders point at a dead address and must be\n * respawned, not reused. Pid-agnostic (a launchd runner records no supervisor pid).\n */\nexport function tunnelTargetsEqual(a: TunnelTarget[], b: TunnelTarget[]): boolean {\n const key = (ts: TunnelTarget[]) =>\n ts.map((t) => `${t.name}:${t.localPort}:${t.targetIp}:${t.remotePort}`).sort().join(\",\");\n return key(a) === key(b);\n}\n\n/** True iff `state` has a supervisor pid and its target set equals `targets`. */\nexport function supervisorTargetsMatch(\n state: TunnelState | null,\n targets: TunnelTarget[],\n): boolean {\n if (!state || !state.supervisorPid) return false;\n return tunnelTargetsEqual(state.tunnels, targets);\n}\n\nfunction pidAlive(pid: number | null | undefined): boolean {\n if (!pid) return false;\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * SIGTERM the supervisor's whole process GROUP, not the bare pid.\n *\n * `state.supervisorPid` is the pid of the detached spawn \u2014 which, under the\n * canonical source launcher, is `bin/mesh.mjs`. That launcher blocks in\n * `execFileSync` around the *real* runner (a `node --import tsx \u2026 mesh.ts`\n * grandchild that actually binds the forwarder ports), and `execFileSync` does\n * not forward signals. So signalling the bare pid kills only the launcher and\n * ORPHANS the runner, which keeps its ports bound \u2014 the orphan then answers\n * `allForwardersListening`'s ownership-less liveness dial and silently pins\n * every tunnel to a stale target (the MESH-2169 / MESH-2014 failure class).\n *\n * The launcher is spawned `detached: true`, so it is a process-group leader\n * (`pgid === pid`); `process.kill(-pid, \u2026)` reaps the launcher and the runner\n * together. Falls back to the bare pid for a legacy state file whose pid was\n * not a group leader, and tolerates ESRCH (already gone).\n *\n * `pid` is always recovered \u2014 from `tunnel-state.json`, `runner.json`, or a\n * `ps` scan \u2014 never constructed here, so it is guarded first. The guard rejects\n * anything below 2, which is what makes the NEGATED form safe: `pid >= 2` \u21D2\n * `-pid <= -2`, a real process group, never `kill(0)` (this shell's own group)\n * or `kill(-1)` (broadcast to everything the user can signal). See utils/pid.ts.\n *\n * @throws {MeshCliError} when `pid` is unsignalable. Callers reaping SEVERAL\n * independently-recovered pids must catch per-pid (see `stopTunnelRunners`) \u2014\n * letting one refusal propagate would skip the other pids and leave a live\n * runner holding ports.\n */\nexport function killSupervisor(pid: number, source?: PidSource): void {\n // MUST be outside the try \u2014 both signals below are wrapped in catch-alls, so a\n // guard placed inside would have its refusal swallowed and fall through to the\n // bare-pid kill it was meant to prevent.\n assertSignalablePid(pid, source ?? { what: \"tunnel supervisor pid\" });\n try {\n process.kill(-pid, \"SIGTERM\"); // detached spawn \u21D2 pid is the group leader\n } catch {\n try {\n process.kill(pid, \"SIGTERM\"); // not a group leader (old state file) \u2014 best effort\n } catch {\n /* already gone (ESRCH) */\n }\n }\n}\n\n/**\n * The ownership handshake for a tenant's tunnel runner (MESH-2407): manifest \u2192\n * live pid \u2192 control endpoint \u2192 token + SOCKS port + port coverage. This is\n * the ONLY readiness/reuse signal \u2014 a bare TCP dial proves a listener exists,\n * not that it is ours, and adopting a foreign listener is exactly the\n * silent-dead-tunnel class (MESH-2169 / MESH-2014 / #2991). As a bonus the\n * handshake reads listening state from the runner's in-process servers, so it\n * opens no SOCKS\u2192VPC data connection the way port dials do.\n */\nexport async function verifyTunnelOwnership(\n tenant: string,\n expected: { socksPort: number; ports: number[] },\n): Promise<OwnershipCheck> {\n return verifyRunnerOwnership({\n manifest: readRunnerManifest(runnerManifestPath(tenant)),\n expectedSocksPort: expected.socksPort,\n expectedPorts: expected.ports,\n });\n}\n\n/**\n * Poll the ownership handshake until it passes or `deadlineMs` of WALL CLOCK\n * elapses (each check can cost up to the control-query timeout, so the bound\n * must be time, not rounds); returns the last check.\n */\nfunction awaitOwnership(\n tenant: string,\n expected: { socksPort: number; ports: number[] },\n deadlineMs: number,\n): Promise<OwnershipCheck> {\n return pollOwnership(() => verifyTunnelOwnership(tenant, expected), deadlineMs);\n}\n\n/**\n * Tear down EVERY runner we can attribute to the tenant: the recorded\n * supervisor pid (as a process group \u2014 see `killSupervisor`), the launchd\n * agent, the manifest's process group, and any `__run`/`__supervise` process\n * discovered from argv (a runner from an older build, or one whose state file\n * was lost). This is the single teardown path \u2014 the #2991 lesson generalized:\n * no kill path may leave a grandchild with ports still bound.\n */\nexport function stopTunnelRunners(tenant: string, prior: TunnelState | null): void {\n if (prior?.managed === \"launchd\") uninstallLaunchAgent(tenant);\n // Each pid below is RECOVERED (two state files and a ps scan), so each names\n // its own provenance \u2014 the refusal has to point at the exact file to delete,\n // or a corrupt state dir bricks the very command that would have cleared it.\n //\n // The three sources are INDEPENDENT, so a refusal on one must not skip the\n // others or `clearRunnerManifest`. Aborting would let one corrupt integer in\n // `tunnel-state.json` strand a live, uncorrupted runner from `runner.json`\n // with its forwarder ports still bound \u2014 the silent-squatter class this\n // teardown exists to prevent (\"no kill path may leave a grandchild with ports\n // still bound\", MESH-2407). Refuse the bad pid, reap the rest;\n // `assertTunnelPortsFree` is the backstop that still fails loudly if an\n // un-reaped runner really is holding ports.\n const killOrWarn = (pid: number, source: PidSource): void => {\n try {\n killSupervisor(pid, source);\n } catch (err) {\n if (!(err instanceof MeshCliError)) throw err;\n logWarn(renderErrorBody(err));\n }\n };\n if (prior?.supervisorPid)\n killOrWarn(prior.supervisorPid, {\n what: `the tunnel supervisor pid recorded for tenant '${tenant}'`,\n file: statePath(tenant),\n });\n const manifest = readRunnerManifest(runnerManifestPath(tenant));\n if (manifest)\n killOrWarn(manifest.pgid || manifest.pid, {\n what: `the tunnel runner process group recorded for tenant '${tenant}'`,\n file: runnerManifestPath(tenant),\n });\n for (const pid of discoverRunnerPids(tenant, process.pid))\n killOrWarn(pid, { what: `a tunnel runner pid discovered from 'ps' for tenant '${tenant}'` });\n clearRunnerManifest(runnerManifestPath(tenant));\n}\n\n/**\n * After teardown, wait for the tenant's forwarder ports to actually free. Any\n * port still accepting is held by a process we could not kill \u2014 a foreign\n * squatter \u2014 and spawning a runner over it would produce forwarders that\n * silently fail to bind (the false-green readiness gate). Fail LOUDLY instead.\n */\nasync function assertTunnelPortsFree(tenant: string, ports: number[]): Promise<void> {\n let held = ports;\n for (let i = 0; i < 8; i++) {\n const stillHeld: number[] = [];\n for (const p of held) {\n if (await portAccepts(p, 250)) stillHeld.push(p);\n }\n held = stillHeld;\n if (held.length === 0) return;\n await sleep(250);\n }\n const squatted = await findSquattedPorts(held, (p) => portAccepts(p, 250));\n throw new Error(buildSquatterError(tenant, squatted, \"still bound after teardown\"));\n}\n\n/**\n * Ensure the per-tenant forwarder supervisor is running for `state.tunnels`.\n * Idempotent: reuses a live runner ONLY when it passes the ownership handshake\n * (our manifest token, our SOCKS port, every target port listening in-process);\n * otherwise tears down every attributable runner, verifies the ports actually\n * freed (a still-held port is a foreign squatter \u2192 loud failure, never spawn\n * over it), and (re)spawns a fresh runner \u2014 whose readiness is again the\n * handshake, not a bare port dial. Persists the state and returns the pid.\n */\nexport async function ensureForwarders(state: TunnelState): Promise<number> {\n const prior = readTunnelState(state.tenant);\n const expected = { socksPort: state.socksPort, ports: state.tunnels.map((t) => t.localPort) };\n // Reuse-if-healthy must be mode-aware. A launchd runner records no supervisorPid\n // (KeepAlive owns liveness), so gating reuse on pidAlive would tear down + rebind\n // the shared tunnels on EVERY `up`/`mesh dev` \u2014 severing other concurrent sessions,\n // the exact failure MESH-2014 exists to kill. Treat the launchd agent as \"alive\"\n // when its plist is installed; keep the pid check for the detached path.\n const runnerAlive =\n prior?.managed === \"launchd\"\n ? fs.existsSync(launchAgentPath(state.tenant))\n : pidAlive(prior?.supervisorPid);\n if (\n prior &&\n runnerAlive &&\n tunnelTargetsEqual(prior.tunnels, state.tunnels) &&\n // A prior supervisor spawned for a DIFFERENT SOCKS port still binds the same\n // local ports but dials a dead upstream \u2014 reusing it silently strands every\n // tunnel (MESH-2169). The port must match, and the runner must PROVE it is\n // ours via the ownership handshake (liveness \u2260 ownership \u2014 a port answering\n // a dial can be another session's SSM tunnel or an orphaned runner, #2991).\n // Poll briefly rather than sample once: `ports-not-listening` during the\n // runner's own rebind window and `no-control-answer` under load are\n // transient, and a single miss here would tear down a healthy runner SHARED\n // by every concurrent session on the tenant (MESH-2014). This branch is\n // only reached when the runner is alive with matching targets, so the\n // retry costs nothing on cold-start or genuinely-dead paths.\n prior.socksPort === state.socksPort &&\n (await awaitOwnership(state.tenant, expected, 1000)).ok\n ) {\n state.supervisorPid = prior.supervisorPid;\n state.managed = prior.managed;\n writeTunnelState(state.tenant, state);\n return prior.supervisorPid ?? 0;\n }\n // Tear down every attributable runner (state pid group, launchd agent,\n // manifest process group, argv-discovered strays), then require the ports to\n // actually free \u2014 a still-held port is foreign and must fail loudly here,\n // not surface later as a forwarder that silently failed to bind.\n stopTunnelRunners(state.tenant, prior);\n await assertTunnelPortsFree(state.tenant, expected.ports);\n // Write state first so the runner reads the correct targets on start.\n state.supervisorPid = null;\n // Prefer a launchd-supervised runner (survives reboot/crash); fall back to a\n // detached runner where launchd isn't usable (e.g. sandboxed shells). Both run\n // the same self-healing `__run`.\n // argv[1] under the canonical source launcher is bin/mesh.ts, which plain\n // node cannot execute (same failure class as the credential_process fix in\n // aws-auth.ts) \u2014 resolve to the stable launcher, or the bare `mesh` fallback.\n const meshBin = resolveStableMeshBin(process.argv[1]);\n if (launchdAvailable()) {\n state.managed = \"launchd\";\n writeTunnelState(state.tenant, state);\n // launchd does no PATH lookup, so the bare `mesh` fallback can't back a\n // LaunchAgent (it would become `node mesh \u2026`, crash-looping under KeepAlive).\n // Require an absolute path; otherwise fall through to the detached runner,\n // where spawn *does* resolve `mesh` on PATH.\n if (path.isAbsolute(meshBin) && installLaunchAgent(state.tenant, meshBin)) {\n // Installing the agent proves nothing about the forwarders \u2014 wait for the\n // runner's ownership handshake (this path used to return success blind).\n if ((await awaitOwnership(state.tenant, expected, 8000)).ok) return 0;\n uninstallLaunchAgent(state.tenant);\n // `launchctl bootout` signals the job but doesn't wait for it \u2014 spawning\n // the detached runner immediately would race the dying launchd runner for\n // the ports (EADDRINUSE \u2192 a transient turned into a hard failure). Every\n // teardown path must be followed by the ports-actually-freed check.\n await assertTunnelPortsFree(state.tenant, expected.ports);\n logInfo(\"launchd runner did not take ownership of the tunnel ports \u2014 using a detached runner.\");\n } else {\n logInfo(\"launchd install failed \u2014 using a detached self-healing runner.\");\n }\n }\n state.managed = \"detached\";\n writeTunnelState(state.tenant, state);\n // meshBin is the stable launcher, or the bare `mesh` fallback which spawn\n // resolves on PATH here (no PATH-lookup ternary needed \u2014 that was a no-op).\n const child = spawn(meshBin, [\"vpn\", \"tunnel\", \"__run\", state.tenant], {\n detached: true,\n stdio: \"ignore\",\n });\n // ENOENT from the bare `mesh` fallback (mesh-cli not installed globally)\n // arrives asynchronously \u2014 without this handler an unhandled 'error' throws\n // an uncaught exception and takes down `mesh dev` instead of degrading.\n child.on(\"error\", (err) =>\n logWarn(`tunnel supervisor failed to start (${err.message}) \u2014 falling back to SSM.`),\n );\n child.unref();\n state.supervisorPid = child.pid ?? null;\n writeTunnelState(state.tenant, state);\n // Readiness = the ownership handshake, not a port dial: the fresh runner must\n // present its manifest token and report every forwarder listening from its\n // own in-process servers. A dial would also pass for another session's SSM\n // tunnel on the same 2XXXX port \u2014 the false-green this contract kills.\n // Throwing here lands in startServices' catch \u2192 clean SSM fallback.\n const last = await awaitOwnership(state.tenant, expected, 5000);\n if (last.ok) return child.pid ?? -1;\n // Diagnose before failing: a port that accepts TCP while ownership failed is\n // held by someone else \u2014 name it and say exactly what to do.\n const squatted = await findSquattedPorts(expected.ports, (p) => portAccepts(p, 250));\n if (squatted.length > 0) {\n throw new Error(buildSquatterError(state.tenant, squatted, `ownership check: ${last.reason}`));\n }\n const bindErrors = Object.entries(last.resp?.bindErrors ?? {})\n .map(([port, code]) => `port ${port}: ${code}`)\n .join(\", \");\n throw new Error(\n `Tailscale forwarders did not take ownership for tenant '${state.tenant}' ` +\n `(${last.reason}${bindErrors ? `; ${bindErrors}` : \"\"}) \u2014 see ${logPath(state.tenant)}.`,\n );\n}\n\n/**\n * Rewrite `devOutput.tunnels` so each resolved target points at its local\n * forwarder (`localhost:localPort`) \u2014 the same shape `startSsmTunnels`\n * produces. Unmatched tunnels are left untouched. Pure (no mutation of input).\n */\nexport function rewriteTunnelsForTargets(\n devOutput: DevOutput,\n targets: TunnelTarget[],\n): DevOutput {\n const tunnels = { ...devOutput.tunnels };\n for (const t of targets) {\n tunnels[t.name] = { host: \"localhost\", port: t.localPort };\n }\n return { ...devOutput, tunnels };\n}\n\n/** True when the brew `tailscaled` binary is resolvable (Tailscale transport is usable). */\nexport function tailscaleAvailable(): boolean {\n try {\n tailscaledBinPath();\n return true;\n } catch {\n return false;\n }\n}\n\n// ============================================================================\n// Shared engine: ensure/start Tailscale tunnels (used by the command + mesh dev)\n// ============================================================================\n\n/**\n * Ensure the tenant's Tailscale tunnels are fully up: the shared per-tenant\n * daemon (started + OIDC-joined if needed), the resolved VPC targets, and the\n * forwarder supervisor. Idempotent (shared across worktrees/invocations of the\n * same tenant). Returns the resolved targets. Used by both `mesh vpn tunnel up`\n * and `mesh dev --transport=tailscale`.\n */\nexport async function ensureTailscaleTunnels(\n tenant: string,\n env: string,\n opts: { region: string; loginServer: string; socksPort: number; preAuthKey?: string },\n): Promise<TunnelTarget[]> {\n // Reconcile the daemon's SOCKS port \u2014 an already-running daemon may be on a\n // different port than requested; the forwarders MUST dial the real one (MESH-2169).\n const socksPort = await ensureDaemon(tenant, { region: opts.region, socksPort: opts.socksPort });\n await joinHeadscale(tenant, opts.loginServer, { preAuthKey: opts.preAuthKey });\n // Pass the region explicitly rather than clobbering process.env.AWS_REGION \u2014\n // this runs mid `mesh dev` launch and must not mutate the global env.\n const bastion = await getPlatformBastionInfo(tenant, env, opts.region);\n if (!bastion) {\n throw new Error(`Could not read the platform bastion for ${tenant}/${env} (check AWS credentials).`);\n }\n const portOffset = tenantPortIndex(tenant) * PORT_BLOCK;\n const targets = resolveTunnelTargets(bastion.services, resolveElbIp, portOffset);\n if (targets.length === 0) {\n throw new Error(`No resolvable VPC tunnels found for ${tenant}/${env}.`);\n }\n const state: TunnelState = {\n tenant,\n env,\n socksPort,\n loginServer: opts.loginServer,\n supervisorPid: null,\n startedAt: new Date().toISOString(),\n tunnels: targets,\n };\n await ensureForwarders(state);\n return targets;\n}\n\n/**\n * `startSsmTunnels` drop-in for `mesh dev`: ensure the tenant's Tailscale\n * tunnels, then rewrite `devOutput.tunnels` to the local forwarder ports.\n */\nexport async function startTailscaleTunnels(\n devOutput: DevOutput,\n ctx: { tenant: string; env: string; region: string; loginServer: string; socksPort: number; preAuthKey?: string },\n): Promise<DevOutput> {\n const targets = await ensureTailscaleTunnels(ctx.tenant, ctx.env, {\n region: ctx.region,\n loginServer: ctx.loginServer,\n socksPort: ctx.socksPort,\n preAuthKey: ctx.preAuthKey,\n });\n return rewriteTunnelsForTargets(devOutput, targets);\n}\n\n// ============================================================================\n// launchd supervision + self-heal (Slice 2a)\n// ============================================================================\n\nexport function launchAgentLabel(tenant: string): string {\n return `tech.mesh.tunnel.${tenant}`;\n}\n\n/** Minimal XML-escape for plist string values (controlled inputs, but paths can vary). */\nfunction xmlEscape(s: string): string {\n return s\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\");\n}\n\n/** Render the per-tenant LaunchAgent plist (pure). */\nexport function renderLaunchAgentPlist(args: {\n tenant: string;\n meshBin: string;\n nodeBin: string;\n logPath: string;\n /** PATH for the agent \u2014 must include the dir of `tailscaled` so daemon reheal\n * works under launchd's minimal PATH (esp. Intel `/usr/local/bin`). */\n pathEnv?: string;\n}): string {\n const pathEnv = args.pathEnv ?? \"/usr/bin:/bin:/usr/sbin:/sbin\";\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key>\n <string>${launchAgentLabel(args.tenant)}</string>\n <key>ProgramArguments</key>\n <array>\n <string>${xmlEscape(args.nodeBin)}</string>\n <string>${xmlEscape(args.meshBin)}</string>\n <string>vpn</string>\n <string>tunnel</string>\n <string>__run</string>\n <string>${xmlEscape(args.tenant)}</string>\n </array>\n <key>EnvironmentVariables</key>\n <dict>\n <key>PATH</key>\n <string>${xmlEscape(pathEnv)}</string>\n </dict>\n <key>RunAtLoad</key>\n <true/>\n <key>KeepAlive</key>\n <dict>\n <key>SuccessfulExit</key>\n <false/>\n </dict>\n <key>StandardOutPath</key>\n <string>${xmlEscape(args.logPath)}</string>\n <key>StandardErrorPath</key>\n <string>${xmlEscape(args.logPath)}</string>\n</dict>\n</plist>\n`;\n}\n\n/** Targets whose local forwarder port isn't currently accepting connections. */\nexport function forwardersNeedingRebind(\n targets: TunnelTarget[],\n listening: Set<number>,\n): TunnelTarget[] {\n return targets.filter((t) => !listening.has(t.localPort));\n}\n\nexport function launchAgentPath(tenant: string): string {\n return path.join(os.homedir(), \"Library\", \"LaunchAgents\", `${launchAgentLabel(tenant)}.plist`);\n}\n\nfunction guiDomain(): string {\n return `gui/${process.getuid?.() ?? 0}`;\n}\n\nlet _launchdAvailable: boolean | undefined;\n/** True when launchctl works for this user (blocked under the seatbelt sandbox \u2192 false). */\nexport function launchdAvailable(): boolean {\n if (_launchdAvailable !== undefined) return _launchdAvailable;\n try {\n execFileSync(\"which\", [\"launchctl\"], { stdio: \"ignore\" });\n execFileSync(\"launchctl\", [\"print\", guiDomain()], { stdio: \"ignore\" });\n _launchdAvailable = true;\n } catch {\n _launchdAvailable = false;\n }\n return _launchdAvailable;\n}\n\n/**\n * Write + (re)load the per-tenant LaunchAgent. Returns true iff it fully\n * succeeded \u2014 any failure (plist write blocked by the sandbox, `launchctl`\n * bootstrap denied, \u2026) returns false so the caller falls back to a detached\n * runner. Never throws.\n */\nexport function installLaunchAgent(tenant: string, meshBin: string): boolean {\n const plistPath = launchAgentPath(tenant);\n try {\n // Resolve symlinks so the plist embeds a stable path (a since-deleted\n // worktree symlink would leave a KeepAlive agent respawning a dead binary).\n let realMeshBin = meshBin;\n try {\n realMeshBin = fs.realpathSync(meshBin);\n } catch {\n /* keep the raw path */\n }\n // Bake a PATH that includes the tailscaled dir so the runner's daemon reheal\n // works under launchd's minimal PATH (Intel installs live in /usr/local/bin).\n let pathEnv = \"/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin\";\n try {\n pathEnv = `${path.dirname(tailscaledBinPath())}:${pathEnv}`;\n } catch {\n /* fall back to the default PATH */\n }\n fs.mkdirSync(path.dirname(plistPath), { recursive: true });\n fs.writeFileSync(\n plistPath,\n renderLaunchAgentPlist({\n tenant,\n meshBin: realMeshBin,\n nodeBin: process.execPath,\n logPath: path.join(tenantStateDir(tenant), \"runner.log\"),\n pathEnv,\n }),\n );\n try {\n execFileSync(\"launchctl\", [\"bootout\", guiDomain(), plistPath], { stdio: \"ignore\" });\n } catch {\n /* not loaded \u2014 fine */\n }\n execFileSync(\"launchctl\", [\"bootstrap\", guiDomain(), plistPath], { stdio: \"ignore\" });\n return true;\n } catch {\n return false;\n }\n}\n\n/** Unload + remove the per-tenant LaunchAgent (best-effort). */\nexport function uninstallLaunchAgent(tenant: string): void {\n const plistPath = launchAgentPath(tenant);\n try {\n execFileSync(\"launchctl\", [\"bootout\", guiDomain(), plistPath], { stdio: \"ignore\" });\n } catch {\n /* not loaded */\n }\n try {\n fs.unlinkSync(plistPath);\n } catch {\n /* already gone */\n }\n}\n\n// ============================================================================\n// The runner (__run): forwarders + continuous self-heal\n// ============================================================================\n\n/**\n * Long-lived runner for a tenant's tunnels \u2014 used both under launchd and as the\n * detached fallback. Runs a forwarder per target and, every ~5s, self-heals:\n * respawns the daemon if its process died, and rebinds any forwarder whose port\n * stopped listening. As the process that actually binds the ports, it is the\n * sole author of the ownership manifest + control endpoint (MESH-2407) that\n * callers verify against. Needs no AWS (targets come from tunnel-state). Never\n * returns.\n */\nexport async function runTunnels(tenant: string): Promise<never> {\n const st = readTunnelState(tenant);\n if (!st) {\n // State is gone (torn down). Under launchd's KeepAlive a non-zero exit would\n // respawn every ~10s forever (surviving reboots) \u2014 so self-uninstall the\n // agent (no-op when detached), drop any manifest a previous incarnation\n // left (it describes a runner that no longer exists), and exit cleanly.\n uninstallLaunchAgent(tenant);\n clearRunnerManifest(runnerManifestPath(tenant));\n process.exit(0);\n }\n const token = mintRunnerToken();\n const servers = new Map<number, import(\"node:net\").Server>();\n // port \u2192 last bind error code. Surfaced through the control endpoint so a\n // failed bind (EADDRINUSE from a squatted port) is a visible, attributable\n // failure at the caller \u2014 never a silently-dead forwarder.\n const bindErrors = new Map<number, string>();\n const spawnFor = (t: TunnelTarget) => {\n servers.get(t.localPort)?.close();\n bindErrors.delete(t.localPort);\n const server = createForwarder({\n listenPort: t.localPort,\n socksPort: st.socksPort,\n targetIp: t.targetIp,\n targetPort: t.remotePort,\n onError: (err) => {\n bindErrors.set(t.localPort, err.code ?? err.message);\n logWarn(`forwarder ${t.name} failed on 127.0.0.1:${t.localPort}: ${err.code ?? err.message}`);\n },\n });\n server.on(\"listening\", () => bindErrors.delete(t.localPort));\n servers.set(t.localPort, server);\n };\n for (const t of st.tunnels) spawnFor(t);\n const control = await startControlServer(\n (): ControlResponse => ({\n token,\n tenant,\n pid: process.pid,\n socksPort: st.socksPort,\n listening: st.tunnels.filter((t) => servers.get(t.localPort)?.listening).map((t) => t.localPort),\n bindErrors: Object.fromEntries([...bindErrors].map(([p, c]) => [String(p), c])),\n }),\n );\n writeRunnerManifest(runnerManifestPath(tenant), {\n tenant,\n pid: process.pid,\n pgid: getProcessGroupId(process.pid) ?? process.pid,\n token,\n controlPort: control.port,\n socksPort: st.socksPort,\n ports: st.tunnels.map((t) => t.localPort),\n startedAt: new Date().toISOString(),\n });\n const shutdown = () => {\n control.server.close();\n for (const s of servers.values()) s.close();\n // Token-guarded: never clobber the manifest of a newer runner that already\n // replaced us (teardown kills groups, and signal delivery order is loose).\n clearRunnerManifest(runnerManifestPath(tenant), token);\n process.exit(0);\n };\n process.on(\"SIGTERM\", shutdown);\n process.on(\"SIGINT\", shutdown);\n for (;;) {\n await sleep(5000);\n try {\n if (daemonState(tenant).backendState === \"Down\") {\n await ensureDaemon(tenant, {\n region: process.env.AWS_REGION ?? \"us-east-2\",\n socksPort: st.socksPort,\n });\n }\n // Check the in-process net.Server directly \u2014 do NOT dial the forwarder.\n // A dial makes the forwarder open a real SOCKS\u2192VPC-target connection, and\n // the probe's clean FIN doesn't tear the upstream leg down, leaking a\n // connection to Temporal/RDS/etc. every 5s per target.\n const listening = new Set<number>();\n for (const t of st.tunnels) {\n if (servers.get(t.localPort)?.listening) listening.add(t.localPort);\n }\n for (const t of forwardersNeedingRebind(st.tunnels, listening)) spawnFor(t);\n } catch {\n /* keep the loop alive across transient errors */\n }\n }\n}\n", "/**\n * `mesh vpn tunnel` \u2014 userspace-Tailscale tunnels to a tenant's VPC services.\n *\n * Stands up the tenant's `localhost:PORT` set (drop-in for the SSM tunnels)\n * backed by a per-tenant userspace `tailscaled` + SOCKS5 forwarders. Detached\n * and managed: `up` starts everything and returns; `down`/`status` manage it.\n * (MESH-2040 / Slice 1 of MESH-2014; graduates the MESH-2036 spike.)\n */\n\nimport type { Command } from \"commander\";\nimport * as net from \"node:net\";\nimport { logInfo, logError, logSuccess } from \"../../utils/log.js\";\nimport { getContextConfig } from \"../login.js\";\nimport {\n ensureTailscaleTunnels,\n stopDaemon,\n logout,\n daemonState,\n readTunnelState,\n clearTunnelState,\n readDaemonMeta,\n runTunnels,\n stopTunnelRunners,\n verifyTunnelOwnership,\n} from \"../../utils/tailscale.js\";\n\ninterface VpnOpts {\n tenant: string;\n env: string;\n}\n\n/**\n * Derive the Headscale login-server URL from the login context's issuer\n * (`identity.<env>.<domain>` \u2192 `vpn.<env>.<domain>`). Mirrors\n * `vpnEndpointFromContext` in index.ts (kept local to avoid a circular import;\n * Slice 2 can unify).\n */\nfunction deriveLoginServer(context: string): string {\n const cfg = getContextConfig(context);\n if (!cfg?.issuer) {\n throw new Error(`No login config for context '${context}'. Run: mesh login ${context}`);\n }\n const u = new URL(cfg.issuer);\n const parts = u.hostname.split(\".\");\n parts[0] = \"vpn\";\n return `https://${parts.join(\".\")}`;\n}\n\nfunction findFreePort(): Promise<number> {\n return new Promise((resolve, reject) => {\n const s = net.createServer();\n s.on(\"error\", reject);\n s.listen(0, \"127.0.0.1\", () => {\n const port = (s.address() as net.AddressInfo).port;\n s.close(() => resolve(port));\n });\n });\n}\n\nfunction canConnect(port: number): Promise<boolean> {\n return new Promise((resolve) => {\n const s = new net.Socket();\n let settled = false;\n const done = (ok: boolean) => {\n if (settled) return;\n settled = true;\n s.destroy();\n resolve(ok);\n };\n s.setTimeout(500);\n s.once(\"connect\", () => done(true));\n s.once(\"timeout\", () => done(false));\n s.once(\"error\", () => done(false));\n s.connect(port, \"127.0.0.1\");\n });\n}\n\n// \u2500\u2500 up \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nasync function tunnelUp(vpn: VpnOpts, cmdOpts: { context?: string }): Promise<void> {\n const { tenant, env } = vpn;\n const context = cmdOpts.context ?? `${tenant}.${env}`;\n const region = process.env.AWS_REGION ?? process.env.AWS_DEFAULT_REGION ?? \"us-east-2\";\n const loginServer = deriveLoginServer(context);\n\n const prior = readTunnelState(tenant);\n const daemonUp = daemonState(tenant).backendState !== \"Down\";\n // When the daemon is already up, reuse the SOCKS port IT is listening on\n // (from daemon.json, which `down` doesn't clear) \u2014 not `prior` (cleared by\n // `down`) and never a fresh port the daemon isn't bound to.\n const socksPort = daemonUp\n ? (readDaemonMeta(tenant)?.socksPort ?? prior?.socksPort ?? (await findFreePort()))\n : await findFreePort();\n\n logInfo(`Bringing up userspace VPN tunnels for tenant '${tenant}'...`);\n const targets = await ensureTailscaleTunnels(tenant, env, { region, loginServer, socksPort });\n\n logSuccess(`VPN tunnels up for '${tenant}' (${targets.length}):`);\n for (const t of targets) {\n logInfo(` ${t.name.padEnd(14)} 127.0.0.1:${t.localPort} \u2192 ${t.targetHost}:${t.remotePort}`);\n }\n}\n\n// The __run / __supervise runner lives in utils/tailscale.ts (runTunnels) \u2014\n// forwarders + a continuous self-heal loop, used under launchd or detached.\n\n// \u2500\u2500 down \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction tunnelDown(vpn: VpnOpts, cmdOpts: { logout?: boolean; stop?: boolean }): void {\n const { tenant } = vpn;\n const st = readTunnelState(tenant);\n // Nothing to tear down for the forwarders \u2014 but still honor an explicit\n // --stop/--logout so a leaked daemon (state file already gone) can be killed.\n if (!st && !cmdOpts.stop && !cmdOpts.logout) {\n logInfo(`No tunnels running for tenant '${tenant}'.`);\n return;\n }\n // One teardown path for every runner shape (state pid group, launchd agent,\n // manifest process group, argv-discovered strays) \u2014 no kill path may leave a\n // grandchild with ports still bound (MESH-2407).\n stopTunnelRunners(tenant, st);\n if (cmdOpts.logout) {\n logout(tenant);\n logInfo(\"Logged the VPN daemon out of Headscale.\");\n }\n // By default the daemon persists (join-once / reuse). --stop or --logout\n // (after which the daemon is useless) tear it down too.\n if (cmdOpts.stop || cmdOpts.logout) {\n stopDaemon(tenant);\n logInfo(\"Stopped the userspace VPN daemon.\");\n }\n clearTunnelState(tenant);\n logSuccess(`VPN tunnels down for '${tenant}'.`);\n}\n\n// \u2500\u2500 status \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nasync function tunnelStatus(vpn: VpnOpts, cmdOpts: { json?: boolean }): Promise<void> {\n const { tenant } = vpn;\n const st = readTunnelState(tenant);\n const ds = daemonState(tenant);\n // Ownership handshake against the runner's manifest \u2014 status must distinguish\n // \"our runner owns the ports\" from \"something answers the port\" (MESH-2407).\n const owned = st\n ? await verifyTunnelOwnership(tenant, {\n socksPort: st.socksPort,\n ports: st.tunnels.map((t) => t.localPort),\n })\n : null;\n if (cmdOpts.json) {\n console.log(\n JSON.stringify(\n {\n tenant,\n daemon: ds,\n up: !!st,\n managed: st?.managed ?? null,\n owned: owned?.ok ?? false,\n ownership: owned ? (owned.ok ? \"owned\" : owned.reason) : \"no-state\",\n tunnels: st?.tunnels ?? [],\n },\n null,\n 2,\n ),\n );\n return;\n }\n logInfo(`Daemon: ${ds.backendState}${ds.selfName ? ` (${ds.selfName})` : \"\"}`);\n if (!st) {\n logInfo(`No tunnels running for tenant '${tenant}'.`);\n return;\n }\n logInfo(`Managed: ${st.managed ?? \"detached\"}`);\n logInfo(\n owned?.ok\n ? `Runner: owned (verified)`\n : `Runner: NOT OWNED (${owned?.reason}) \u2014 ports below may be foreign listeners`,\n );\n const listening = owned?.ok ? new Set(owned.resp?.listening ?? []) : null;\n for (const t of st.tunnels) {\n // When ownership holds, report from the runner's in-process listening set\n // (no data-plane dial); otherwise fall back to a dial, flagged above.\n const up = listening ? listening.has(t.localPort) : await canConnect(t.localPort);\n logInfo(` ${up ? \"\u2713\" : \"\u2717\"} ${t.name.padEnd(14)} 127.0.0.1:${t.localPort} \u2192 ${t.targetHost}:${t.remotePort}`);\n }\n}\n\n// \u2500\u2500 registration \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Run an action, printing a clean error (not a stack trace) + exit 1 on failure. */\nasync function guard(fn: () => void | Promise<void>): Promise<void> {\n try {\n await fn();\n } catch (e) {\n logError(e instanceof Error ? e.message : String(e));\n process.exit(1);\n }\n}\n\nexport function registerTunnelSubcommands(vpn: Command): void {\n const tunnel = vpn\n .command(\"tunnel\")\n .description(\"Userspace-Tailscale tunnels to VPC services (localhost:PORT set)\");\n\n tunnel\n .command(\"up\", { isDefault: true })\n .description(\"Start the tenant's VPC tunnels over userspace Tailscale\")\n .option(\"--context <ctx>\", \"Login context for the VPN (default: <tenant>.<env>)\")\n .action((cmdOpts: { context?: string }) => guard(() => tunnelUp(vpn.opts() as VpnOpts, cmdOpts)));\n\n tunnel\n .command(\"down\")\n .description(\"Stop the tenant's VPC tunnels\")\n .option(\"--stop\", \"Also stop the userspace tailscaled daemon (keeps VPN login)\")\n .option(\"--logout\", \"Log the daemon out of Headscale and stop it\")\n .action((cmdOpts: { logout?: boolean; stop?: boolean }) =>\n guard(() => tunnelDown(vpn.opts() as VpnOpts, cmdOpts)),\n );\n\n tunnel\n .command(\"status\")\n .description(\"Show daemon + tunnel status\")\n .option(\"--json\", \"Machine-readable output\")\n .action((cmdOpts: { json?: boolean }) => guard(() => tunnelStatus(vpn.opts() as VpnOpts, cmdOpts)));\n\n tunnel\n .command(\"__run <tenant>\", { hidden: true })\n .action((tenant: string) => runTunnels(tenant));\n\n // Back-compat alias for any launchd/detached runner referencing the old name.\n tunnel\n .command(\"__supervise <tenant>\", { hidden: true })\n .action((tenant: string) => runTunnels(tenant));\n}\n", "/**\n * mesh vpn \u2014 Headscale VPN management commands\n *\n * Commands:\n * mesh vpn connect <context> Connect to VPN via Tailscale + OIDC\n * mesh vpn disconnect Disconnect from VPN\n * mesh vpn status Show VPN control plane status\n * mesh vpn api-key Create a Headscale API key\n * mesh vpn pre-auth-key Create a pre-authentication key for a user\n * mesh vpn users List registered VPN users\n *\n * All commands shell out to kubectl. The user must have kubeconfig\n * configured for the target cluster (e.g., via `aws eks update-kubeconfig`).\n */\n\nimport { Command } from \"commander\";\nimport { execFileSync, type ExecFileSyncOptions } from \"child_process\";\nimport * as net from \"node:net\";\nimport { logInfo, logSuccess, logError, logWarn } from \"../../utils/index.js\";\nimport { getContextConfig } from \"../login.js\";\nimport { registerTunnelSubcommands } from \"./tunnel.js\";\nimport {\n ensureDaemon,\n joinHeadscale,\n daemonState,\n stopDaemon,\n tailscaleAvailable,\n readDaemonMeta,\n findRunningDaemon,\n} from \"../../utils/tailscale.js\";\n\n// =============================================================================\n// Constants\n// =============================================================================\n\n/** Default namespace follows the convention: {tenant}-{env}-headscale */\nfunction defaultNamespace(tenant: string, env: string): string {\n return `${tenant}-${env}-headscale`;\n}\n\nconst HEADSCALE_POD = \"headscale-0\";\nconst HEADSCALE_CONTAINER = \"headscale\";\n\n// =============================================================================\n// Options\n// =============================================================================\n\ninterface VpnOptions {\n tenant: string;\n env: string;\n namespace?: string;\n}\n\ninterface PreAuthKeyOptions extends VpnOptions {\n user: string;\n expiration?: string;\n reusable?: boolean;\n ephemeral?: boolean;\n}\n\n// =============================================================================\n// Helpers\n// =============================================================================\n\nfunction resolveNamespace(options: VpnOptions): string {\n return options.namespace ?? defaultNamespace(options.tenant, options.env);\n}\n\n/**\n * Run a headscale CLI command inside the headscale pod.\n * Returns stdout as a string. Throws on non-zero exit.\n */\nfunction headscaleExec(\n namespace: string,\n args: string[],\n opts?: { json?: boolean },\n): string {\n const cmd = [\"headscale\", ...args];\n if (opts?.json) {\n cmd.push(\"--output\", \"json\");\n }\n\n const execOpts: ExecFileSyncOptions = {\n encoding: \"utf-8\" as BufferEncoding,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n };\n\n try {\n const result = execFileSync(\n \"kubectl\",\n [\n \"exec\",\n \"-n\", namespace,\n HEADSCALE_POD,\n \"-c\", HEADSCALE_CONTAINER,\n \"--\",\n ...cmd,\n ],\n execOpts,\n );\n return (result as string).trim();\n } catch (error: unknown) {\n const execError = error as { stderr?: Buffer | string; status?: number };\n const stderr = execError.stderr?.toString().trim() ?? \"\";\n if (stderr) {\n throw new Error(stderr);\n }\n throw error;\n }\n}\n\n/**\n * Derive the likely EKS cluster name from tenant/env convention.\n */\nfunction clusterName(tenant: string, env: string): string {\n return `${tenant}-${env}-eks`;\n}\n\n/**\n * Check that the headscale pod is running and reachable.\n */\nfunction assertPodReady(namespace: string, options: VpnOptions): void {\n try {\n const output = execFileSync(\n \"kubectl\",\n [\n \"get\", \"pod\", HEADSCALE_POD,\n \"-n\", namespace,\n \"-o\", \"jsonpath={.status.phase}\",\n ],\n { encoding: \"utf-8\", stdio: [\"pipe\", \"pipe\", \"pipe\"] },\n );\n if (output.trim() !== \"Running\") {\n logError(`Headscale pod is not running (status: ${output.trim()})`);\n process.exit(1);\n }\n } catch (err: unknown) {\n const stderr = (err as { stderr?: Buffer | string }).stderr?.toString() ?? \"\";\n logError(`Cannot reach headscale pod in namespace ${namespace}`);\n if (stderr.includes(\"expired\") || stderr.includes(\"token\")) {\n logInfo(\"Your AWS credentials appear to be expired. Refresh them and retry.\");\n } else {\n const cluster = clusterName(options.tenant, options.env);\n logInfo(\"Make sure your kubeconfig is configured for the target cluster:\");\n const region = process.env.AWS_REGION ?? process.env.AWS_DEFAULT_REGION ?? \"us-east-2\";\n logInfo(` aws eks update-kubeconfig --name ${cluster} --region ${region}`);\n }\n process.exit(1);\n }\n}\n\n// =============================================================================\n// Commands\n// =============================================================================\n\nasync function vpnStatus(options: VpnOptions): Promise<void> {\n const ns = resolveNamespace(options);\n logInfo(`Checking Headscale in namespace ${ns}...`);\n\n assertPodReady(ns, options);\n\n // Get pod details\n const podJson = execFileSync(\n \"kubectl\",\n [\n \"get\", \"pod\", HEADSCALE_POD,\n \"-n\", ns,\n \"-o\", \"json\",\n ],\n { encoding: \"utf-8\", stdio: [\"pipe\", \"pipe\", \"pipe\"] },\n );\n const pod = JSON.parse(podJson);\n const container = pod.status?.containerStatuses?.find(\n (c: { name: string }) => c.name === HEADSCALE_CONTAINER,\n );\n const image = container?.image ?? \"unknown\";\n const ready = container?.ready ?? false;\n const restarts = container?.restartCount ?? 0;\n\n // Get the HTTPRoute hostname\n let endpoint = \"unknown\";\n try {\n endpoint = execFileSync(\n \"kubectl\",\n [\n \"get\", \"httproute\",\n \"-n\", ns,\n \"-o\", \"jsonpath={.items[0].spec.hostnames[0]}\",\n ],\n { encoding: \"utf-8\", stdio: [\"pipe\", \"pipe\", \"pipe\"] },\n ).trim();\n if (endpoint) {\n endpoint = `https://${endpoint}`;\n }\n } catch {\n // HTTPRoute may not exist\n }\n\n // List users\n let userCount = 0;\n try {\n const usersJson = headscaleExec(ns, [\"users\", \"list\"], { json: true });\n const users = JSON.parse(usersJson);\n userCount = Array.isArray(users) ? users.length : 0;\n } catch {\n // Users may not be queryable yet\n }\n\n // List nodes\n let nodeCount = 0;\n try {\n const nodesJson = headscaleExec(ns, [\"nodes\", \"list\"], { json: true });\n const nodes = JSON.parse(nodesJson);\n nodeCount = Array.isArray(nodes) ? nodes.length : 0;\n } catch {\n // Nodes may not be queryable\n }\n\n console.log(\"\");\n console.log(` Endpoint: ${endpoint}`);\n console.log(` Image: ${image}`);\n console.log(` Ready: ${ready ? \"yes\" : \"no\"}`);\n console.log(` Restarts: ${restarts}`);\n console.log(` Namespace: ${ns}`);\n console.log(` Users: ${userCount}`);\n console.log(` Nodes: ${nodeCount}`);\n console.log(\"\");\n\n if (ready) {\n logSuccess(\"Headscale is healthy\");\n } else {\n logWarn(\"Headscale pod is not ready\");\n }\n}\n\nasync function createApiKey(options: VpnOptions): Promise<void> {\n const ns = resolveNamespace(options);\n logInfo(`Creating Headscale API key in namespace ${ns}...`);\n\n assertPodReady(ns, options);\n\n try {\n const output = headscaleExec(ns, [\"apikeys\", \"create\"]);\n console.log(\"\");\n logSuccess(\"API key created:\");\n console.log(\"\");\n console.log(` ${output}`);\n console.log(\"\");\n logWarn(\"Store this key securely \u2014 it cannot be retrieved again.\");\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : String(error);\n logError(`Failed to create API key: ${message}`);\n process.exit(1);\n }\n}\n\nasync function createPreAuthKey(options: PreAuthKeyOptions): Promise<void> {\n const ns = resolveNamespace(options);\n const { user, expiration, reusable, ephemeral } = options;\n\n logInfo(`Creating pre-auth key for user \"${user}\" in namespace ${ns}...`);\n\n assertPodReady(ns, options);\n\n // Ensure the user exists\n try {\n headscaleExec(ns, [\"users\", \"create\", user]);\n logInfo(`Created user \"${user}\"`);\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : String(error);\n // \"already exists\" is fine\n if (!message.includes(\"already exists\")) {\n logError(`Failed to create user: ${message}`);\n process.exit(1);\n }\n logInfo(`User \"${user}\" already exists`);\n }\n\n const args = [\"preauthkeys\", \"create\", \"--user\", user];\n if (expiration) {\n args.push(\"--expiration\", expiration);\n }\n if (reusable) {\n args.push(\"--reusable\");\n }\n if (ephemeral) {\n args.push(\"--ephemeral\");\n }\n\n try {\n const output = headscaleExec(ns, args);\n console.log(\"\");\n logSuccess(\"Pre-authentication key created:\");\n console.log(\"\");\n console.log(` ${output}`);\n console.log(\"\");\n logInfo(\"Use this key to register a node:\");\n logInfo(` tailscale up --login-server <endpoint> --authkey ${output}`);\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : String(error);\n logError(`Failed to create pre-auth key: ${message}`);\n process.exit(1);\n }\n}\n\nasync function listUsers(options: VpnOptions): Promise<void> {\n const ns = resolveNamespace(options);\n logInfo(`Listing Headscale users in namespace ${ns}...`);\n\n assertPodReady(ns, options);\n\n try {\n const output = headscaleExec(ns, [\"users\", \"list\"]);\n console.log(\"\");\n console.log(output);\n console.log(\"\");\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : String(error);\n logError(`Failed to list users: ${message}`);\n process.exit(1);\n }\n}\n\n// =============================================================================\n// VPN Connect / Disconnect\n// =============================================================================\n\n/**\n * Derive the VPN (Headscale) endpoint from a mesh login context.\n *\n * The login config stores an issuer URL like:\n * https://identity.dev.mesh-platform.trabian.com\n * The VPN endpoint follows the same domain with \"vpn\" as the subdomain:\n * https://vpn.dev.mesh-platform.trabian.com\n */\nfunction vpnEndpointFromContext(context: string): string {\n const config = getContextConfig(context);\n if (!config) {\n throw new Error(\n `No configuration found for \"${context}\".\\n` +\n `Run: mesh login ${context} (or add the context to ~/.config/mesh/config.json)`\n );\n }\n\n const issuerUrl = new URL(config.issuer);\n // Replace the first subdomain (\"identity\") with \"vpn\"\n const hostParts = issuerUrl.hostname.split(\".\");\n if (hostParts.length < 3) {\n throw new Error(\n `Cannot derive VPN endpoint from issuer \"${config.issuer}\". ` +\n `Expected a subdomain like identity.<env>.<domain>.`\n );\n }\n hostParts[0] = \"vpn\";\n return `https://${hostParts.join(\".\")}`;\n}\n\n/** Split a platform context (\"mesh.dev\") into its tenant + env. Pure. */\nexport function parseContextTenantEnv(context: string): { tenant: string; env: string } {\n const [tenant, env] = context.split(\".\");\n return { tenant: tenant || \"mesh\", env: env || \"dev\" };\n}\n\n/** Ephemeral free TCP port on loopback for the userspace daemon's SOCKS proxy. */\nfunction findFreePort(): Promise<number> {\n return new Promise((resolve, reject) => {\n const srv = net.createServer();\n srv.on(\"error\", reject);\n srv.listen(0, \"127.0.0.1\", () => {\n const addr = srv.address();\n const port = typeof addr === \"object\" && addr ? addr.port : 0;\n srv.close(() => resolve(port));\n });\n });\n}\n\n/**\n * Check whether the `tailscale` CLI is installed and return its path,\n * or null if not found.\n */\nfunction findTailscale(): string | null {\n try {\n return execFileSync(\"which\", [\"tailscale\"], {\n encoding: \"utf-8\",\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n }).trim() || null;\n } catch {\n return null;\n }\n}\n\ninterface TailscaleStatus {\n BackendState?: string;\n /** Control server URL, e.g. \"https://vpn.dev.mesh-platform.trabian.com\" */\n ControlURL?: string;\n CurrentTailnet?: { Name?: string } | null;\n}\n\n/** Return Tailscale's full status, or null if tailscale is not running. */\nfunction tailscaleStatus(): TailscaleStatus | null {\n try {\n const json = execFileSync(\"tailscale\", [\"status\", \"--json\"], {\n encoding: \"utf-8\",\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n return JSON.parse(json) as TailscaleStatus;\n } catch {\n return null;\n }\n}\n\n/** Return Tailscale's BackendState, or null if tailscale is not running. */\nexport function tailscaleBackendState(): string | null {\n return tailscaleStatus()?.BackendState ?? null;\n}\n\n/**\n * Normalize a control server URL for comparison.\n * Trims trailing slashes and lowercases the origin.\n */\nfunction normalizeControlUrl(url: string): string {\n try {\n const u = new URL(url);\n return `${u.protocol}//${u.host}`.toLowerCase();\n } catch {\n return url.replace(/\\/+$/, \"\").toLowerCase();\n }\n}\n\nasync function vpnConnect(context: string, opts: { system?: boolean } = {}): Promise<void> {\n const endpoint = vpnEndpointFromContext(context);\n if (opts.system) {\n // Whole-machine VPN via the GUI Tailscale.app daemon. Opt-in only: it needs\n // the GUI app installed/running and CANNOT run headless or under the safehouse\n // sandbox (dyld can't load the app bundle's Sparkle.framework \u2192 abort trap).\n await vpnConnectSystem(endpoint);\n return;\n }\n await vpnConnectUserspace(context, endpoint);\n}\n\n/**\n * Default path: bring up the per-tenant userspace `tailscaled` (brew formula, NOT\n * the GUI app) and register this machine with the platform Headscale. This is the\n * same daemon `mesh dev --transport tailscale` / `mesh vpn tunnel` already use, so\n * it runs headless and under the sandbox. It exposes a local SOCKS5 proxy \u2014 the\n * userspace analog of system-wide routing \u2014 instead of a system TUN; for\n * auto-forwarded VPC services (Temporal, RDS, \u2026) use `mesh vpn tunnel` / `mesh dev`.\n */\nasync function vpnConnectUserspace(context: string, loginServer: string): Promise<void> {\n if (!tailscaleAvailable()) {\n logError(\"Standalone tailscale/tailscaled not found.\");\n logInfo(\"Install it: brew install tailscale\");\n logInfo(\"(The GUI Tailscale.app is not used here \u2014 for whole-machine VPN see `mesh vpn connect --system`.)\");\n process.exit(1);\n }\n const { tenant } = parseContextTenantEnv(context);\n const region = process.env.AWS_REGION ?? process.env.AWS_DEFAULT_REGION ?? \"us-east-2\";\n\n if (daemonState(tenant).backendState === \"Running\") {\n // Prefer daemon.json; recover the real bound port from argv if meta is missing\n // (older build) so a \"connected\" session always shows how to reach it.\n const port = readDaemonMeta(tenant)?.socksPort ?? findRunningDaemon(tenant)?.socksPort;\n logSuccess(`Already connected to the platform VPN for '${tenant}' (userspace).`);\n if (port) logInfo(` SOCKS5 proxy: 127.0.0.1:${port} (route a tool via ALL_PROXY=socks5://127.0.0.1:${port})`);\n return;\n }\n\n logInfo(`Connecting to the platform VPN for '${tenant}' (userspace tailscaled)\u2026`);\n const socksPort = readDaemonMeta(tenant)?.socksPort ?? (await findFreePort());\n const realPort = await ensureDaemon(tenant, { region, socksPort });\n // Interactive join \u2014 joinHeadscale relays the one-time registration URL for\n // headless/SSH machines (no local browser to pop) and polls up to ~5 min.\n await joinHeadscale(tenant, loginServer);\n logSuccess(`VPN connected (userspace) for '${tenant}'.`);\n logInfo(` SOCKS5 proxy: 127.0.0.1:${realPort} \u2014 route a tool via ALL_PROXY=socks5://127.0.0.1:${realPort}`);\n logInfo(\" For auto-forwarded VPC services (Temporal, RDS, \u2026): mesh vpn tunnel up (or mesh dev)\");\n}\n\n/** Opt-in whole-machine VPN via the GUI Tailscale.app daemon (`mesh vpn connect --system`). */\nasync function vpnConnectSystem(endpoint: string): Promise<void> {\n if (!findTailscale()) {\n logError(\"Tailscale CLI not found.\");\n logInfo(\"Install it: brew install tailscale (or see https://tailscale.com/download)\");\n process.exit(1);\n }\n\n // If already connected to *this* endpoint, short-circuit. But if connected\n // to a different control server, fall through and reconnect \u2014 otherwise the\n // user would silently stay on the wrong tailnet.\n const status = tailscaleStatus();\n if (status?.BackendState === \"Running\") {\n const current = status.ControlURL ? normalizeControlUrl(status.ControlURL) : null;\n const target = normalizeControlUrl(endpoint);\n if (current === target) {\n logSuccess(`Already connected to VPN at ${endpoint}.`);\n logInfo(\"Run: tailscale status to see connected nodes.\");\n return;\n }\n if (current) {\n logWarn(`Currently connected to ${current}. Reconnecting to ${target}...`);\n }\n }\n\n logInfo(`Connecting to VPN at ${endpoint}...`);\n logInfo(\"A browser window will open for Zitadel authentication.\");\n console.log(\"\");\n\n // tailscale up is interactive (opens browser), so we inherit stdio.\n // On macOS, Tailscale.app owns the daemon \u2014 `tailscale up` talks to it.\n // On Linux, tailscaled runs as root and `tailscale up` may need sudo.\n //\n // --reset: wipe prior prefs so this command is idempotent. Without it,\n // tailscale refuses to apply prefs if a previous session set non-default\n // flags that aren't re-specified here.\n // --accept-routes: accept subnet routes advertised by the Headscale\n // SubnetRouter so clients can reach in-VPC services (EKS, RDS, internal LBs).\n const upArgs = [\n \"up\",\n \"--reset\",\n \"--login-server\", endpoint,\n \"--accept-routes\",\n ];\n try {\n execFileSync(\"tailscale\", upArgs, { stdio: \"inherit\" });\n console.log(\"\");\n logSuccess(\"VPN connected.\");\n } catch (error: unknown) {\n const code = (error as { status?: number }).status;\n const isPermissionError = process.platform === \"linux\" && (code === 1 || code === 2);\n console.log(\"\");\n logError(`tailscale up failed (exit ${code}).`);\n if (isPermissionError) {\n logInfo(\"On Linux, tailscaled runs as root \u2014 you may need sudo:\");\n logInfo(` sudo tailscale ${upArgs.join(\" \")}`);\n }\n process.exit(1);\n }\n}\n\nasync function vpnDisconnect(opts: { tenant: string; system?: boolean }): Promise<void> {\n if (opts.system) {\n // Whole-machine GUI Tailscale down (opt-in, mirrors `connect --system`).\n if (!findTailscale()) {\n logError(\"Tailscale CLI not found.\");\n process.exit(1);\n }\n if (tailscaleBackendState() !== \"Running\") {\n logInfo(\"System VPN is not connected.\");\n return;\n }\n logInfo(\"Disconnecting system VPN\u2026\");\n try {\n execFileSync(\"tailscale\", [\"down\"], { stdio: \"inherit\" });\n logSuccess(\"VPN disconnected.\");\n } catch (error: unknown) {\n const code = (error as { status?: number }).status;\n logError(`tailscale down failed (exit ${code}). Try: sudo tailscale down`);\n process.exit(1);\n }\n return;\n }\n\n // Default: stop the tenant's userspace daemon (leaves the Headscale node\n // identity in the statedir so a later `connect` rejoins without re-login).\n const { tenant } = opts;\n if (daemonState(tenant).backendState === \"Down\") {\n logInfo(`No userspace VPN daemon running for '${tenant}'.`);\n return;\n }\n logInfo(`Disconnecting userspace VPN for '${tenant}'\u2026`);\n stopDaemon(tenant);\n logSuccess(`VPN disconnected for '${tenant}'.`);\n}\n\n// =============================================================================\n// Registration\n// =============================================================================\n\nexport function registerVpnCommands(program: Command): void {\n const vpn = program\n .command(\"vpn\")\n .description(\"Headscale VPN management\")\n .option(\"-t, --tenant <tenant>\", \"Platform tenant\", \"mesh\")\n .option(\"-e, --env <env>\", \"Platform environment\", \"dev\")\n .option(\"-n, --namespace <namespace>\", \"Override K8s namespace (default: {tenant}-{env}-headscale)\");\n\n vpn\n .command(\"status\")\n .description(\"Show VPN control plane status\")\n .action(async () => {\n const opts = vpn.opts() as VpnOptions;\n await vpnStatus(opts);\n });\n\n vpn\n .command(\"connect\")\n .description(\"Connect to the platform VPN (userspace tailscaled; opens browser for Zitadel auth)\")\n .argument(\"<context>\", 'Platform context (e.g., \"mesh.dev\")')\n .option(\n \"--system\",\n \"Use the whole-machine GUI Tailscale.app instead (system TUN; cannot run headless/sandboxed)\",\n )\n .action(async (context: string, cmdOpts: { system?: boolean }) => {\n await vpnConnect(context, cmdOpts);\n });\n\n vpn\n .command(\"disconnect\")\n .description(\n \"Disconnect from the platform VPN \u2014 stops the tenant's shared userspace daemon \" +\n \"(also ends any active `mesh vpn tunnel` / `mesh dev` forwards for it); --system for GUI Tailscale\",\n )\n .option(\"--system\", \"Disconnect the whole-machine GUI Tailscale instead of the userspace daemon\")\n .action(async (cmdOpts: { system?: boolean }) => {\n const { tenant } = vpn.opts() as VpnOptions;\n await vpnDisconnect({ tenant, system: cmdOpts.system });\n });\n\n vpn\n .command(\"api-key\")\n .description(\"Create a Headscale API key\")\n .action(async () => {\n const opts = vpn.opts() as VpnOptions;\n await createApiKey(opts);\n });\n\n vpn\n .command(\"pre-auth-key\")\n .description(\"Create a pre-authentication key for node registration\")\n .requiredOption(\"-u, --user <user>\", \"User/namespace to create the key for (e.g., matt@trabian.com)\")\n .option(\"--expiration <duration>\", \"Key expiration (e.g., 24h, 7d)\", \"24h\")\n .option(\"--reusable\", \"Allow key to be used multiple times\")\n .option(\"--ephemeral\", \"Nodes registered with this key are ephemeral\")\n .action(async (cmdOpts: { user: string; expiration?: string; reusable?: boolean; ephemeral?: boolean }) => {\n const parentOpts = vpn.opts() as VpnOptions;\n await createPreAuthKey({ ...parentOpts, ...cmdOpts });\n });\n\n vpn\n .command(\"users\")\n .description(\"List registered VPN users\")\n .action(async () => {\n const opts = vpn.opts() as VpnOptions;\n await listUsers(opts);\n });\n\n registerTunnelSubcommands(vpn);\n}\n", "/**\n * Client for the Zitadel-gated registry-auth broker.\n *\n * This is the path that lets a brand-new Trabian developer install\n * `@mesh-tech/*` with **no AWS account, no AWS CLI and no ~/.aws/config**: the\n * broker verifies the Zitadel id token `mesh login` already cached, checks the\n * caller's role, and returns a CodeArtifact token minted with the BROKER's AWS\n * identity. No AWS credential of any kind reaches the laptop.\n *\n * Everything here is pure or dependency-injected so the fallback behaviour \u2014\n * which is what decides whether a broker hiccup breaks an install \u2014 is\n * unit-testable without a network.\n */\n\nimport { getContextConfig, getValidToken, readAllCredentials, readAllContextConfigs } from \"../commands/login.js\";\n\ntype CtxConfig = { issuer?: string; registryBroker?: string } | null;\n\n/**\n * Pick a context for a `mesh registry login` invoked with none.\n *\n * A context-less call used to skip the broker outright, which quietly sent\n * anyone following a remediation that omits the context straight back to the\n * AWS chain \u2014 the exact routing this feature removes. So: if exactly one cached\n * context publishes a `registryBroker`, use it. Zero or several is genuinely\n * ambiguous and the caller must say which.\n *\n * Deliberately narrow. Guessing among several contexts would post the user's id\n * token to a broker they did not name.\n */\nexport function resolveDefaultBrokerContext(\n configs: Record<string, { registryBroker?: string }> = readAllContextConfigs(),\n credentials: Record<string, unknown> = readAllCredentials(),\n): { context: string } | { reason: \"none\" | \"ambiguous\"; candidates: string[] } {\n const candidates = Object.entries(configs)\n .filter(([name, cfg]) => Boolean(cfg?.registryBroker) && name in credentials)\n .map(([name]) => name);\n if (candidates.length === 1) return { context: candidates[0]! };\n return { reason: candidates.length === 0 ? \"none\" : \"ambiguous\", candidates };\n}\n\n/** A successful grant from `POST /token`. */\nexport interface RegistryGrant {\n /** npm scope the endpoint is bound to, e.g. \"@mesh-tech\". */\n scope: string;\n /** Registry endpoint URL (npm format). */\n endpoint: string;\n /** CodeArtifact bearer for the `//<host>:_authToken=` npmrc line. */\n authorizationToken: string;\n /** ISO 8601 expiry, for reporting. */\n expiresAt?: string;\n}\n\n/** Why a broker attempt didn't produce a grant. */\nexport type RegistryBrokerFailure =\n /** No broker URL for this context \u2014 the platform predates the broker. */\n | { kind: \"no-broker\" }\n /** No cached Zitadel session \u2014 the user needs `mesh login <context>`. */\n | { kind: \"no-session\" }\n /** The broker rejected the token (expired/wrong audience). */\n | { kind: \"unauthenticated\" }\n /** A valid Mesh account that has not been granted registry access. */\n | { kind: \"not-authorized\"; email?: string; requiredRoles?: string[]; requestUrl?: string }\n /** Broker unreachable, 5xx, or a malformed body. */\n | { kind: \"unavailable\"; detail: string };\n\nexport type RegistryBrokerResult =\n | { ok: true; grant: RegistryGrant }\n | { ok: false; failure: RegistryBrokerFailure };\n\n/**\n * Resolve the broker URL, preferring the platform-published value from\n * discovery (`ContextConfig.registryBroker`) and falling back to DNS-convention\n * derivation for platforms not yet redeployed with the payload field.\n *\n * Mirrors `resolveVpnJoinBroker` deliberately \u2014 one convention for\n * platform-published service URLs, not two.\n */\nexport function resolveRegistryBroker(\n context: string,\n getCfg: (c: string) => CtxConfig = getContextConfig,\n): string | null {\n return resolveRegistryBrokerSource(context, getCfg).url;\n}\n\n/**\n * Timeout for a broker whose URL the platform actually published. It exists;\n * wait for it.\n */\nexport const PUBLISHED_BROKER_TIMEOUT_MS = 15_000;\n\n/**\n * Timeout for a broker URL we merely *derived* by DNS convention. For every\n * platform that has not deployed the broker \u2014 which today is all of them \u2014 that\n * host does not exist, and this wait sits in front of the AWS fallback on the\n * `mesh login` path too. Fail fast on a guess; be patient with a fact.\n */\nexport const DERIVED_BROKER_TIMEOUT_MS = 4_000;\n\n/**\n * Resolve the broker URL *and* say where it came from, so the caller can pick a\n * timeout that matches how much confidence the URL deserves.\n */\nexport function resolveRegistryBrokerSource(\n context: string,\n getCfg: (c: string) => CtxConfig = getContextConfig,\n): { url: string | null; source: \"published\" | \"derived\" } {\n const cfg = getCfg(context);\n if (cfg?.registryBroker) return { url: cfg.registryBroker, source: \"published\" };\n return { url: deriveRegistryBroker(context, getCfg), source: \"derived\" };\n}\n\n/**\n * FALLBACK ONLY. Derive by convention \u2014 issuer host `identity.<env>.<domain>`\n * \u2192 `registry-auth.<env>.<domain>`. Prefer `resolveRegistryBroker`, which reads\n * the platform-published URL first.\n */\nexport function deriveRegistryBroker(\n context: string,\n getCfg: (c: string) => CtxConfig = getContextConfig,\n): string | null {\n const cfg = getCfg(context);\n if (!cfg?.issuer) return null;\n try {\n const u = new URL(cfg.issuer);\n const parts = u.hostname.split(\".\");\n parts[0] = \"registry-auth\";\n return `https://${parts.join(\".\")}`;\n } catch {\n return null;\n }\n}\n\nexport interface FetchGrantDeps {\n getValidToken: (context: string) => Promise<string | null>;\n fetchFn?: typeof fetch;\n /** Abort the broker call after this long. Keeps a wedged broker from hanging an install. */\n timeoutMs?: number;\n}\n\n/**\n * Classify a broker response into a grant or a typed failure.\n *\n * Split out from the fetch so every status code's meaning is pinned by a test.\n * The distinction that matters: **401 means re-login, 403 means request\n * access** \u2014 collapsing them (as a boolean-returning client would) is what\n * sends a developer to re-run `mesh login` forever when the real answer is\n * \"ask an admin for the role\".\n */\nexport async function classifyBrokerResponse(res: {\n status: number;\n json: () => Promise<unknown>;\n}): Promise<RegistryBrokerResult> {\n if (res.status === 401) return { ok: false, failure: { kind: \"unauthenticated\" } };\n\n if (res.status === 403) {\n const body = (await res.json().catch(() => ({}))) as Record<string, unknown>;\n return {\n ok: false,\n failure: {\n kind: \"not-authorized\",\n email: typeof body.email === \"string\" ? body.email : undefined,\n requiredRoles: Array.isArray(body.requiredRoles)\n ? body.requiredRoles.filter((r): r is string => typeof r === \"string\")\n : undefined,\n requestUrl: typeof body.requestUrl === \"string\" ? body.requestUrl : undefined,\n },\n };\n }\n\n if (res.status !== 200) {\n return { ok: false, failure: { kind: \"unavailable\", detail: `broker returned ${res.status}` } };\n }\n\n let body: Record<string, unknown>;\n try {\n body = (await res.json()) as Record<string, unknown>;\n } catch (err) {\n return {\n ok: false,\n failure: { kind: \"unavailable\", detail: `malformed broker response: ${(err as Error).message}` },\n };\n }\n\n const { endpoint, authorizationToken, scope, expiresAt } = body;\n if (typeof endpoint !== \"string\" || !endpoint || typeof authorizationToken !== \"string\" || !authorizationToken) {\n return {\n ok: false,\n failure: { kind: \"unavailable\", detail: \"broker response missing endpoint or authorizationToken\" },\n };\n }\n\n return {\n ok: true,\n grant: {\n scope: typeof scope === \"string\" && scope ? scope : \"@mesh-tech\",\n endpoint,\n authorizationToken,\n expiresAt: typeof expiresAt === \"string\" ? expiresAt : undefined,\n },\n };\n}\n\n/**\n * Exchange the cached Zitadel id token for a CodeArtifact read grant.\n *\n * `interactive: false` on the token lookup \u2014 this runs inside\n * `mesh registry login`, which has its own AWS fallback chain, so an expired\n * session must return `no-session` rather than stalling a headless run in a\n * device-code poll.\n */\nexport async function fetchRegistryGrant(\n context: string,\n brokerUrl: string,\n deps: FetchGrantDeps,\n): Promise<RegistryBrokerResult> {\n const token = await deps.getValidToken(context);\n if (!token) return { ok: false, failure: { kind: \"no-session\" } };\n\n const doFetch = deps.fetchFn ?? fetch;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), deps.timeoutMs ?? PUBLISHED_BROKER_TIMEOUT_MS);\n try {\n const res = await doFetch(`${brokerUrl.replace(/\\/+$/, \"\")}/token`, {\n method: \"POST\",\n headers: { authorization: `Bearer ${token}` },\n signal: controller.signal,\n });\n return await classifyBrokerResponse(res);\n } catch (err) {\n return {\n ok: false,\n failure: { kind: \"unavailable\", detail: (err as Error).message },\n };\n } finally {\n clearTimeout(timer);\n }\n}\n\n/** Convenience for production callers that use the real login.ts token source. */\nexport function realGrantDeps(): FetchGrantDeps {\n return { getValidToken: (c) => getValidToken(c) };\n}\n", "/**\n * `mesh registry publish --snapshot` \u2014 publish an in-development *snapshot* of the\n * @mesh-tech/* packages to CodeArtifact under a `dev` dist-tag.\n *\n * Why: a consumer repo outside the monorepo (e.g. fub-mesh-apps) can't use\n * `workspace:*`, and cutting a real release for every SDK/UI tweak is heavy. A\n * snapshot publishes the CURRENT source at a throwaway prerelease version\n * (`0.0.0-dev.<stamp>.<sha>`). Because it's a `0.0.0` prerelease, a consumer's\n * `^`/`~` ranges NEVER auto-resolve it \u2014 it's picked up ONLY by an explicit pin\n * or the `dev` dist-tag. That's the \"pushed to the registry but explicitly\n * referenced\" contract.\n *\n * Real releases still go through changesets + the changeset-version CI workflow;\n * this command is dev-loop tooling only and never touches the `latest` dist-tag.\n *\n * Mechanism: set the snapshot version into each selected publishable package.json,\n * reuse the proven scripts/publish-packages.sh (which runs build:publish \u2014 whose\n * build-for-publish.ts rewrites internal workspace:* deps to the local version,\n * i.e. the snapshot \u2014 then publishes each package), always restore the source\n * package.json versions afterward.\n */\nimport { execFileSync, execSync } from \"child_process\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport type { Command } from \"commander\";\nimport { logError, logInfo, logSuccess } from \"../utils/log.js\";\nimport { resolveCredentials, codeartifactLogin } from \"./registry.js\";\n\ninterface PublishablePkg {\n name: string;\n dir: string;\n subPackages?: (string | { dir: string; name?: string })[];\n}\n\ninterface PublishOpts {\n snapshot?: boolean;\n tag: string;\n only?: string;\n dryRun?: boolean;\n role?: string;\n}\n\nfunction repoRoot(): string {\n return execSync(\"git rev-parse --show-toplevel\", { encoding: \"utf-8\" }).trim();\n}\n\n/** `0.0.0-dev.<YYYYMMDDHHMMSS>.<shortsha>` \u2014 a valid semver prerelease. */\nfunction computeSnapshotVersion(root: string): string {\n const sha = execSync(\"git rev-parse --short HEAD\", { cwd: root, encoding: \"utf-8\" }).trim();\n const stamp = new Date().toISOString().replace(/[-:T]/g, \"\").slice(0, 14);\n return `0.0.0-dev.${stamp}.${sha}`;\n}\n\n/** Rewrite the top-level \"version\" field, preserving the file's formatting. */\nfunction setPackageVersion(file: string, version: string): void {\n const content = fs.readFileSync(file, \"utf-8\");\n const next = content.replace(/\"version\"(\\s*:\\s*)\"[^\"]*\"/, `\"version\"$1\"${version}\"`);\n fs.writeFileSync(file, next);\n}\n\n/**\n * Tracked package.json files with uncommitted modifications (`git diff`), as a set\n * of repo-relative paths. Used to tell the user's OWN pre-existing edits apart from\n * files `build:publish` dirties as a side effect (it re-vendors e.g. hub subpackages),\n * so cleanup reverts only the latter.\n */\nfunction dirtyPackageJsons(root: string): Set<string> {\n const out = execSync(\"git diff --name-only\", { cwd: root, encoding: \"utf-8\" });\n return new Set(\n out.split(\"\\n\").map((s) => s.trim()).filter((s) => s.endsWith(\"package.json\")),\n );\n}\n\nexport function registerRegistryPublish(registry: Command): void {\n registry\n .command(\"publish\")\n .description(\n \"Publish an in-development snapshot of @mesh-tech packages to CodeArtifact (dev dist-tag)\",\n )\n .argument(\"[context]\", 'Platform context for Zitadel auth (e.g. \"mesh.dev\")')\n .option(\n \"--snapshot\",\n \"Publish a dev snapshot build (required \u2014 real releases go through changesets/CI)\",\n false,\n )\n .option(\"--tag <tag>\", \"dist-tag to publish the snapshot under\", \"dev\")\n .option(\n \"--only <pkgs>\",\n \"Comma-separated substring filter, e.g. --only agent-sdk,app-kit (default: all publishable)\",\n )\n .option(\"--dry-run\", \"Build + resolve versions but do not upload\", false)\n .option(\"--role <arn>\", \"IAM role ARN for registry access\")\n .action(async (context: string | undefined, opts: PublishOpts) => {\n if (!opts.snapshot) {\n logError(\n \"mesh registry publish currently supports only snapshot (dev) builds.\\n\\n\" +\n \"Re-run with --snapshot. Real releases go through changesets + the\\n\" +\n \"changeset-version CI workflow, not this command.\",\n );\n process.exit(1);\n }\n\n const root = repoRoot();\n\n // 1. CodeArtifact auth (token + scoped registry written to ~/.npmrc).\n const awsCreds = resolveCredentials(context, opts.role);\n const env =\n Object.keys(awsCreds).length > 0\n ? ({ ...process.env, ...awsCreds } as Record<string, string>)\n : undefined;\n logInfo(\"Authenticating with CodeArtifact...\");\n if (!codeartifactLogin(env)) {\n logError(\"CodeArtifact login failed. Run: mesh registry login <context>\");\n process.exit(1);\n }\n\n // 2. Resolve the publishable set (optionally filtered by --only).\n const listPath = path.join(root, \"scripts/lib/publishable-packages.json\");\n const all: PublishablePkg[] = JSON.parse(fs.readFileSync(listPath, \"utf-8\"));\n const patterns = (opts.only ?? \"\")\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean);\n const selected = patterns.length\n ? all.filter((p) => patterns.some((pat) => p.dir.includes(pat) || p.name.includes(pat)))\n : all;\n if (selected.length === 0) {\n logError(`No publishable package matched --only '${opts.only}'`);\n process.exit(1);\n }\n\n // 3. Snapshot version \u2014 uniform across the selected set so their internal\n // @mesh-tech deps rewrite to the same version.\n const version = computeSnapshotVersion(root);\n logInfo(`Snapshot version: ${version} (dist-tag '${opts.tag}')`);\n\n // Snapshot the user's PRE-EXISTING dirty package.json set, so the cleanup in\n // `finally` reverts only what this run (and build:publish) touched, never their edits.\n const preDirty = dirtyPackageJsons(root);\n\n // 4. Stamp the version onto each selected package (+ its sub-packages),\n // remembering the originals so we can always restore.\n const backups: { file: string; content: string }[] = [];\n const stamp = (dir: string): void => {\n const file = path.join(root, dir, \"package.json\");\n if (!fs.existsSync(file)) return;\n backups.push({ file, content: fs.readFileSync(file, \"utf-8\") });\n setPackageVersion(file, version);\n };\n\n try {\n for (const p of selected) {\n stamp(p.dir);\n for (const sub of p.subPackages ?? []) {\n stamp(path.join(p.dir, typeof sub === \"string\" ? sub : sub.dir));\n }\n }\n\n // 5. Build + publish via the proven script (dev tag, never `latest`).\n const args = [\n \"scripts/publish-packages.sh\",\n \"--tag\",\n opts.tag,\n \"--skip-latest\",\n // Pass the TS-resolved DIRS (not the raw patterns) so the shell's\n // dir-substring --only filter selects exactly the set we stamped \u2014\n // a name-only pattern would otherwise stamp here but be skipped there.\n ...(patterns.length ? [\"--only\", selected.map((p) => p.dir).join(\",\")] : []),\n ...(opts.dryRun ? [\"--dry-run\"] : []),\n ];\n logInfo(`Publishing ${selected.length} package(s)...`);\n execFileSync(\"bash\", args, { cwd: root, stdio: \"inherit\", env: env ?? process.env });\n } finally {\n for (const b of backups) fs.writeFileSync(b.file, b.content);\n logInfo(\"Restored source package.json versions.\");\n\n // build:publish re-vendors some package.json files (e.g. hub subpackages)\n // beyond the ones we stamped \u2014 revert those too so a local run leaves a clean\n // tree, but NEVER the user's own pre-existing edits.\n const collateral = [...dirtyPackageJsons(root)].filter((f) => !preDirty.has(f));\n if (collateral.length) {\n try {\n execFileSync(\"git\", [\"checkout\", \"--\", ...collateral], { cwd: root, stdio: \"inherit\" });\n logInfo(`Reverted ${collateral.length} package.json file(s) re-vendored by build:publish.`);\n } catch {\n logError(\n `Could not auto-revert build:publish side-effects \u2014 run \\`git checkout --\\` on:\\n ${collateral.join(\"\\n \")}`,\n );\n }\n }\n }\n\n // 6. Tell the user exactly how to consume it.\n logSuccess(`Published snapshot ${version} under dist-tag '${opts.tag}'.`);\n console.log(\n \"\\nPin these EXACTLY in the consumer repo (prereleases are never auto-resolved by ^/~):\",\n );\n for (const p of selected) console.log(` \"${p.name}\": \"${version}\",`);\n console.log(\n `\\nOr always grab the newest dev build:\\n pnpm add ${selected\n .map((p) => `${p.name}@${opts.tag}`)\n .join(\" \")}`,\n );\n });\n}\n", "/**\n * mesh registry \u2014 Manage npm registry authentication for @mesh-tech packages.\n *\n * Handles CodeArtifact token refresh and project .npmrc setup so that\n * `pnpm install` can resolve @mesh-tech/* packages from the private registry.\n *\n * Credential resolution, in order:\n * 0. The Zitadel-gated registry-auth BROKER \u2014 needs no AWS anything on this\n * machine. This is the path a brand-new developer takes.\n * 1. Existing AWS credentials in environment (CI/CD) \u2192 use directly\n * 2. Zitadel JWT from `mesh login` \u2192 AssumeRoleWithWebIdentity\n * 3. AWS SSO / current profile \u2192 use directly\n *\n * Paths 1\u20133 all shell out to the AWS CLI, so they require it to be installed\n * and credentialed. Path 0 requires only a Mesh account, which is the whole\n * point (design: registry-access-without-aws-sso).\n *\n * Usage:\n * mesh registry login \u2014 refresh token, ensure .npmrc\n * mesh registry login mesh.dev \u2014 broker first, then the AWS paths\n * mesh registry login --ci \u2014 CI mode (skip .npmrc creation)\n * mesh registry login --no-broker \u2014 skip the broker, force the AWS paths\n * mesh registry status \u2014 show current auth state\n */\n\nimport { Command } from \"commander\";\nimport { execFileSync } from \"child_process\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport { logError, logInfo, logSuccess, logWarn } from \"../utils/log.js\";\nimport { MeshCliError } from \"../utils/errors.js\";\nimport {\n awsConfigHasProfile,\n findUnscopedCodeArtifactRegistry,\n homeNpmrcPath,\n npmrcAuthKeyForEndpoint,\n probeRegistryToken,\n readAwsConfig,\n REGISTRY_CONTEXT,\n SSO_SESSION_SNIPPET,\n stripUnscopedCodeArtifactRegistry,\n upsertNpmrcLines,\n} from \"../utils/auth-preflight.js\";\nimport type { RegistryTokenState } from \"../utils/auth-preflight.js\";\nimport {\n fetchRegistryGrant,\n realGrantDeps,\n DERIVED_BROKER_TIMEOUT_MS,\n PUBLISHED_BROKER_TIMEOUT_MS,\n resolveDefaultBrokerContext,\n resolveRegistryBrokerSource,\n type RegistryBrokerFailure,\n type RegistryGrant,\n} from \"../utils/registry-broker.js\";\nimport { readCredentials } from \"./login.js\";\nimport { registerRegistryPublish } from \"./registry-publish.js\";\n\n// =============================================================================\n// Constants \u2014 platform CodeArtifact registry\n// =============================================================================\n\nconst CA_DOMAIN = \"mesh-platform\";\nconst CA_REPOSITORY = \"mesh-packages\";\nconst CA_NAMESPACE = \"@mesh-tech\";\nconst CA_REGION = \"us-east-2\";\n\n// Default registry role \u2014 tenants get read access via their deployer role,\n// but a dedicated read-only role can be configured here.\nconst DEFAULT_REGISTRY_ROLE: string | null = null;\n\n// =============================================================================\n// Helpers\n// =============================================================================\n\n/**\n * Get the CodeArtifact repository endpoint URL.\n */\nfunction getEndpoint(env?: Record<string, string>): string | null {\n try {\n const result = execFileSync(\"aws\", [\n \"codeartifact\", \"get-repository-endpoint\",\n \"--domain\", CA_DOMAIN,\n \"--repository\", CA_REPOSITORY,\n \"--format\", \"npm\",\n \"--region\", CA_REGION,\n \"--output\", \"text\",\n \"--query\", \"repositoryEndpoint\",\n ], {\n encoding: \"utf-8\",\n env: env ? { ...process.env, ...env } : undefined,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n return result.trim() || null;\n } catch {\n return null;\n }\n}\n\n/**\n * Run `aws codeartifact login` to set the auth token in ~/.npmrc.\n */\nexport function codeartifactLogin(env?: Record<string, string>): boolean {\n try {\n execFileSync(\"aws\", [\n \"codeartifact\", \"login\",\n \"--tool\", \"npm\",\n \"--domain\", CA_DOMAIN,\n \"--repository\", CA_REPOSITORY,\n \"--namespace\", CA_NAMESPACE,\n \"--region\", CA_REGION,\n ], {\n encoding: \"utf-8\",\n env: env ? { ...process.env, ...env } : undefined,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Parse a mesh context like \"mesh.dev\" into tenant + env.\n * Returns null if the context doesn't match the expected {tenant}.{env} pattern.\n *\n * (Mirrors login.ts's parseTenantEnv \u2014 kept local/minimal here to avoid\n * expanding login.ts's export surface for a single caller.)\n */\nfunction parseTenantEnv(context: string): { tenant: string; env: string } | null {\n const parts = context.split(\".\");\n if (parts.length !== 2 || !parts[0] || !parts[1]) return null;\n return { tenant: parts[0], env: parts[1] };\n}\n\n/**\n * Read the registry's SSM export (published by PackageRegistry, Task 2 of\n * MESH-2168) for a given tenant/env, e.g. /mesh-platform/mesh/dev/registry.\n *\n * Returns null on any failure (missing param, no AWS creds, malformed JSON) \u2014\n * callers treat a null publisherRoleArn as \"not configured\" and surface an\n * actionable error via resolvePublisherRoleArn.\n */\nasync function getRegistrySsmExport(\n tenant: string,\n env: string,\n): Promise<{ publisherRoleArn?: string } | null> {\n try {\n const { SSMClient, GetParameterCommand } = await import(\"@aws-sdk/client-ssm\");\n const region = process.env.AWS_REGION ?? process.env.AWS_DEFAULT_REGION ?? CA_REGION;\n const ssm = new SSMClient({ region });\n const ssmPath = `/mesh-platform/${tenant}/${env}/registry`;\n const response = await ssm.send(new GetParameterCommand({ Name: ssmPath }));\n if (!response.Parameter?.Value) return null;\n return JSON.parse(response.Parameter.Value) as { publisherRoleArn?: string };\n } catch {\n return null;\n }\n}\n\n/**\n * Resolve the publisher role ARN to assume for `--publish`.\n *\n * Precedence: explicit --role-arn flag wins, then the registry's SSM export\n * (publisherRoleArn, Task 2 of MESH-2168). Throws an actionable error if\n * neither is available \u2014 there's no safe default to fall back to since\n * publishing is an opt-in privileged path (DEFAULT_REGISTRY_ROLE stays null).\n */\nexport function resolvePublisherRoleArn({\n roleArnFlag,\n ssmArn,\n}: {\n roleArnFlag?: string;\n ssmArn?: string;\n}): string {\n const resolved = roleArnFlag || ssmArn;\n if (!resolved) {\n throw new Error(\n \"No publisher role: pass --role or ensure the registry stack exported publisherRoleArn (MESH-2168).\",\n );\n }\n return resolved;\n}\n\n/**\n * Assume an IAM role, return credential env vars.\n */\nfunction assumeRole(roleArn: string): Record<string, string> | null {\n try {\n const result = execFileSync(\"aws\", [\n \"sts\", \"assume-role\",\n \"--role-arn\", roleArn,\n \"--role-session-name\", \"mesh-registry\",\n \"--output\", \"json\",\n ], { encoding: \"utf-8\", stdio: [\"pipe\", \"pipe\", \"pipe\"] });\n\n const creds = JSON.parse(result).Credentials;\n return {\n AWS_ACCESS_KEY_ID: creds.AccessKeyId,\n AWS_SECRET_ACCESS_KEY: creds.SecretAccessKey,\n AWS_SESSION_TOKEN: creds.SessionToken,\n };\n } catch {\n return null;\n }\n}\n\n/**\n * Assume role via Zitadel JWT (AssumeRoleWithWebIdentity).\n */\nfunction assumeRoleWithWebIdentity(\n roleArn: string,\n idToken: string,\n sessionName: string,\n): Record<string, string> | null {\n try {\n const result = execFileSync(\"aws\", [\n \"sts\", \"assume-role-with-web-identity\",\n \"--role-arn\", roleArn,\n \"--web-identity-token\", idToken,\n \"--role-session-name\", sessionName,\n \"--output\", \"json\",\n ], { encoding: \"utf-8\", stdio: [\"pipe\", \"pipe\", \"pipe\"] });\n\n const creds = JSON.parse(result).Credentials;\n return {\n AWS_ACCESS_KEY_ID: creds.AccessKeyId,\n AWS_SECRET_ACCESS_KEY: creds.SecretAccessKey,\n AWS_SESSION_TOKEN: creds.SessionToken,\n };\n } catch {\n return null;\n }\n}\n\n/**\n * Resolve AWS credentials for registry access.\n *\n * Returns env var overrides (or empty object if current env is fine).\n */\nexport function resolveCredentials(\n context?: string,\n roleArn?: string,\n): Record<string, string> {\n // Path 1: Existing AWS credentials in environment\n if (process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SESSION_TOKEN) {\n logInfo(\"Using existing AWS credentials from environment\");\n return {};\n }\n\n // Path 2: Zitadel JWT \u2192 AssumeRoleWithWebIdentity\n if (context) {\n const meshCreds = readCredentials(context);\n if (meshCreds && new Date(meshCreds.expiresAt) > new Date()) {\n const targetRole = roleArn || DEFAULT_REGISTRY_ROLE;\n if (targetRole) {\n const sessionName = (meshCreds.email ?? \"mesh-registry\")\n .replace(/[^a-zA-Z0-9=,.@-]/g, \"_\")\n .slice(0, 64);\n logInfo(`Assuming registry role via Zitadel (${meshCreds.email ?? context})`);\n\n const creds = assumeRoleWithWebIdentity(targetRole, meshCreds.idToken, sessionName);\n if (creds) {\n logSuccess(\"Assumed registry role via Zitadel\");\n return creds;\n }\n logWarn(\"Zitadel JWT role assumption failed \u2014 falling back to AWS profile\");\n } else {\n logInfo(`Zitadel auth available (${meshCreds.email}) but no registry role configured \u2014 using AWS profile`);\n }\n } else if (meshCreds) {\n logWarn(`Zitadel token expired for ${context}. Run: mesh login ${context}`);\n } else {\n logWarn(`No Zitadel credentials for ${context}. Run: mesh login ${context}`);\n }\n }\n\n // Path 3: AssumeRole via current AWS session (if a role was specified)\n if (roleArn) {\n logInfo(`Assuming ${roleArn.split(\"/\").pop()} via AWS SSO`);\n const creds = assumeRole(roleArn);\n if (creds) {\n logSuccess(\"Assumed registry role via AWS SSO\");\n return creds;\n }\n logWarn(\"Role assumption failed \u2014 trying current credentials directly\");\n }\n\n // Path 4: Current AWS profile/credentials as-is\n logInfo(\"Using current AWS profile\");\n return {};\n}\n\n/**\n * Find project root by looking for pnpm-workspace.yaml, package.json, or .git\n * walking up from cwd.\n */\nfunction findProjectRoot(): string | null {\n let dir = process.cwd();\n while (true) {\n if (\n fs.existsSync(path.join(dir, \"pnpm-workspace.yaml\")) ||\n fs.existsSync(path.join(dir, \"pnpm-lock.yaml\")) ||\n fs.existsSync(path.join(dir, \"Pulumi.yaml\")) ||\n fs.existsSync(path.join(dir, \".npmrc\"))\n ) {\n return dir;\n }\n const parent = path.dirname(dir);\n if (parent === dir) return null;\n dir = parent;\n }\n}\n\n/**\n * Ensure project .npmrc has the @mesh-tech registry scope entry.\n * Creates the file if it doesn't exist. Doesn't touch auth tokens\n * (those live in ~/.npmrc via `aws codeartifact login`).\n */\nfunction ensureProjectNpmrc(endpoint: string): { created: boolean; updated: boolean; path: string } {\n const projectRoot = findProjectRoot() ?? process.cwd();\n const npmrcPath = path.join(projectRoot, \".npmrc\");\n const scopeLine = `${CA_NAMESPACE}:registry=${endpoint}`;\n\n if (!fs.existsSync(npmrcPath)) {\n fs.writeFileSync(npmrcPath, scopeLine + \"\\n\", \"utf-8\");\n return { created: true, updated: false, path: npmrcPath };\n }\n\n const content = fs.readFileSync(npmrcPath, \"utf-8\");\n\n // Check if scope already configured (with any endpoint)\n const scopeRegex = new RegExp(`^${CA_NAMESPACE.replace(\"/\", \"\\\\/\")}:registry=.+$`, \"m\");\n if (scopeRegex.test(content)) {\n // Check if it's the right endpoint\n if (content.includes(scopeLine)) {\n return { created: false, updated: false, path: npmrcPath };\n }\n // Update existing line\n const updated = content.replace(scopeRegex, scopeLine);\n fs.writeFileSync(npmrcPath, updated, \"utf-8\");\n return { created: false, updated: true, path: npmrcPath };\n }\n\n // Append scope line\n const separator = content.endsWith(\"\\n\") ? \"\" : \"\\n\";\n fs.writeFileSync(npmrcPath, content + separator + scopeLine + \"\\n\", \"utf-8\");\n return { created: false, updated: true, path: npmrcPath };\n}\n\n/**\n * Write a broker-issued grant into ~/.npmrc: the scoped registry line and the\n * endpoint's auth token, in exactly the shape `aws codeartifact login\n * --namespace @mesh-tech` would have written.\n *\n * Byte-compatibility with the AWS CLI's output is the requirement, not a nicety:\n * `mesh registry status`, the `mesh start` preflight and the dev doctor all\n * parse ~/.npmrc for that pair, and a machine that gets its token from the\n * broker has to look identical to one that got it from AWS.\n */\nexport function applyGrantToUserNpmrc(\n grant: RegistryGrant,\n npmrcPath = homeNpmrcPath(),\n): { path: string } {\n let existing = \"\";\n try {\n existing = fs.readFileSync(npmrcPath, \"utf-8\");\n } catch {\n // no ~/.npmrc yet \u2014 a clean laptop, which is the case this exists for\n }\n const content = upsertNpmrcLines(existing, [\n { key: `${grant.scope}:registry`, value: grant.endpoint },\n { key: `${npmrcAuthKeyForEndpoint(grant.endpoint)}:_authToken`, value: grant.authorizationToken },\n ]);\n fs.mkdirSync(path.dirname(npmrcPath), { recursive: true });\n fs.writeFileSync(npmrcPath, content, { mode: 0o600 });\n // `mode` only applies when writeFileSync CREATES the file, so an existing\n // 0644 ~/.npmrc would keep world-readable permissions on a 12h bearer token.\n // Parity with `aws codeartifact login` either way, but one line buys better.\n try {\n fs.chmodSync(npmrcPath, 0o600);\n } catch {\n // A read-only home or an exotic filesystem must not fail an otherwise-good login.\n }\n return { path: npmrcPath };\n}\n\n/**\n * Human-facing explanation of a failed broker attempt, plus whether the AWS\n * fallback chain is worth running.\n *\n * `not-authorized` is the one case we do NOT fall through on: the caller has a\n * working Mesh account that simply lacks the grant, and quietly trying AWS next\n * would either succeed (masking a missing grant with an AWS account we're\n * trying to stop requiring) or fail with an unrelated AWS error that buries the\n * real answer.\n */\nexport function describeBrokerFailure(failure: RegistryBrokerFailure, context?: string): {\n message: string;\n hint?: string;\n fatal: boolean;\n} {\n switch (failure.kind) {\n case \"no-broker\":\n return {\n message: \"No registry broker published for this context \u2014 using the AWS paths.\",\n fatal: false,\n };\n case \"no-session\":\n return {\n message: `No valid Mesh session${context ? ` for ${context}` : \"\"} \u2014 using the AWS paths.`,\n hint: context ? `mesh login ${context}` : \"mesh login <context>\",\n fatal: false,\n };\n case \"unauthenticated\":\n return {\n message: \"The registry broker rejected your Mesh session (expired or wrong audience).\",\n hint: context ? `mesh login ${context}` : \"mesh login <context>\",\n fatal: false,\n };\n case \"not-authorized\":\n return {\n // The whole message lives in the body, not in a `remediation.command`:\n // the answer here is \"ask a human for a role\", which is not a command\n // anyone can run, and rendering a URL behind \"\u2192 run:\" reads as one.\n message:\n `Your Mesh account${failure.email ? ` (${failure.email})` : \"\"} is not authorized to read ` +\n `${CA_NAMESPACE} packages.` +\n (failure.requiredRoles?.length\n ? `\\n Needs one of these Zitadel roles: ${failure.requiredRoles.join(\", \")}`\n : \"\") +\n (failure.requestUrl\n ? `\\n Request access: ${failure.requestUrl}`\n : \"\\n Ask a Mesh platform admin to grant your account registry access.\"),\n fatal: true,\n };\n case \"unavailable\":\n return {\n message: `Registry broker unavailable (${failure.detail}) \u2014 falling back to the AWS paths.`,\n fatal: false,\n };\n }\n}\n\n/**\n * Try the broker. Returns true when it produced a working ~/.npmrc, false when\n * the caller should continue to the AWS credential chain.\n *\n * Throws `MeshCliError` only for `not-authorized` \u2014 see describeBrokerFailure.\n */\nasync function tryBrokerLogin(\n contextArg: string | undefined,\n opts: RegistryLoginOptions,\n): Promise<RegistryGrant | null> {\n if (opts.broker === false) return null;\n\n let context = contextArg;\n if (!context) {\n // A context-less invocation used to skip the broker silently \u2014 which sent\n // anyone following a remediation that omits the context straight back to\n // the AWS chain. Resolve one when it is unambiguous; say so when it isn't.\n const resolved = resolveDefaultBrokerContext();\n if (\"context\" in resolved) {\n context = resolved.context;\n logInfo(`No context given \u2014 using the only one with a registry broker: ${context}`);\n } else if (resolved.reason === \"ambiguous\") {\n logInfo(\n `Skipping the registry broker: several contexts publish one (${resolved.candidates.join(\", \")}). ` +\n `Name it \u2014 e.g. \\`mesh registry login ${resolved.candidates[0]}\\`.`,\n );\n return null;\n } else {\n logInfo(\n \"Skipping the registry broker: no signed-in context publishes one. \" +\n `To use it: \\`mesh login ${REGISTRY_CONTEXT}\\`, then \\`mesh registry login ${REGISTRY_CONTEXT}\\`.`,\n );\n return null;\n }\n }\n\n const { url: brokerUrl, source } = resolveRegistryBrokerSource(context);\n if (!brokerUrl) {\n logInfo(\"No registry broker published for this context \u2014 using the AWS paths.\");\n return null;\n }\n\n logInfo(`Requesting a registry token from ${brokerUrl} (no AWS credentials needed)\u2026`);\n const result = await fetchRegistryGrant(context, brokerUrl, {\n ...realGrantDeps(),\n // A DERIVED url is a guess at a host that, for every platform not yet\n // redeployed, does not exist \u2014 and this wait also sits on the `mesh login`\n // path. Don't make everyone pay the published-broker timeout for a guess.\n timeoutMs: source === \"published\" ? PUBLISHED_BROKER_TIMEOUT_MS : DERIVED_BROKER_TIMEOUT_MS,\n });\n if (result.ok) return result.grant;\n\n const { message, hint, fatal } = describeBrokerFailure(result.failure, context);\n if (fatal) {\n throw new MeshCliError(message, hint ? { remediation: { command: hint } } : undefined);\n }\n logWarn(message);\n if (hint) logInfo(` Try: ${hint}`);\n return null;\n}\n\n/**\n * Whether this `mesh registry login` invocation may rewrite ~/.npmrc.\n *\n * The self-heal is a **laptop** fix. CI pipelines run the unscoped\n * `aws codeartifact login` DELIBERATELY \u2014 a host-scoped token is what lets\n * pnpm pull upstream-cached public packages through CodeArtifact \u2014 so in a\n * runner the \"hijack\" line is load-bearing and deleting it would break the\n * install we were asked not to touch. `--ci` is the one signal that says so.\n *\n * Extracted (and tested) rather than left inline because \"this changes no CI\n * behaviour\" is a promise about the code, not about the workflow files we\n * happen not to have edited.\n */\nexport function shouldRepairUserNpmrc(opts: Pick<RegistryLoginOptions, \"ci\">): boolean {\n return !opts.ci;\n}\n\n/**\n * Repair a hijacked ~/.npmrc: remove an unscoped `registry=<codeartifact>`\n * line if one is present, after taking a timestamped backup.\n *\n * `aws codeartifact login` run WITHOUT `--namespace @mesh-tech` writes that\n * line, and nothing in this CLI used to remove it \u2014 so one bare login made\n * CodeArtifact the default registry forever, and every public `npm install`\n * started failing with E401 12 hours later when the token expired. We write\n * the correct (scoped) state; this is the missing repair of the wrong state.\n *\n * Never throws \u2014 a repair failure must not fail an otherwise-good login.\n */\nexport function repairUnscopedRegistry(npmrcPath = homeNpmrcPath()): {\n removed: string | null;\n backupPath?: string;\n error?: string;\n} {\n let original: string;\n try {\n original = fs.readFileSync(npmrcPath, \"utf-8\");\n } catch {\n return { removed: null }; // no ~/.npmrc \u2192 nothing to repair\n }\n\n const { content, removed } = stripUnscopedCodeArtifactRegistry(original);\n if (!removed) return { removed: null };\n\n const backupPath = `${npmrcPath}.bak-${new Date().toISOString().replace(/[:.]/g, \"-\")}`;\n try {\n fs.writeFileSync(backupPath, original, \"utf-8\");\n fs.writeFileSync(npmrcPath, content, \"utf-8\");\n } catch (err) {\n return { removed: null, error: err instanceof Error ? err.message : String(err) };\n }\n return { removed, backupPath };\n}\n\n/**\n * Check that ~/.npmrc is in a working state for @mesh-tech installs: a\n * CodeArtifact token that the registry actually accepts, and no unscoped\n * `registry=` hijacking public npm.\n *\n * A substring match on the file (the old check) reported \"valid\" for an\n * expired token AND for a hijacked default registry \u2014 precisely the state\n * `mesh registry status` exists to catch.\n */\nexport interface RegistryTokenCheck {\n /** Token accepted by the registry AND no unscoped `registry=` hijack. */\n valid: boolean;\n /** The probe's verdict, so callers can tell \"broken\" from \"unverifiable\". */\n state: RegistryTokenState;\n endpoint?: string;\n reason?: string;\n hijackLine?: string;\n}\n\nexport async function checkExistingToken(): Promise<RegistryTokenCheck> {\n const npmrcPath = homeNpmrcPath();\n if (!fs.existsSync(npmrcPath)) return { valid: false, state: \"missing\", reason: \"no ~/.npmrc\" };\n\n const hijackLine = findUnscopedCodeArtifactRegistry(\n fs.readFileSync(npmrcPath, \"utf-8\"),\n ) ?? undefined;\n\n const probe = await probeRegistryToken({ npmrcPath });\n if (probe.state === \"missing\") {\n return { valid: false, state: probe.state, reason: \"no CodeArtifact token in ~/.npmrc\", hijackLine };\n }\n if (probe.state === \"expired\") {\n return {\n valid: false,\n state: probe.state,\n reason: probe.detail ?? \"the CodeArtifact token is expired\",\n hijackLine,\n };\n }\n if (probe.state === \"unreachable\") {\n return {\n valid: false,\n state: probe.state,\n reason: `could not reach the registry to verify the token (${probe.detail ?? \"unknown error\"})`,\n hijackLine,\n };\n }\n\n // Token works \u2014 a hijacked default registry still breaks public installs.\n if (hijackLine) {\n return { valid: false, state: probe.state, reason: \"unscoped CodeArtifact registry\", hijackLine };\n }\n\n return { valid: true, state: probe.state, endpoint: getEndpoint() ?? undefined };\n}\n\n/**\n * `mesh registry status` \u2014 returns the process exit code instead of calling\n * `process.exit`, so the \"broken\" vs \"unverifiable\" distinction is testable.\n *\n * Exit 1 is for faults the user can act on right now: a missing or expired\n * token, or an unscoped CodeArtifact `registry=` line (locally detectable, and\n * broken regardless of the network). An **unreachable** registry is neither \u2014\n * it warns and exits 0, because the remediation we'd print (`mesh registry\n * login`) cannot work offline either, and the same rule already governs the\n * `mesh init` doctor.\n */\nexport async function runRegistryStatus(opts?: {\n /** Test seam \u2014 defaults to the real ~/.npmrc + live registry probe. */\n check?: () => Promise<RegistryTokenCheck>;\n}): Promise<number> {\n const { valid, state, endpoint, reason, hijackLine } = await (opts?.check ?? checkExistingToken)();\n\n if (hijackLine) {\n logWarn(\n \"~/.npmrc sets CodeArtifact as your DEFAULT registry \u2014 every public npm install goes \" +\n \"through it and will 401 when the 12h token expires:\",\n );\n logInfo(` ${hijackLine.trim()}`);\n logInfo(\"Fix: mesh registry login # removes it (backup taken) and keeps @mesh-tech scoped\");\n }\n\n // A network fault is not an auth fault. Any *other* invalid state is.\n const unverifiable = state === \"unreachable\" && !hijackLine;\n\n if (!valid && !unverifiable) {\n logWarn(`Registry auth is not usable${reason ? ` \u2014 ${reason}` : \"\"}. Run: mesh registry login`);\n return 1;\n }\n\n if (unverifiable) {\n logWarn(`Could not verify the CodeArtifact token in ~/.npmrc \u2014 ${reason}.`);\n logInfo(\"Nothing to fix from here; retry when the registry is reachable.\");\n } else {\n logSuccess(\"CodeArtifact token in ~/.npmrc is valid\");\n if (endpoint) {\n logInfo(`Endpoint: ${endpoint}`);\n }\n }\n\n // Project .npmrc \u2014 worth reporting even when the token couldn't be verified.\n const projectRoot = findProjectRoot();\n if (projectRoot) {\n const npmrcPath = path.join(projectRoot, \".npmrc\");\n if (fs.existsSync(npmrcPath)) {\n const content = fs.readFileSync(npmrcPath, \"utf-8\");\n if (content.includes(`${CA_NAMESPACE}:registry=`)) {\n logSuccess(`Project .npmrc configured (${npmrcPath})`);\n } else {\n logWarn(`Project .npmrc exists but missing ${CA_NAMESPACE} scope (${npmrcPath})`);\n logInfo(\"Run: mesh registry login\");\n }\n } else {\n logWarn(`No .npmrc in project root (${projectRoot})`);\n logInfo(\"Run: mesh registry login\");\n }\n }\n\n return 0;\n}\n\n// =============================================================================\n// Commands\n// =============================================================================\n\n/**\n * Ensure the named AWS SSO profile has a live session \u2014 trigger the\n * interactive `aws sso login` (browser) when it's stale.\n *\n * Guardrails (MESH-2479): a missing profile fails fast with the exact\n * `aws configure` setup instead of an opaque CLI error, and the identity\n * probes are time-bounded so a wedged AWS CLI can't hang this silently.\n */\nfunction ensureSsoProfile(profile: string): void {\n const awsConfig = readAwsConfig();\n if (awsConfig && !awsConfigHasProfile(awsConfig, profile)) {\n throw new MeshCliError(\n `AWS profile '${profile}' is not defined in ~/.aws/config \u2014 \\`aws sso login --profile ${profile}\\` cannot work until it exists.\\n\\n` +\n \"If you only need to INSTALL @mesh-tech packages, drop --profile: `mesh login <context>` then\\n\" +\n \"`mesh registry login <context>` uses the Zitadel-gated broker and needs no AWS account at all.\\n\\n\" +\n `If you DEPLOY and genuinely need this profile \u2014 one-time setup: \\`aws configure sso --profile ${profile}\\`,\\n` +\n `or add the session + profile by hand:\\n` +\n `${SSO_SESSION_SNIPPET}\\n[profile ${profile}]\\nsso_session = mesh\\nsso_account_id = <account id>\\nsso_role_name = <role>\\nregion = us-east-2`,\n { remediation: { command: `aws configure sso --profile ${profile}` } },\n );\n }\n const probe = () =>\n execFileSync(\"aws\", [\"sts\", \"get-caller-identity\", \"--profile\", profile], {\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n timeout: 20_000,\n });\n try {\n probe();\n logInfo(`AWS SSO session for profile '${profile}' is live`);\n return;\n } catch {\n logInfo(`AWS SSO session for profile '${profile}' is stale \u2014 opening browser login\u2026`);\n }\n execFileSync(\"aws\", [\"sso\", \"login\", \"--profile\", profile], { stdio: \"inherit\" });\n try {\n probe();\n } catch (err) {\n throw new MeshCliError(\n `AWS SSO login for profile '${profile}' completed but the session still fails an identity check.`,\n {\n remediation: { command: `aws sts get-caller-identity --profile ${profile} # see the underlying error` },\n cause: err,\n },\n );\n }\n logSuccess(`AWS SSO session refreshed (profile '${profile}')`);\n}\n\nexport interface RegistryLoginOptions {\n role?: string;\n ci?: boolean;\n skipNpmrc?: boolean;\n /** AWS SSO profile (e.g. mesh-dev) \u2014 auto-runs `aws sso login` when stale */\n profile?: string;\n /** Assume the registry's publisher role (from --role or the registry's SSM export) */\n publish?: boolean;\n /**\n * Try the Zitadel-gated registry broker before the AWS paths. Default true.\n * `--no-broker` forces the AWS chain (commander sets this to false).\n */\n broker?: boolean;\n}\n\n/**\n * The full registry-auth sequence (CodeArtifact token \u2192 ~/.npmrc \u2192 project\n * .npmrc). Shared by `mesh registry login` and `mesh login <context>` (F2:\n * login absorbs registry auth).\n */\nexport async function runRegistryLogin(context: string | undefined, opts: RegistryLoginOptions): Promise<void> {\n // --publish is the opt-in privileged path: resolve the publisher role\n // (explicit --role flag wins, else the registry's SSM export) and feed\n // it through the same Zitadel role-assumption path as the reader flow.\n let roleArn = opts.role;\n if (opts.publish) {\n let ssmArn: string | undefined;\n if (!opts.role) {\n if (!context) {\n logError(\n '`--publish` requires a platform context, e.g. \"mesh registry login mesh.dev --publish\".',\n );\n process.exit(1);\n }\n const parsed = parseTenantEnv(context);\n if (!parsed) {\n logError(`Could not parse tenant/env from context \"${context}\" (expected \"<tenant>.<env>\").`);\n process.exit(1);\n }\n const registryExport = await getRegistrySsmExport(parsed.tenant, parsed.env);\n ssmArn = registryExport?.publisherRoleArn;\n }\n try {\n roleArn = resolvePublisherRoleArn({ roleArnFlag: opts.role, ssmArn });\n } catch (err) {\n logError((err as Error).message);\n process.exit(1);\n }\n logInfo(`Publisher role resolved: ${roleArn}`);\n }\n\n // Step 0: the broker. Tried FIRST for the read path, because it is the only\n // one that works on a machine with no AWS account, no AWS CLI and no\n // ~/.aws/config \u2014 the machine this whole feature exists for.\n //\n // Skipped for --publish (a privileged write path that deliberately goes\n // through an assumed IAM role) and for --profile (an explicit \"use this AWS\n // profile\" instruction we must not silently override).\n if (!opts.publish && !opts.profile) {\n const grant = await tryBrokerLogin(context, opts);\n if (grant) {\n const { path: npmrcPath } = applyGrantToUserNpmrc(grant);\n logSuccess(\n `Registry token issued by the Mesh broker \u2192 ${npmrcPath}` +\n (grant.expiresAt ? ` (expires ${grant.expiresAt})` : \"\"),\n );\n\n // Same hijack repair as the AWS path \u2014 an unscoped `registry=` line left\n // by a past bare `aws codeartifact login` breaks public installs\n // regardless of where today's token came from.\n if (shouldRepairUserNpmrc(opts)) {\n const repair = repairUnscopedRegistry();\n if (repair.removed) {\n logWarn(\n \"Removed an unscoped CodeArtifact `registry=` from ~/.npmrc \u2014 it routed ALL npm traffic \" +\n \"(public packages included) through CodeArtifact.\",\n );\n logInfo(` removed: ${repair.removed.trim()}`);\n if (repair.backupPath) logInfo(` backup: ${repair.backupPath}`);\n }\n }\n\n if (!opts.ci && !opts.skipNpmrc) {\n const result = ensureProjectNpmrc(grant.endpoint);\n if (result.created) {\n logSuccess(`Created ${result.path} with ${CA_NAMESPACE} registry scope`);\n } else if (result.updated) {\n logSuccess(`Updated ${CA_NAMESPACE} registry in ${result.path}`);\n } else {\n logInfo(`${result.path} already configured`);\n }\n }\n\n logSuccess(`Ready \u2014 run pnpm install to fetch ${CA_NAMESPACE} packages`);\n return;\n }\n }\n\n let env: Record<string, string> | undefined;\n if (opts.profile) {\n // Jawad's flow, one command: live SSO session + profile-scoped token.\n // Static creds in the environment would override the profile \u2014 drop them.\n ensureSsoProfile(opts.profile);\n env = { ...process.env, AWS_PROFILE: opts.profile } as Record<string, string>;\n for (const key of [\"AWS_ACCESS_KEY_ID\", \"AWS_SECRET_ACCESS_KEY\", \"AWS_SESSION_TOKEN\"]) {\n delete env[key];\n }\n } else {\n const awsCreds = resolveCredentials(context, roleArn);\n env = Object.keys(awsCreds).length > 0\n ? ({ ...process.env, ...awsCreds } as Record<string, string>)\n : undefined;\n }\n\n // Step 1: Run `aws codeartifact login` (sets token in ~/.npmrc)\n logInfo(\"Authenticating with CodeArtifact...\");\n if (!codeartifactLogin(env)) {\n logError(\n \"CodeArtifact login failed.\\n\\n\" +\n \"You do NOT need an AWS account to install @mesh-tech packages. The supported path is:\\n\" +\n ` mesh login ${context ?? \"<context>\"} # browser \u2192 Zitadel; then re-run this command\\n\\n` +\n \"This machine fell through to the AWS path, which means one of: the platform publishes no\\n\" +\n \"registry broker yet, your Mesh account is not signed in, or the broker was unreachable \u2014\\n\" +\n \"the warning above says which.\\n\\n\" +\n \"AWS SSO is only needed if you DEPLOY (mesh deploy):\\n\" +\n \" mesh registry login --profile mesh-dev # auto-runs `aws sso login`\"\n );\n process.exit(1);\n }\n logSuccess(\"CodeArtifact token refreshed (valid for 12 hours)\");\n\n // Step 1b: Repair a hijacked ~/.npmrc. We always write the SCOPED form\n // above (--namespace @mesh-tech), but a bare `aws codeartifact login` run\n // at any point in the past leaves an unscoped `registry=` line that we\n // never removed \u2014 so it survived every subsequent correct login.\n //\n // Laptops only \u2014 see shouldRepairUserNpmrc: in `--ci` the unscoped line is\n // doing its job and a \"repair\" would break the runner's install.\n if (shouldRepairUserNpmrc(opts)) {\n const repair = repairUnscopedRegistry();\n if (repair.removed) {\n logWarn(\n \"Removed an unscoped CodeArtifact `registry=` from ~/.npmrc \u2014 it routed ALL npm traffic \" +\n \"(public packages included) through CodeArtifact, so every install broke when the 12h token expired. \" +\n `${CA_NAMESPACE} stays scoped; public packages now go to npmjs.`,\n );\n logInfo(` removed: ${repair.removed.trim()}`);\n if (repair.backupPath) logInfo(` backup: ${repair.backupPath}`);\n } else if (repair.error) {\n logWarn(`Could not repair ~/.npmrc (${repair.error}) \u2014 remove any unscoped \\`registry=\\` line by hand.`);\n }\n }\n\n // Step 2: Get endpoint URL\n const endpoint = getEndpoint(env);\n if (!endpoint) {\n logWarn(\"Could not retrieve registry endpoint \u2014 .npmrc scope not configured\");\n logInfo(\"You may need to manually add to .npmrc:\");\n logInfo(` ${CA_NAMESPACE}:registry=https://mesh-platform-<ACCOUNT>.d.codeartifact.${CA_REGION}.amazonaws.com/npm/${CA_REPOSITORY}/`);\n return;\n }\n\n // Step 3: Ensure project .npmrc (unless --ci or --skip-npmrc)\n if (!opts.ci && !opts.skipNpmrc) {\n const result = ensureProjectNpmrc(endpoint);\n if (result.created) {\n logSuccess(`Created ${result.path} with ${CA_NAMESPACE} registry scope`);\n } else if (result.updated) {\n logSuccess(`Updated ${CA_NAMESPACE} registry in ${result.path}`);\n } else {\n logInfo(`${result.path} already configured`);\n }\n }\n\n logSuccess(`Ready \u2014 run pnpm install to fetch ${CA_NAMESPACE} packages`);\n}\n\nexport function registerRegistryCommands(program: Command): void {\n const registry = program\n .command(\"registry\")\n .description(\"Manage npm registry auth for @mesh-tech packages\");\n\n registry\n .command(\"login\")\n .description(\"Authenticate with CodeArtifact and configure .npmrc\")\n .argument(\"[context]\", 'Platform context for Zitadel auth (e.g., \"mesh.dev\")')\n .option(\"--role <arn>\", \"IAM role ARN for registry access\")\n .option(\"--ci\", \"CI mode \u2014 refresh token only, skip project .npmrc setup\")\n .option(\"--skip-npmrc\", \"Skip project .npmrc setup\")\n .option(\"--profile <name>\", \"AWS SSO profile (e.g. mesh-dev) \u2014 auto-runs `aws sso login` when the session is stale\")\n .option(\n \"--no-broker\",\n \"Skip the Zitadel-gated registry broker and go straight to the AWS credential chain\",\n )\n .option(\n \"--publish\",\n \"Assume the registry's publisher role for CodeArtifact publish access \" +\n \"(opt-in privileged path \u2014 resolves publisherRoleArn from the registry's SSM export unless --role is given)\",\n )\n .action(async (context: string | undefined, opts: RegistryLoginOptions) => {\n await runRegistryLogin(context, opts);\n });\n\n registry\n .command(\"status\")\n .description(\"Check current registry authentication status\")\n .action(async () => {\n const code = await runRegistryStatus();\n if (code !== 0) process.exit(code);\n });\n\n registerRegistryPublish(registry);\n}\n", "/**\n * mesh login \u2014 Authenticate with Zitadel via OIDC PKCE or Device Code flow.\n *\n * Opens browser to Zitadel (PKCE) or prints a code to enter in the browser\n * (Device Code). Exchanges for tokens and caches at ~/.config/mesh/credentials.json.\n *\n * Config is read from ~/.config/mesh/config.json, keyed by context\n * (e.g., \"mesh.dev\"). After deploying the platform, copy the CLI client ID\n * from the Pulumi stack output into the config file.\n *\n * In containers/SSH sessions, device code flow is used automatically.\n *\n * Usage:\n * mesh login mesh.dev \u2014 authenticate to mesh dev\n * mesh login mesh.dev --device \u2014 force device code flow\n * mesh login mesh.dev --status \u2014 show current auth state (Zitadel session if\n * there is one, otherwise whatever the AWS\n * credential chain resolves \u2014 SSO or key pair)\n * mesh logout mesh.dev \u2014 clear cached credentials\n */\n\nimport { Command } from \"commander\";\nimport * as http from \"http\";\nimport * as crypto from \"crypto\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport { execFileSync } from \"child_process\";\nimport { logError, logInfo, logSuccess, logWarn } from \"../utils/log.js\";\nimport {\n assumeRoleCredentials,\n assumeRoleWithWebIdentity,\n describeAssumeFailure,\n probeAwsIdentity,\n renderCredentialProcessProfile,\n tokenIssuer,\n resolveStableMeshBin,\n selectRoleForCaller,\n toCredentialProcessJson,\n upsertManagedAwsConfigSection,\n type AwsIdentity,\n} from \"../utils/aws-auth.js\";\n\nimport { firstPartyDomainFor } from \"../utils/first-party-contexts.js\";\nimport { tailscaleBackendState } from \"./vpn/index.js\";\n// =============================================================================\n// Paths (XDG Base Directory Specification)\n// =============================================================================\n\nconst CONFIG_DIR = path.join(\n process.env.XDG_CONFIG_HOME ?? path.join(process.env.HOME ?? \"~\", \".config\"),\n \"mesh\"\n);\nconst CONFIG_FILE = path.join(CONFIG_DIR, \"config.json\");\nconst CREDENTIALS_FILE = path.join(CONFIG_DIR, \"credentials.json\");\n\nconst REDIRECT_PORT = 9876;\nconst REDIRECT_URI = `http://localhost:${REDIRECT_PORT}/callback`;\nconst SCOPES =\n \"openid email profile offline_access urn:zitadel:iam:org:project:id:zitadel:aud\";\n\n// =============================================================================\n// Config & Credentials\n// =============================================================================\n\ninterface ContextConfig {\n issuer: string;\n clientId: string;\n /**\n * Default IAM role ARN to assume for this context when no `--role` flag\n * and no `MESH_AWS_ROLE` env var are provided. Set automatically the first\n * time `mesh login ... --export --role <arn>` runs against this context;\n * subsequent `--role` values overwrite it.\n */\n defaultRole?: string;\n /**\n * Optional admin-tier IAM role for this context. When set,\n * `selectRoleForCaller` upgrades to this ARN automatically when the\n * caller's Zitadel JWT carries the admin role (default\n * `mesh.platform:admin`; override via adminClaimRoles).\n */\n adminRole?: string;\n /**\n * Zitadel role names that map a caller to `adminRole`. Defaults to\n * `[\"mesh.platform:admin\"]` when omitted.\n */\n adminClaimRoles?: string[];\n /** Headscale login server (published by the platform). */\n vpn?: string;\n /** Zero-touch pre-auth broker URL (published by the platform). */\n vpnJoinBroker?: string;\n /**\n * Zitadel-gated registry-auth broker URL (published by the platform).\n * With this set, `mesh registry login` needs no AWS credentials at all.\n */\n registryBroker?: string;\n}\n\ninterface CachedCredentials {\n idToken: string;\n accessToken: string;\n refreshToken?: string;\n expiresAt: string; // ISO date\n email?: string;\n sub?: string;\n}\n\ntype ConfigFile = Record<string, ContextConfig>;\ntype CredentialsFile = Record<string, CachedCredentials>;\n\nfunction readConfig(): ConfigFile {\n if (!fs.existsSync(CONFIG_FILE)) return {};\n try {\n return JSON.parse(fs.readFileSync(CONFIG_FILE, \"utf-8\"));\n } catch {\n return {};\n }\n}\n\nexport function writeContextConfig(context: string, config: ContextConfig): void {\n const existing = readConfig();\n existing[context] = config;\n fs.mkdirSync(CONFIG_DIR, { recursive: true });\n fs.writeFileSync(CONFIG_FILE, JSON.stringify(existing, null, 2));\n}\n\nfunction getContextConfig(context: string): ContextConfig | null {\n const config = readConfig();\n return config[context] ?? null;\n}\n\n/**\n * Parse a mesh context like \"mesh.dev\" or \"acme.uat\" into tenant + env.\n * Returns null if the context doesn't match the expected {tenant}.{env} pattern.\n */\nfunction parseTenantEnv(context: string): { tenant: string; env: string } | null {\n const parts = context.split(\".\");\n if (parts.length !== 2 || !parts[0] || !parts[1]) return null;\n return { tenant: parts[0], env: parts[1] };\n}\n\n/**\n * Attempt auto-discovery of platform config from SSM Parameter Store.\n *\n * Uses ambient AWS credentials to read the zitadel config export at\n * /mesh-platform/{tenant}/{env}/platform/zitadel. This is the preferred\n * discovery path for users who already have AWS SSO access to the platform.\n *\n * Returns null if AWS credentials are unavailable, SSM read fails, or the\n * parameter doesn't contain the required fields.\n */\nasync function discoverConfigFromSsm(context: string): Promise<ContextConfig | null> {\n const parsed = parseTenantEnv(context);\n if (!parsed) return null;\n\n const { tenant, env } = parsed;\n const ssmPath = `/mesh-platform/${tenant}/${env}/platform/zitadel`;\n logInfo(`Attempting SSM discovery from ${ssmPath}...`);\n\n try {\n const { SSMClient, GetParameterCommand } = await import(\"@aws-sdk/client-ssm\");\n const region = process.env.AWS_REGION ?? process.env.AWS_DEFAULT_REGION ?? \"us-east-2\";\n const ssm = new SSMClient({ region });\n\n const resp = await ssm.send(new GetParameterCommand({ Name: ssmPath }));\n const raw = resp.Parameter?.Value;\n if (!raw) {\n logWarn(`SSM parameter ${ssmPath} has no value`);\n return null;\n }\n\n const data = JSON.parse(raw) as Record<string, unknown>;\n const issuer = data.endpoint;\n const clientId = data.cliClientId;\n\n if (typeof issuer !== \"string\" || !issuer) {\n logWarn(\"SSM zitadel entry missing 'endpoint' field\");\n return null;\n }\n if (typeof clientId !== \"string\" || !clientId) {\n logWarn(\n \"SSM zitadel entry missing 'cliClientId' field.\\n\" +\n \" The platform needs to be deployed with an updated ZitadelPlatformIdentity\\n\" +\n \" that exports cliClientId. Until then, contact your platform admin.\"\n );\n return null;\n }\n\n const config: ContextConfig = { issuer, clientId };\n if (typeof data.vpn === \"string\") config.vpn = data.vpn;\n if (typeof data.vpnJoinBroker === \"string\") config.vpnJoinBroker = data.vpnJoinBroker;\n if (typeof data.registryBroker === \"string\") config.registryBroker = data.registryBroker;\n writeContextConfig(context, config);\n logSuccess(`Discovered platform configuration for ${context} via SSM`);\n return config;\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n if (message.includes(\"ExpiredToken\") || message.includes(\"credentials\")) {\n logWarn(`SSM discovery failed: AWS credentials expired or unavailable.`);\n // Do NOT send someone to `aws sso login` when an anonymous path is about\n // to be tried \u2014 on the install journey that is the exact misdirection\n // this feature removes. Only mention AWS when nothing else can resolve.\n if (firstPartyDomainFor(context) || context.split(\".\").length - 1 >= 2) {\n logInfo(` Falling back to anonymous HTTPS discovery \u2014 no AWS needed.`);\n } else {\n logInfo(` If you have an AWS account: aws sso login --profile <profile>`);\n logInfo(` Otherwise use the platform's full domain, e.g. mesh login dev.<tenant>.meshtech.io`);\n }\n } else if (message.includes(\"ParameterNotFound\")) {\n logWarn(`SSM parameter not found: ${ssmPath}`);\n logInfo(\" This platform context may not be deployed.\");\n } else {\n logWarn(`SSM discovery failed: ${message}`);\n }\n return null;\n }\n}\n\n/**\n * Attempt auto-discovery of platform config from a well-known endpoint.\n * Returns null if discovery fails for any reason (network, timeout, bad data).\n *\n * `contextKey` is the name the resulting config is CACHED under, which is not\n * always the domain probed: a pinned first-party alias (`mesh.dev`) probes\n * `dev.platform.meshtech.io` but must be cached under `mesh.dev`, or the very\n * next command re-runs discovery and the alias buys nothing.\n */\nasync function discoverConfig(\n domain: string,\n contextKey: string = domain,\n): Promise<ContextConfig | null> {\n const url = `https://cli.${domain}/.well-known/mesh.json`;\n logInfo(`Attempting discovery from ${url}...`);\n\n try {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 5000);\n const resp = await fetch(url, { signal: controller.signal });\n clearTimeout(timeout);\n\n if (!resp.ok) {\n logWarn(`Discovery endpoint returned ${resp.status}`);\n return null;\n }\n\n const data = (await resp.json()) as Record<string, unknown>;\n const issuer = data.issuer;\n const clientId = data.clientId;\n\n if (typeof issuer !== \"string\" || !issuer || typeof clientId !== \"string\" || !clientId) {\n logWarn(\"Discovery endpoint returned invalid config (missing issuer or clientId)\");\n return null;\n }\n\n const config: ContextConfig = { issuer, clientId };\n if (typeof data.vpn === \"string\") config.vpn = data.vpn;\n if (typeof data.vpnJoinBroker === \"string\") config.vpnJoinBroker = data.vpnJoinBroker;\n if (typeof data.registryBroker === \"string\") config.registryBroker = data.registryBroker;\n writeContextConfig(contextKey, config);\n logSuccess(`Discovered platform configuration for ${contextKey}`);\n return config;\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n if (message.includes(\"abort\")) {\n logWarn(\"Discovery timed out\");\n } else {\n logWarn(`Discovery failed: ${message}`);\n }\n return null;\n }\n}\nfunction readAllCredentials(): CredentialsFile {\n if (!fs.existsSync(CREDENTIALS_FILE)) return {};\n try {\n return JSON.parse(fs.readFileSync(CREDENTIALS_FILE, \"utf-8\"));\n } catch {\n return {};\n }\n}\n\nfunction readCredentials(context: string): CachedCredentials | null {\n return readAllCredentials()[context] ?? null;\n}\n\n/** Monotonic counter mixed into temp-file names alongside the pid, so two\n * writes from the same process in the same tick (e.g. rapid retries) never\n * collide on a temp path. */\nlet atomicWriteCounter = 0;\n\n/**\n * Write `data` to `path` atomically: write to a temp file in the SAME\n * directory as `path` (so the subsequent rename is same-filesystem, hence\n * atomic), then `fs.renameSync` it into place. This guarantees concurrent\n * readers (e.g. other `credential_process` invocations racing a refresh)\n * only ever observe a fully-written file \u2014 never a truncated one from an\n * interleaved `fs.writeFileSync`.\n *\n * On any error, best-effort removes the temp file before rethrowing.\n *\n * Exported for unit testing.\n */\nexport function atomicWriteFileSync(path: string, data: string, mode: number): void {\n const tmpPath = `${path}.${process.pid}.${atomicWriteCounter++}.tmp`;\n try {\n fs.writeFileSync(tmpPath, data, { mode });\n fs.renameSync(tmpPath, path);\n } catch (err) {\n try {\n fs.unlinkSync(tmpPath);\n } catch {\n // best-effort cleanup \u2014 ignore (e.g. write itself never created the file)\n }\n throw err;\n }\n}\n\nfunction writeCredentials(context: string, creds: CachedCredentials): void {\n fs.mkdirSync(CONFIG_DIR, { recursive: true });\n const all = readAllCredentials();\n all[context] = creds;\n atomicWriteFileSync(CREDENTIALS_FILE, JSON.stringify(all, null, 2), 0o600);\n}\n\nfunction clearCredentials(context: string): void {\n const all = readAllCredentials();\n delete all[context];\n fs.mkdirSync(CONFIG_DIR, { recursive: true });\n fs.writeFileSync(CREDENTIALS_FILE, JSON.stringify(all, null, 2), {\n mode: 0o600,\n });\n}\n\n// =============================================================================\n// OIDC Helpers\n// =============================================================================\n\ninterface TokenResponse {\n access_token: string;\n id_token: string;\n refresh_token?: string;\n token_type: string;\n expires_in: number;\n}\n\nfunction base64url(buffer: Buffer): string {\n return buffer.toString(\"base64url\");\n}\n\nfunction generateCodeVerifier(): string {\n return base64url(crypto.randomBytes(32));\n}\n\nfunction generateCodeChallenge(verifier: string): string {\n return base64url(crypto.createHash(\"sha256\").update(verifier).digest());\n}\n\nfunction decodeJwtPayload(token: string): Record<string, unknown> {\n const parts = token.split(\".\");\n if (parts.length !== 3) throw new Error(\"Invalid JWT\");\n return JSON.parse(Buffer.from(parts[1]!, \"base64url\").toString());\n}\n\nasync function exchangeCode(\n issuer: string,\n clientId: string,\n code: string,\n codeVerifier: string\n): Promise<TokenResponse> {\n const body = new URLSearchParams({\n grant_type: \"authorization_code\",\n code,\n redirect_uri: REDIRECT_URI,\n client_id: clientId,\n code_verifier: codeVerifier,\n });\n\n const resp = await fetch(`${issuer}/oauth/v2/token`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: body.toString(),\n });\n\n if (!resp.ok) {\n const text = await resp.text();\n throw new Error(`Token exchange failed (${resp.status}): ${text}`);\n }\n\n return resp.json() as Promise<TokenResponse>;\n}\n\nasync function refreshTokens(\n issuer: string,\n clientId: string,\n refreshToken: string\n): Promise<TokenResponse> {\n const body = new URLSearchParams({\n grant_type: \"refresh_token\",\n refresh_token: refreshToken,\n client_id: clientId,\n });\n\n const resp = await fetch(`${issuer}/oauth/v2/token`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: body.toString(),\n });\n\n if (!resp.ok) {\n throw new Error(`Token refresh failed (${resp.status})`);\n }\n\n return resp.json() as Promise<TokenResponse>;\n}\n\n// =============================================================================\n// Login Flow\n// =============================================================================\n\nfunction login(context: string, config: ContextConfig): Promise<void> {\n return new Promise((resolve, reject) => {\n const codeVerifier = generateCodeVerifier();\n const codeChallenge = generateCodeChallenge(codeVerifier);\n const state = base64url(crypto.randomBytes(16));\n\n const authUrl = new URL(`${config.issuer}/oauth/v2/authorize`);\n authUrl.searchParams.set(\"client_id\", config.clientId);\n authUrl.searchParams.set(\"redirect_uri\", REDIRECT_URI);\n authUrl.searchParams.set(\"response_type\", \"code\");\n authUrl.searchParams.set(\"scope\", SCOPES);\n authUrl.searchParams.set(\"code_challenge\", codeChallenge);\n authUrl.searchParams.set(\"code_challenge_method\", \"S256\");\n authUrl.searchParams.set(\"state\", state);\n\n // Tracked teardown \u2014 without this `mesh login` hangs after success\n // because (a) the 2-minute timeout below kept the event loop alive,\n // and (b) the browser's keep-alive socket survived `server.close()`\n // (which only stops new connections, not active ones).\n let timeoutId: NodeJS.Timeout | undefined;\n\n const server = http.createServer(async (req, res) => {\n try {\n const url = new URL(req.url ?? \"/\", `http://localhost:${REDIRECT_PORT}`);\n if (url.pathname !== \"/callback\") {\n res.writeHead(404);\n res.end(\"Not found\");\n return;\n }\n\n const error = url.searchParams.get(\"error\");\n if (error) {\n const desc =\n url.searchParams.get(\"error_description\") ?? error;\n const safeDesc = desc.replace(/&/g, \"&amp;\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\").replace(/\"/g, \"&quot;\");\n res.writeHead(400, { \"Content-Type\": \"text/html; charset=utf-8\" });\n res.end(\n `<html><body><h2>Login failed</h2><p>${safeDesc}</p></body></html>`\n );\n teardown();\n reject(new Error(desc));\n return;\n }\n\n const returnedState = url.searchParams.get(\"state\");\n if (returnedState !== state) {\n res.writeHead(400);\n res.end(\"State mismatch\");\n teardown();\n reject(new Error(\"State mismatch\"));\n return;\n }\n\n const code = url.searchParams.get(\"code\");\n if (!code) {\n res.writeHead(400);\n res.end(\"No code\");\n teardown();\n reject(new Error(\"No authorization code received\"));\n return;\n }\n\n // Exchange code for tokens\n const tokens = await exchangeCode(\n config.issuer,\n config.clientId,\n code,\n codeVerifier\n );\n const idPayload = decodeJwtPayload(tokens.id_token);\n const email =\n (idPayload.email as string) ??\n (idPayload.preferred_username as string) ??\n \"unknown\";\n const sub = idPayload.sub as string;\n\n // Parse tenants from access token\n // (the Zitadel Action enriches the access token with urn:mesh:tenants)\n let tenants: string[] = [];\n try {\n const accessPayload = decodeJwtPayload(tokens.access_token);\n tenants =\n (accessPayload[\"urn:mesh:tenants\"] as string[]) ?? [];\n } catch {\n // Access token may be opaque (non-JWT) in some configs\n }\n\n // Cache credentials\n writeCredentials(context, {\n idToken: tokens.id_token,\n accessToken: tokens.access_token,\n refreshToken: tokens.refresh_token,\n expiresAt: new Date(\n Date.now() + tokens.expires_in * 1000\n ).toISOString(),\n email,\n sub,\n });\n\n res.writeHead(200, { \"Content-Type\": \"text/html; charset=utf-8\" });\n res.end(\n `<html><body><h2>&#x2705; Logged in to ${context}!</h2><p>You can close this tab.</p></body></html>`\n );\n\n logSuccess(`Logged in as ${email} (${context})`);\n if (tenants.length > 0) {\n logInfo(`Deployable tenants: ${tenants.join(\", \")}`);\n }\n hintVpnIfDisconnected(context);\n\n teardown();\n resolve();\n } catch (err) {\n teardown();\n reject(err);\n }\n });\n\n // Defined after `server` so the closure captures it; covers\n // success, error, and timeout paths.\n const teardown = () => {\n if (timeoutId) clearTimeout(timeoutId);\n server.closeAllConnections?.();\n server.close();\n };\n\n server.listen(REDIRECT_PORT, () => {\n logInfo(`Opening browser for authentication (${context})...`);\n\n const url = authUrl.toString();\n try {\n if (process.platform === \"darwin\") {\n execFileSync(\"open\", [url], { stdio: \"ignore\" });\n } else if (process.platform === \"linux\") {\n execFileSync(\"xdg-open\", [url], { stdio: \"ignore\" });\n } else {\n logInfo(`Open this URL in your browser:\\n${url}`);\n }\n } catch {\n logInfo(`Open this URL in your browser:\\n${url}`);\n }\n });\n\n // Timeout after 2 minutes. We keep a handle so success / error\n // paths can clear it via `teardown()` \u2014 otherwise the timer keeps\n // the Node event loop alive for 2 minutes after a successful\n // login and the CLI appears to hang.\n timeoutId = setTimeout(() => {\n teardown();\n reject(new Error(\"Login timed out (2 minutes)\"));\n }, 120_000);\n });\n}\n\n\n// =============================================================================\n// Device Code Flow (RFC 8628) \u2014 works in containers, SSH, headless envs\n// =============================================================================\n\ninterface DeviceAuthResponse {\n device_code: string;\n user_code: string;\n verification_uri: string;\n verification_uri_complete?: string;\n expires_in: number;\n interval: number;\n}\n\n/** Number of fresh device codes to issue before giving up. A code's TTL is\n * short (a couple of minutes), so if the user is slow we quietly issue another\n * rather than failing the whole login (we hit this repeatedly in practice). */\nconst MAX_DEVICE_CODES = 3;\n\n/**\n * Run device-code login, re-issuing a fresh code (up to `maxCodes`) if the user\n * doesn't finish before a code expires. `attempt` performs ONE code's\n * request+poll and resolves `\"success\"` or `\"expired\"`; it rejects only on a\n * hard error (denied / network). Extracted + injectable so the reissue loop is\n * unit-testable without real network calls.\n */\nexport async function deviceLoginWithReissue(\n attempt: (codeNumber: number) => Promise<\"success\" | \"expired\">,\n maxCodes: number = MAX_DEVICE_CODES,\n): Promise<void> {\n for (let n = 1; n <= maxCodes; n++) {\n if (n > 1) logWarn(`That code expired \u2014 issuing a fresh one (${n}/${maxCodes})\u2026`);\n if ((await attempt(n)) === \"success\") return;\n }\n throw new Error(\n `Device login not completed after ${maxCodes} codes. Re-run the command when you're ready to authorize.`,\n );\n}\n\nasync function deviceCodeLogin(context: string, config: ContextConfig): Promise<void> {\n await deviceLoginWithReissue(() => attemptDeviceCode(context, config));\n}\n\nasync function attemptDeviceCode(\n context: string,\n config: ContextConfig,\n): Promise<\"success\" | \"expired\"> {\n // Step 1: Request device authorization\n const resp = await fetch(`${config.issuer}/oauth/v2/device_authorization`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({\n client_id: config.clientId,\n scope: SCOPES,\n }).toString(),\n });\n\n if (!resp.ok) {\n const text = await resp.text();\n throw new Error(`Device authorization request failed (${resp.status}): ${text}`);\n }\n\n const deviceAuth = await resp.json() as DeviceAuthResponse;\n const openUrl = deviceAuth.verification_uri_complete ?? deviceAuth.verification_uri;\n\n // Step 2: Display instructions\n console.log();\n logInfo(`Open this URL in your browser:\\n`);\n logInfo(` ${openUrl}\\n`);\n logInfo(`Code: ${deviceAuth.user_code}`);\n console.log();\n logInfo(\"Waiting for authorization...\");\n\n // Try to open browser (works on host, harmless failure in container)\n try {\n if (process.platform === \"darwin\") {\n execFileSync(\"open\", [openUrl], { stdio: \"ignore\" });\n } else if (process.platform === \"linux\") {\n execFileSync(\"xdg-open\", [openUrl], { stdio: \"ignore\" });\n }\n } catch { /* ignore \u2014 user can open manually */ }\n\n // Step 3: Poll for token\n const deadline = Date.now() + deviceAuth.expires_in * 1000;\n let interval = deviceAuth.interval * 1000;\n\n while (Date.now() < deadline) {\n await new Promise((r) => setTimeout(r, interval));\n\n const tokenResp = await fetch(`${config.issuer}/oauth/v2/token`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({\n client_id: config.clientId,\n grant_type: \"urn:ietf:params:oauth:grant-type:device_code\",\n device_code: deviceAuth.device_code,\n }).toString(),\n });\n\n if (tokenResp.ok) {\n const tokens = await tokenResp.json() as TokenResponse;\n const idPayload = decodeJwtPayload(tokens.id_token);\n const email = (idPayload.email as string) ?? (idPayload.preferred_username as string) ?? \"unknown\";\n const sub = idPayload.sub as string;\n\n let tenants: string[] = [];\n try {\n const accessPayload = decodeJwtPayload(tokens.access_token);\n tenants = (accessPayload[\"urn:mesh:tenants\"] as string[]) ?? [];\n } catch { /* opaque access token */ }\n\n writeCredentials(context, {\n idToken: tokens.id_token,\n accessToken: tokens.access_token,\n refreshToken: tokens.refresh_token,\n expiresAt: new Date(Date.now() + tokens.expires_in * 1000).toISOString(),\n email,\n sub,\n });\n\n logSuccess(`Logged in as ${email} (${context})`);\n if (tenants.length > 0) {\n logInfo(`Deployable tenants: ${tenants.join(\", \")}`);\n }\n hintVpnIfDisconnected(context);\n return \"success\";\n }\n\n const error = await tokenResp.json() as { error: string; error_description?: string };\n switch (error.error) {\n case \"authorization_pending\":\n continue;\n case \"slow_down\":\n interval += 1000;\n continue;\n case \"expired_token\":\n return \"expired\"; // caller re-issues a fresh code\n case \"access_denied\":\n throw new Error(\"Authorization denied by user.\");\n default:\n throw new Error(`Token exchange failed: ${error.error} \u2014 ${error.error_description ?? \"\"}`);\n }\n }\n\n return \"expired\"; // deadline reached without authorization \u2014 re-issue\n}\n\n/**\n * Detect an environment where the PKCE browser-callback flow won't work \u2014 a\n * container, a remote/SSH session, or any non-interactive shell (piped output,\n * headless, agent/CI-run). In all of these the callback flow has no browser to\n * open and no interactive terminal, so it can only hang until the 2-minute\n * timeout. Device-code flow (print a URL + code to complete elsewhere) is the\n * correct fallback, so callers use it whenever this returns true.\n *\n * Exported for tests.\n */\nexport function isRemoteEnvironment(): boolean {\n // Docker / devcontainer\n if (process.env.REMOTE_CONTAINERS || process.env.CODESPACES) return true;\n if (fs.existsSync(\"/.dockerenv\")) return true;\n // SSH session\n if (process.env.SSH_CLIENT || process.env.SSH_TTY) return true;\n // No interactive terminal on stdin/stdout \u2014 `isTTY` is `undefined` (falsy)\n // when the stream is not a TTY. This is the case that bit us: an agent- or\n // script-driven shell over Tailscale has none of the env vars above set, so\n // the old check fell through to the browser flow and timed out. Device flow\n // still works when a browser IS available (just copy the URL+code), so\n // preferring it here is strictly safer than a guaranteed timeout.\n if (!process.stdout.isTTY || !process.stdin.isTTY) return true;\n return false;\n}\n\n/**\n * After a successful login, hint about VPN if Tailscale is not connected.\n * Non-blocking \u2014 never fails or delays the login flow.\n */\nfunction hintVpnIfDisconnected(context: string): void {\n try {\n const state = tailscaleBackendState();\n if (state !== \"Running\") {\n console.log(\"\");\n logInfo(`VPN not connected. To access dev services, run:`);\n logInfo(` mesh vpn connect ${context}`);\n }\n } catch {\n // Tailscale not installed or not queryable \u2014 skip hint\n }\n}\n\n// =============================================================================\n// Status\n// =============================================================================\n\n/**\n * What `--status` reports when there is no usable Zitadel session.\n *\n * Zitadel is one way to reach a platform's AWS account, not the only one. A\n * profile authenticated with SSO \u2014 or with a plain access-key/secret pair \u2014\n * is just as good, and everything downstream already accepts it: aws-auth's\n * path 1 (ambient env creds) and path 3 (AssumeRole via the current session)\n * never touch the OIDC cache. Reporting \"not logged in\" purely because that\n * cache is empty sent people off to run a device flow they did not need, and\n * failed the check for anyone deliberately using static credentials.\n *\n * So: fall through to the AWS credential chain and report what it finds.\n */\n/** One `--status` output line plus which logger it goes through. */\nexport interface StatusLine {\n level: \"success\" | \"info\" | \"warn\";\n text: string;\n}\n\n/**\n * The account id embedded in an IAM role ARN\n * (`arn:aws:iam::123456789012:role/...`), or undefined when there is no ARN\n * to read one from.\n */\nexport function accountIdFromRoleArn(\n roleArn: string | undefined\n): string | undefined {\n return roleArn?.match(/^arn:aws:iam::(\\d{12}):/)?.[1];\n}\n\n/**\n * Decide everything `--status` says (and its exit code) when there is no\n * usable Zitadel session \u2014 pure so the wording and the exit decision are\n * pinned by tests.\n *\n * The probe only proves \"some AWS identity works on this machine\"; it says\n * nothing about whether that identity belongs to `context`. So the claim is\n * scoped to the credentials \u2014 unless the context config carries a role ARN,\n * whose account id makes the context check free: verify when we can, say so\n * when we can't.\n */\nexport function renderAwsFallbackStatus(\n context: string,\n reason: string,\n identity: AwsIdentity | null,\n expectedAccountId?: string\n): { lines: StatusLine[]; exitCode: 0 | 1 } {\n if (!identity) {\n return {\n lines: [\n {\n level: \"warn\",\n text: `${reason}, and no working AWS credentials were found either.`,\n },\n { level: \"info\", text: \"Authenticate with whichever you use:\" },\n { level: \"info\", text: ` mesh login ${context} (Zitadel SSO)` },\n {\n level: \"info\",\n text: \" aws sso login --profile \u2026 (AWS SSO profile)\",\n },\n {\n level: \"info\",\n text: \" export AWS_PROFILE=\u2026 (profile with a key/secret pair)\",\n },\n ],\n exitCode: 1,\n };\n }\n\n const lines: StatusLine[] = [\n {\n level: \"success\",\n text: `AWS credentials are working (${identity.source})`,\n },\n { level: \"info\", text: `Identity: ${identity.arn}` },\n { level: \"info\", text: `Account: ${identity.accountId}` },\n ];\n\n if (expectedAccountId && identity.accountId !== expectedAccountId) {\n lines.push({\n level: \"warn\",\n text:\n `This account does not match ${context}'s configured role account ` +\n `(${expectedAccountId}) \u2014 commands against ${context} will likely ` +\n `fail with AccessDenied. Check AWS_PROFILE / your exported credentials.`,\n });\n } else if (expectedAccountId) {\n lines.push({\n level: \"info\",\n text: `Account matches ${context}'s configured role account.`,\n });\n } else {\n lines.push({\n level: \"info\",\n text:\n `This is a working AWS identity, not a verified connection to ` +\n `${context} \u2014 nothing here checked that this account is ${context}'s.`,\n });\n }\n\n lines.push({\n level: \"info\",\n text:\n `${reason} \u2014 that only matters for the commands that need a *user* ` +\n `identity (Hub SSO, \\`mesh dev\\` test users, zero-touch VPN join). ` +\n `Deploys, registry auth and secrets work off these credentials.`,\n });\n\n return { lines, exitCode: 0 };\n}\n\nasync function showAwsCredentialStatus(\n context: string,\n reason: string,\n config: ContextConfig\n): Promise<void> {\n const identity = await probeAwsIdentity();\n const { lines, exitCode } = renderAwsFallbackStatus(\n context,\n reason,\n identity,\n accountIdFromRoleArn(config.defaultRole ?? config.adminRole)\n );\n\n for (const line of lines) {\n if (line.level === \"success\") logSuccess(line.text);\n else if (line.level === \"warn\") logWarn(line.text);\n else logInfo(line.text);\n }\n if (exitCode !== 0) process.exit(exitCode);\n}\n\nasync function showStatus(\n context: string,\n config: ContextConfig\n): Promise<void> {\n const creds = readCredentials(context);\n if (!creds) {\n await showAwsCredentialStatus(context, \"No cached Zitadel session\", config);\n return;\n }\n\n const expired = new Date(creds.expiresAt) < new Date();\n\n if (expired && creds.refreshToken) {\n logInfo(\"Token expired, attempting refresh...\");\n try {\n const tokens = await refreshTokens(\n config.issuer,\n config.clientId,\n creds.refreshToken\n );\n const idPayload = decodeJwtPayload(tokens.id_token);\n writeCredentials(context, {\n ...creds,\n idToken: tokens.id_token,\n accessToken: tokens.access_token,\n refreshToken: tokens.refresh_token ?? creds.refreshToken,\n expiresAt: new Date(\n Date.now() + tokens.expires_in * 1000\n ).toISOString(),\n email: (idPayload.email as string) ?? creds.email,\n });\n logSuccess(`Token refreshed for ${creds.email ?? \"unknown\"}`);\n return;\n } catch {\n await showAwsCredentialStatus(\n context,\n \"Zitadel token expired and refresh failed\",\n config\n );\n return;\n }\n }\n\n if (expired) {\n await showAwsCredentialStatus(\n context,\n `Zitadel token expired at ${creds.expiresAt}`,\n config\n );\n return;\n }\n\n // Parse tenants from access token\n let tenants: string[] = [];\n try {\n const accessPayload = decodeJwtPayload(creds.accessToken);\n tenants = (accessPayload[\"urn:mesh:tenants\"] as string[]) ?? [];\n } catch {\n // Access token may be opaque\n }\n\n logSuccess(`Logged in as ${creds.email ?? \"unknown\"} (${context})`);\n logInfo(`Subject: ${creds.sub}`);\n logInfo(`Expires: ${creds.expiresAt}`);\n if (tenants.length > 0) {\n logInfo(`Deployable tenants: ${tenants.join(\", \")}`);\n }\n}\n// =============================================================================\n// Commands\n// =============================================================================\n\nexport function registerLoginCommand(program: Command): void {\n program\n .command(\"login\")\n .description(\"Authenticate with Zitadel (OIDC PKCE or Device Code)\")\n .argument(\"<context>\", 'Platform context (e.g., \"mesh.dev\")')\n .option(\n \"--status\",\n \"Show current authentication status \u2014 the Zitadel session if one is cached, otherwise the AWS identity the credential chain resolves (SSO profile or key pair). Exits non-zero only when neither works.\"\n )\n .option(\"--device\", \"Force device code flow (no callback server needed)\")\n .option(\n \"--export\",\n \"After login, print a self-refreshing AWS credential_process profile as shell `export` statements (use with `eval`). The resulting shell auto-refreshes credentials via `mesh login`. Requires --role or MESH_AWS_ROLE.\"\n )\n .option(\n \"--static\",\n \"With --export: print raw temporary AWS credentials (a frozen ~1h triple) instead of the default self-refreshing credential_process profile\"\n )\n .option(\n \"--credential-process\",\n \"Print AWS credential_process JSON (used by mesh dev's temp profile); refreshes the Zitadel token as needed. Requires --role or a cached defaultRole.\"\n )\n .option(\n \"--role <arn>\",\n \"IAM role ARN to assume via web identity (used with --export). Saved as the default for this context so future --export runs can omit it. Resolution order: --role > MESH_AWS_ROLE > cached defaultRole.\"\n )\n .option(\n \"--region <region>\",\n \"AWS region to include in the exported AWS_REGION. Defaults to AWS_REGION env or us-east-2.\"\n )\n .option(\n \"--no-registry\",\n \"Skip the CodeArtifact registry-auth step that runs automatically after login for {tenant}.{env} contexts\"\n )\n .action(async (context: string, opts: {\n status?: boolean;\n device?: boolean;\n export?: boolean;\n static?: boolean;\n credentialProcess?: boolean;\n role?: string;\n region?: string;\n registry?: boolean;\n }) => {\n let config = getContextConfig(context);\n if (!config) {\n // One chain, shared with `ensureLogin` \u2014 see discoverConfigGuarded.\n // Deliberately NOT re-implemented here: this call site and that one\n // drifted apart once already, and the difference was whether a clean\n // laptop could resolve a short context at all.\n config = await discoverConfigGuarded(context);\n\n if (!config) {\n const pinned = firstPartyDomainFor(context);\n logError(\n `No configuration found for \"${context}\".\\n\\n` +\n `Tried:\\n` +\n ` 1. SSM: /mesh-platform/${context.split(\".\")[0]}/${context.split(\".\")[1]}/platform/zitadel\\n` +\n ` (requires AWS SSO login + read access)\\n` +\n (pinned\n ? ` 2. HTTPS: https://cli.${pinned}/.well-known/mesh.json (pinned first-party domain)\\n\\n`\n : ` 2. HTTPS: https://cli.${context}/.well-known/mesh.json\\n` +\n ` (only attempted for a full domain, or a known first-party context)\\n\\n`) +\n `To fix:\\n` +\n ` - Use the platform's full domain: mesh login <env>.<tenant>.meshtech.io\\n` +\n ` - Or, if you have AWS access, ensure SSO is active: aws sso login --profile <profile>\\n` +\n ` - Or add config manually to ${CONFIG_FILE}:\\n\\n` +\n ` {\\n` +\n ` \"${context}\": {\\n` +\n ` \"issuer\": \"https://identity.<env>.<your-platform-domain>\",\\n` +\n ` \"clientId\": \"<cli-oidc-client-id>\"\\n` +\n ` }\\n` +\n ` }\\n`\n );\n process.exit(1);\n }\n }\n\n if (opts.status) {\n await showStatus(context, config);\n return;\n }\n\n if (opts.export) {\n await exportAwsCredentials(context, config, opts);\n return;\n }\n\n if (opts.credentialProcess) {\n await credentialProcessAwsCredentials(context, config, opts);\n return;\n }\n\n try {\n const useDevice = opts.device || isRemoteEnvironment();\n if (useDevice) {\n logInfo(\"Using device code flow\");\n await deviceCodeLogin(context, config);\n } else {\n await login(context, config);\n }\n } catch (err) {\n logError(`Login failed: ${(err as Error).message}`);\n process.exit(1);\n }\n\n // F2: login absorbs registry auth. CodeArtifact-backed contexts are the\n // {tenant}.{env} ones \u2014 the local platform ('local') has no registry.\n // Best-effort: a registry hiccup must not fail an otherwise good login.\n if (opts.registry !== false && parseTenantEnv(context)) {\n try {\n logInfo(\"Refreshing CodeArtifact registry auth (skip with --no-registry)\u2026\");\n const { runRegistryLogin } = await import(\"./registry.js\");\n await runRegistryLogin(context, {});\n } catch (err) {\n logWarn(\n `Registry auth failed (login itself succeeded): ${(err as Error).message}` +\n ` \u2014 retry with: mesh registry login ${context}`\n + ` (add --profile mesh-dev only if you have an AWS account and the broker is unavailable)`,\n );\n }\n }\n });\n\n program\n .command(\"logout\")\n .description(\"Clear cached Zitadel credentials\")\n .argument(\"<context>\", 'Platform context (e.g., \"mesh.dev\")')\n .action((context: string) => {\n clearCredentials(context);\n logSuccess(`Logged out of ${context}. Credentials cleared.`);\n });\n}\n\n// =============================================================================\n// Exports (for use by other mesh commands)\n// =============================================================================\n\n/**\n * Get a valid access token for the given context, refreshing if needed.\n *\n * Returns the id token (a JWT with `sub` claim) suitable for\n * Authorization: Bearer headers. Returns null if no credentials are\n * cached or refresh fails.\n */\n/**\n * True while a cached token is still valid, treating anything within `marginMs`\n * of expiry as already stale. The margin lets pollers (e.g. the dev-user\n * token-server) re-mint BEFORE expiry instead of handing out a token that dies\n * before the caller's next poll.\n */\nexport function tokenStillValid(expiresAt: string, marginMs = 0, now = Date.now()): boolean {\n return new Date(expiresAt).getTime() - marginMs > now;\n}\n\nasync function getValidToken(\n context: string,\n opts: { marginMs?: number } = {},\n): Promise<string | null> {\n const config = getContextConfig(context);\n if (!config) return null;\n\n const creds = readCredentials(context);\n if (!creds) return null;\n\n if (tokenStillValid(creds.expiresAt, opts.marginMs ?? 0)) {\n return creds.idToken;\n }\n\n // Attempt refresh\n if (!creds.refreshToken) return null;\n try {\n const tokens = await refreshTokens(config.issuer, config.clientId, creds.refreshToken);\n const idPayload = decodeJwtPayload(tokens.id_token);\n writeCredentials(context, {\n ...creds,\n idToken: tokens.id_token,\n accessToken: tokens.access_token,\n refreshToken: tokens.refresh_token ?? creds.refreshToken,\n expiresAt: new Date(Date.now() + tokens.expires_in * 1000).toISOString(),\n email: (idPayload.email as string) ?? creds.email,\n });\n return tokens.id_token;\n } catch {\n return null;\n }\n}\n\n// =============================================================================\n// Credential freshness probe (shared seam: mesh dev doctor + preflight)\n// =============================================================================\n\n/**\n * Structured diagnosis of the deployer-credential path for a context/role,\n * without mutating anything. The shared seam behind `mesh dev doctor`'s creds\n * check and the launch preflight (MESH-2015), reusing the same\n * `getValidToken` + `assumeRoleCredentials` path as `--credential-process`\n * (MESH-1965).\n */\nexport type CredProbe =\n | { state: \"ok\"; ttlSeconds: number; expiresAt: string; email?: string }\n | { state: \"no-session\" }\n | { state: \"expired-session\" }\n | { state: \"assume-denied\"; detail: string }\n | { state: \"stale-env-override\" };\n\n/**\n * Probe deployer creds for `context`/`roleArn`. Order matters:\n * 1. No cached Zitadel session \u2192 `no-session`.\n * 2. Cached session AND ambient `AWS_*` env keys present \u2192 `stale-env-override`\n * (the frozen triple would override the self-refreshing profile at\n * runtime \u2014 the exact `mesh dev` trap). Guarded on a cached session so\n * legitimate CI env-key credentials, which have no `mesh login` session,\n * are not misreported.\n * 3. Session can't be refreshed \u2192 `expired-session`.\n * 4. AssumeRoleWithWebIdentity fails \u2192 `assume-denied` (valid identity, wrong\n * IAM/role/policy).\n * 5. Otherwise \u2192 `ok` with the STS TTL.\n */\nexport async function probeCredentials(\n context: string,\n roleArn: string,\n): Promise<CredProbe> {\n const cached = readCredentials(context);\n if (!cached) return { state: \"no-session\" };\n\n if (process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SESSION_TOKEN) {\n return { state: \"stale-env-override\" };\n }\n\n const token = await getValidToken(context);\n if (!token) return { state: \"expired-session\" };\n\n const sessionName = (cached.email ?? \"mesh-cli-doctor\")\n .replace(/[^a-zA-Z0-9=,.@-]/g, \"_\")\n .slice(0, 64);\n const sts = await assumeRoleCredentials(roleArn, token, sessionName);\n if (!sts) {\n return {\n state: \"assume-denied\",\n detail: describeAssumeFailure({ roleArn, context, issuer: tokenIssuer(token) }, \"inline\"),\n };\n }\n const ttlSeconds = Math.max(\n 0,\n Math.round((Date.parse(sts.Expiration) - Date.now()) / 1000),\n );\n return { state: \"ok\", ttlSeconds, expiresAt: sts.Expiration, email: cached.email };\n}\n\n// =============================================================================\n// AWS credential export (--export flag)\n// =============================================================================\n\n/**\n * Single-quote a value for shell-safe inclusion in an `export` statement.\n * Single-quoted strings in POSIX shells don't expand `$` or other metachars;\n * embedded single-quotes are escaped via the `'\\''` trick.\n */\nfunction shellSingleQuote(value: string): string {\n return `'${value.replace(/'/g, \"'\\\\''\")}'`;\n}\n\n/**\n * Render the `--static` output: raw temporary AWS credentials as shell\n * `export` statements (the old frozen ~1h triple). Pure \u2014 no I/O. Includes a\n * trailing newline. Exported for unit testing.\n */\nexport function renderExportStaticLines(args: {\n accessKey: string;\n secretKey: string;\n sessionToken: string;\n region: string;\n}): string {\n return (\n `export AWS_ACCESS_KEY_ID=${shellSingleQuote(args.accessKey)}\\n` +\n `export AWS_SECRET_ACCESS_KEY=${shellSingleQuote(args.secretKey)}\\n` +\n `export AWS_SESSION_TOKEN=${shellSingleQuote(args.sessionToken)}\\n` +\n `export AWS_REGION=${shellSingleQuote(args.region)}\\n`\n );\n}\n\n/**\n * Render the default `--export` output: point the shell at a self-refreshing\n * `credential_process` profile. The leading `unset` clears any stale STS\n * triple already in the shell so it can't shadow the profile. Pure \u2014 no I/O.\n * Includes a trailing newline. Exported for unit testing.\n *\n * Deliberately does NOT export `AWS_CONFIG_FILE`: the profile lives in the\n * user's REAL AWS config file (managed marker section \u2014 see\n * `upsertManagedAwsConfigSection`), so their other profiles (e.g.\n * `AWS_PROFILE=mesh-dev` InfraAdmin) keep working in the same shell.\n * Redirecting AWS_CONFIG_FILE to a mesh-private file used to clobber\n * ~/.aws/config for every subsequent AWS command.\n */\nexport function renderExportProfileLines(args: {\n profileName: string;\n region: string;\n}): string {\n return (\n `unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN\\n` +\n `export AWS_PROFILE=${shellSingleQuote(args.profileName)}\\n` +\n `export AWS_REGION=${shellSingleQuote(args.region)}\\n`\n );\n}\n\n/**\n * The AWS config file the managed profile section is written into: the\n * user's `$AWS_CONFIG_FILE` when THEY have set one, else `~/.aws/config` \u2014\n * the same file `aws configure sso` manages. Exported for unit testing.\n */\nexport function resolveUserAwsConfigPath(\n env: Record<string, string | undefined> = process.env,\n): string {\n return env.AWS_CONFIG_FILE ?? path.join(env.HOME ?? \"~\", \".aws\", \"config\");\n}\n\n/** True if `dir` can be created (if needed) and written. Used to detect an\n * unwritable `~/.aws` (e.g. a sandbox with no `~/.aws` grant) without throwing. */\nfunction canWriteDir(dir: string): boolean {\n try {\n fs.mkdirSync(dir, { recursive: true });\n fs.accessSync(dir, fs.constants.W_OK);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Where to write the managed AWS profile, with a safehouse fallback. Normally\n * the user's real `~/.aws/config` (augmented in place, so their other tools see\n * the profile \u2014 hence `redirected: false`, we don't touch their `AWS_CONFIG_FILE`).\n * But when `~/.aws` is not writable (a sandbox without a `~/.aws` grant), fall\n * back to a mesh-managed file under `~/.config/mesh` we CAN write, and set\n * `redirected: true` so the caller also exports `AWS_CONFIG_FILE` (otherwise the\n * AWS SDK, looking only at `~/.aws/config`, would never find the profile). An\n * explicit `AWS_CONFIG_FILE` always wins and is never redirected.\n */\nexport function resolveAwsConfigTarget(\n env: Record<string, string | undefined> = process.env,\n): { configPath: string; redirected: boolean } {\n if (env.AWS_CONFIG_FILE) return { configPath: env.AWS_CONFIG_FILE, redirected: false };\n const real = path.join(env.HOME ?? \"~\", \".aws\", \"config\");\n if (canWriteDir(path.dirname(real))) return { configPath: real, redirected: false };\n return { configPath: path.join(CONFIG_DIR, \"aws-config\"), redirected: true };\n}\n\n/**\n * Resolve which IAM role ARN to use, honoring the same precedence in both\n * `--export` and `--credential-process`: explicit `--role` wins, then\n * `MESH_AWS_ROLE`, then the context's cached `defaultRole`. Pure aside from\n * reading `process.env.MESH_AWS_ROLE` \u2014 returns an explanatory error instead\n * of throwing so callers can route it to stderr and exit non-zero.\n *\n * Exported for unit testing.\n */\nexport function resolveRoleOrExplain(\n opts: { role?: string },\n config: { defaultRole?: string },\n): { role: string } | { error: string } {\n const role = opts.role ?? process.env.MESH_AWS_ROLE ?? config.defaultRole;\n if (!role) {\n return {\n error:\n \"No IAM role available: pass --role <arn>, set MESH_AWS_ROLE, or run \" +\n \"`mesh login <context> --export --role <arn>` once to cache a default role for this context.\",\n };\n }\n return { role };\n}\n\n/**\n * Ensure a valid Zitadel ID token is cached for the given context \u2014 refreshing\n * or running the full login flow as needed. Returns null on failure.\n */\nasync function ensureValidToken(\n context: string,\n config: ContextConfig,\n opts: { device?: boolean },\n): Promise<string | null> {\n let token = await getValidToken(context);\n if (token) return token;\n\n logInfo(`No valid Zitadel session for ${context} \u2014 running login flow`);\n try {\n const useDevice = opts.device || isRemoteEnvironment();\n if (useDevice) {\n logInfo(\"Using device code flow\");\n await deviceCodeLogin(context, config);\n } else {\n await login(context, config);\n }\n } catch (err) {\n logError(`Login failed: ${(err as Error).message}`);\n return null;\n }\n return await getValidToken(context);\n}\n\n/**\n * Ensure a valid login session for `context`, running the login flow (device\n * code in remote/non-TTY, browser callback otherwise) if none is cached. Returns\n * the cached credentials, or null if no config is available to log in with.\n *\n * For use by other commands (e.g. `secrets set`, the AWS-cred resolver) so they\n * can trigger login on demand instead of just failing with guidance.\n */\nexport async function ensureLogin(\n context: string,\n opts: { device?: boolean; interactive?: boolean } = {},\n): Promise<CachedCredentials | null> {\n const existing = readCredentials(context);\n if (existing && new Date(existing.expiresAt) > new Date()) return existing;\n\n // interactive: false \u2192 cached-session-or-nothing. Callers with their own\n // fallback chain (e.g. the AWS-cred resolver's SSO path) use this so an\n // expired cache doesn't stall headless runs in a device-code poll.\n if (opts.interactive === false) return null;\n\n // Same guarded discovery chain as the `login` command: SSM first, and the\n // well-known HTTPS endpoint only for domain-looking contexts (\u22652 dots).\n // Hitting `https://cli.<short-name>/.well-known/mesh.json` for an uncached\n // context like \"mesh.dev\" would let whoever registers that domain seed our\n // cached issuer/clientId (login phishing).\n const config = getContextConfig(context) ?? (await discoverConfigGuarded(context));\n if (!config) {\n logWarn(`No login config for \"${context}\". Run: mesh login ${context}`);\n return null;\n }\n const token = await ensureValidToken(context, config, opts);\n if (!token) return null;\n return readCredentials(context);\n}\n\n/**\n * The one discovery chain, used by both the `login` command and `ensureLogin`:\n *\n * 1. SSM, when the context parses as `{tenant}.{env}` \u2014 the primary path for\n * internal users who already have AWS SSO access.\n * 2. The anonymous HTTPS well-known endpoint at the PINNED domain for a known\n * first-party short context (`mesh.dev` \u2192 `dev.platform.meshtech.io`). This\n * is what makes `mesh login mesh.dev` work on a laptop with no AWS at all\n * \u2014 the P0 case. The domain comes from a compiled-in table, never from the\n * context string, so it is not a phishing surface.\n * 3. The anonymous HTTPS endpoint at the context itself, only when it looks\n * like a real domain (\u22652 dots).\n *\n * Never hits `https://cli.<short-name>/\u2026` for an UNKNOWN short context \u2014 that\n * guard is the anti-phishing property and step 2 is deliberately a pinned\n * allow-list rather than a relaxation of it.\n */\nasync function discoverConfigGuarded(context: string): Promise<ContextConfig | null> {\n let config: ContextConfig | null = null;\n if (parseTenantEnv(context)) {\n config = await discoverConfigFromSsm(context);\n }\n if (!config) {\n const pinned = firstPartyDomainFor(context);\n if (pinned) {\n logInfo(`\"${context}\" is a known Mesh platform \u2014 resolving via ${pinned} (no AWS needed)`);\n config = await discoverConfig(pinned, context);\n }\n }\n if (!config && context.split(\".\").length - 1 >= 2) {\n config = await discoverConfig(context);\n }\n return config;\n}\n\n/**\n * Resolve AWS credentials via Zitadel JWT \u2192 AssumeRoleWithWebIdentity, then\n * print them as `export` statements on stdout. All status/error output goes\n * to stderr so the caller can safely `eval \"$(mesh login ... --export ...)\"`.\n */\nasync function exportAwsCredentials(\n context: string,\n config: ContextConfig,\n opts: { role?: string; region?: string; device?: boolean; static?: boolean },\n): Promise<void> {\n const token = await ensureValidToken(context, config, opts);\n if (!token) {\n process.exit(1);\n }\n\n // Pick a role for the caller. `resolveRoleOrExplain` handles the\n // --role / MESH_AWS_ROLE / cached-defaultRole precedence (shared with\n // --credential-process); on top of that, when we fell back to the cached\n // default we ask `selectRoleForCaller` to upgrade to the context's\n // `adminRole` when the Zitadel JWT carries an admin claim.\n const resolvedRole = resolveRoleOrExplain(opts, config);\n if (\"error\" in resolvedRole) {\n logError(\n \"--export requires --role <arn> (or MESH_AWS_ROLE env var, or a cached defaultRole).\\n\" +\n \" Example: mesh login mesh.dev --export --role arn:aws:iam::123456789012:role/mesh-developer\\n\" +\n \" After the first run, the role is saved to ~/.config/mesh/config.json and --role can be omitted.\"\n );\n process.exit(1);\n }\n let roleArn = resolvedRole.role;\n if (!opts.role && !process.env.MESH_AWS_ROLE && config.defaultRole) {\n roleArn = selectRoleForCaller(token, {\n defaultRole: config.defaultRole,\n adminRole: config.adminRole,\n adminClaimRoles: config.adminClaimRoles,\n });\n }\n if (config.adminRole && roleArn === config.adminRole && !opts.role) {\n logInfo(\n `Caller has admin Zitadel role \u2014 assuming ${roleArn.split(\"/\").pop()} (admin variant)`,\n );\n }\n\n // Persist --role so subsequent runs can omit it.\n if (opts.role && opts.role !== config.defaultRole) {\n writeContextConfig(context, { ...config, defaultRole: opts.role });\n logInfo(`Saved default role for ${context}`);\n }\n\n const region =\n opts.region ??\n process.env.AWS_REGION ??\n process.env.AWS_DEFAULT_REGION ??\n \"us-east-2\";\n\n const roleName = roleArn.split(\"/\").pop() ?? roleArn;\n\n // --static: resolve a frozen STS triple now (the old behavior). Consumers\n // that need raw credentials (no `mesh` binary on refresh) opt into this.\n if (opts.static) {\n const creds = readCredentials(context);\n const sessionName = (creds?.email ?? \"mesh-cli-export\")\n .replace(/[^a-zA-Z0-9=,.@-]/g, \"_\")\n .slice(0, 64);\n\n const env = await assumeRoleWithWebIdentity(roleArn, token, sessionName);\n if (!env) {\n logError(\n describeAssumeFailure({ roleArn, context, issuer: tokenIssuer(token) }),\n );\n process.exit(1);\n }\n\n const accessKey = env.AWS_ACCESS_KEY_ID;\n const secretKey = env.AWS_SECRET_ACCESS_KEY;\n const sessionToken = env.AWS_SESSION_TOKEN;\n if (!accessKey || !secretKey || !sessionToken) {\n logError(\"AWS STS returned incomplete credentials\");\n process.exit(1);\n }\n\n process.stdout.write(\n renderExportStaticLines({ accessKey, secretKey, sessionToken, region }),\n );\n logSuccess(`Exported static AWS credentials for ${roleName} in ${region}`);\n return;\n }\n\n // Default: manage a `[profile mesh-<context>]` block inside the user's REAL\n // AWS config file ($AWS_CONFIG_FILE if they set one, else ~/.aws/config) as\n // an idempotent marker-delimited section \u2014 the same file `aws configure sso`\n // manages \u2014 and export only AWS_PROFILE. The profile's `credential_process`\n // re-invokes `mesh login \u2026 --credential-process`, so `eval`-ed shells\n // auto-refresh instead of dying ~1h in. We must NOT export AWS_CONFIG_FILE\n // pointing at a mesh-private file: that hides ~/.aws/config from the whole\n // shell and breaks the user's other profiles (e.g. AWS_PROFILE=mesh-dev).\n const meshBin = resolveStableMeshBin(process.argv[1]);\n const sanitized = context.replace(/[^A-Za-z0-9_-]/g, \"-\");\n const profileName = `mesh-${sanitized}`;\n // Safehouse-friendly: falls back to a mesh-managed config when ~/.aws is not\n // writable (and then `redirected` tells us to export AWS_CONFIG_FILE too).\n const { configPath, redirected } = resolveAwsConfigTarget();\n fs.mkdirSync(path.dirname(configPath), { recursive: true });\n // Read \u2192 build \u2192 atomic-write back-to-back (all sync) so the lost-update\n // window against concurrent writers (another `mesh login --export`, the\n // user's own editor, `aws configure`) is as small as possible; the temp+\n // rename write means concurrent READERS never observe a truncated file.\n const existedBefore = fs.existsSync(configPath);\n const existing = existedBefore ? fs.readFileSync(configPath, \"utf-8\") : \"\";\n // Preserve the user's existing mode (rename replaces the inode, so the\n // temp file's mode wins) \u2014 never chmod their config out from under them.\n // Restrict to 0600 only when WE create the file.\n const mode = existedBefore ? fs.statSync(configPath).mode & 0o777 : 0o600;\n atomicWriteFileSync(\n configPath,\n upsertManagedAwsConfigSection(\n existing,\n context,\n renderCredentialProcessProfile({\n profileName,\n context,\n roleArn,\n region,\n meshBin,\n }),\n ),\n mode,\n );\n\n process.stdout.write(renderExportProfileLines({ profileName, region }));\n // When we redirected away from an unwritable ~/.aws, the profile lives in a\n // mesh-managed file \u2014 export AWS_CONFIG_FILE so the AWS SDK finds it.\n if (redirected) {\n process.stdout.write(`export AWS_CONFIG_FILE=${shellSingleQuote(configPath)}\\n`);\n }\n logSuccess(\n `Exported self-refreshing AWS profile ${profileName} for ${roleName} in ${region} ` +\n `(managed section in ${configPath})`,\n );\n}\n\n// =============================================================================\n// AWS credential_process (--credential-process flag)\n// =============================================================================\n\n/**\n * Resolve AWS credentials via Zitadel JWT \u2192 AssumeRoleWithWebIdentity, then\n * print them as AWS `credential_process` JSON on stdout \u2014 nothing else may\n * reach stdout in this mode, since the AWS SDK parses it directly. All\n * status/error output goes to stderr.\n *\n * Unlike `--export`, this does NOT run an interactive login flow when no\n * session is cached (there's no terminal/browser to drive it from a child\n * process) \u2014 it only refreshes an existing session via its refresh token\n * (`getValidToken`). Callers must `mesh login <context>` at least once.\n */\nasync function credentialProcessAwsCredentials(\n context: string,\n config: ContextConfig,\n opts: { role?: string },\n): Promise<void> {\n const token = await getValidToken(context);\n if (!token) {\n logError(\n `No valid Zitadel session for ${context} (missing, expired, or refresh failed). Run: mesh login ${context}`\n );\n process.exit(1);\n }\n\n const resolvedRole = resolveRoleOrExplain(opts, config);\n if (\"error\" in resolvedRole) {\n logError(resolvedRole.error);\n process.exit(1);\n }\n\n const creds = readCredentials(context);\n const sessionName = (creds?.email ?? \"mesh-cli-credential-process\")\n .replace(/[^a-zA-Z0-9=,.@-]/g, \"_\")\n .slice(0, 64);\n\n const stsCreds = await assumeRoleCredentials(resolvedRole.role, token, sessionName);\n if (!stsCreds) {\n logError(\n describeAssumeFailure({\n roleArn: resolvedRole.role,\n context,\n issuer: tokenIssuer(token),\n }),\n );\n process.exit(1);\n }\n\n process.stdout.write(toCredentialProcessJson(stsCreds) + \"\\n\");\n}\n\nexport { CONFIG_DIR, CONFIG_FILE, CREDENTIALS_FILE };\nexport type { ContextConfig, CachedCredentials, CredentialsFile };\n/** Every cached context config, keyed by context name. */\nexport function readAllContextConfigs(): ConfigFile {\n return readConfig();\n}\n\n/**\n * The discovery chain on its own, without the browser flow that follows it.\n *\n * Exported so the clean-laptop bootstrap \u2014 SSM \u2192 pinned first-party alias \u2192\n * full-domain, and the anti-phishing refusal for an unknown short context \u2014 can\n * be exercised end-to-end against the live well-known endpoint. The `login`\n * command's own path is otherwise only reachable by completing an interactive\n * sign-in, which is why this leg had no coverage above the unit tier.\n */\nexport async function discoverConfigForContext(context: string): Promise<ContextConfig | null> {\n return getContextConfig(context) ?? (await discoverConfigGuarded(context));\n}\n\nexport { readCredentials, readAllCredentials, getContextConfig, decodeJwtPayload, getValidToken };", "/**\n * Shared agent-api client: resolves a `--target`/`--api-url`/`--context`\n * triple (via the `@mesh-tech/agent-targets` registry) to a concrete\n * `AgentApiTarget`, and fetches agent-api paths against it with auth.\n *\n * Consumed by `mesh artifacts get` today; later `mesh conversations`\n * commands share the same resolution + fetch path.\n */\n\nimport { loadTargetsFile, stripSlash } from \"@mesh-tech/agent-targets\";\nimport { getValidToken } from \"./login.js\";\nimport { logWarn } from \"../utils/log.js\";\n\nconst DEFAULT_AUTH_CONTEXT = \"mesh.dev\";\n\n/** Matches a local (`mesh dev`-hosted) apiBaseUrl \u2014 shared by `authHeaders`'s\n * dev-identity fallback and `describeNetworkError`'s local/remote gating. */\nconst LOCAL_URL_RE = /^https?:\\/\\/(localhost|127\\.0\\.0\\.1|\\[::1\\])(:|\\/|$)/i;\n\nexport interface AgentApiTarget {\n apiBaseUrl: string;\n loginContext?: string;\n conversationPathPrefix?: string;\n hubBaseUrl?: string;\n token?: string;\n}\n\nexport class TargetResolutionError extends Error {}\n\nconst NO_REGISTRY_GUIDANCE =\n \"no registry \u2014 add `mesh agent-targets add <name>` or pass --api-url\";\n\n/**\n * Precedence:\n * 1. --api-url (+ --context, default \"mesh.dev\") \u2014 highest.\n * 2. --target explicitly given \u2192 registry: loaded+found wins, loaded+missing\n * throws (unknown target), invalid throws (with the registry's parse\n * error), absent throws (\"no registry\" guidance).\n * 3. neither given \u2192 loaded registry's defaultTarget; otherwise (registry\n * absent/invalid) falls back to AGENT_API_URL/API_URL/localhost:8787 \u2014\n * this path NEVER throws (backward compat with the old no-flag behavior).\n */\nexport function resolveTarget(opts: { target?: string; apiUrl?: string; context?: string }): AgentApiTarget {\n if (opts.apiUrl) {\n return { apiBaseUrl: stripSlash(opts.apiUrl), loginContext: opts.context || DEFAULT_AUTH_CONTEXT };\n }\n\n const res = loadTargetsFile();\n\n if (opts.target) {\n if (res.status === \"invalid\") {\n throw new TargetResolutionError(\n `Registry at ${res.path} is invalid: ${res.message}. Fix it, or pass --api-url <url>.`,\n );\n }\n if (res.status === \"absent\") {\n throw new TargetResolutionError(`No agent target given and ${NO_REGISTRY_GUIDANCE}.`);\n }\n const entry = res.targets[opts.target];\n if (!entry) {\n throw new TargetResolutionError(\n `Unknown target \"${opts.target}\". Available: ${Object.keys(res.targets).join(\", \") || \"(none)\"}. ` +\n `Add it with 'mesh agent-targets add ${opts.target}' or pass --api-url.`,\n );\n }\n return {\n apiBaseUrl: entry.apiBaseUrl,\n loginContext: entry.loginContext,\n conversationPathPrefix: entry.conversationPathPrefix,\n hubBaseUrl: entry.hubBaseUrl,\n token: entry.token,\n };\n }\n\n if (res.status === \"loaded\") {\n // RegistrySchema's refine() guarantees defaultTarget names an existing entry.\n const entry = res.targets[res.defaultTarget]!;\n return {\n apiBaseUrl: entry.apiBaseUrl,\n loginContext: entry.loginContext,\n conversationPathPrefix: entry.conversationPathPrefix,\n hubBaseUrl: entry.hubBaseUrl,\n token: entry.token,\n };\n }\n\n if (res.status === \"invalid\") {\n // Neither --target nor --api-url given, so this is the implicit/no-flag\n // path \u2014 warn (don't throw) so a broken registry file doesn't silently\n // swallow itself while the CLI quietly falls back to env/localhost.\n logWarn(`Agent-targets registry at ${res.path} is invalid: ${res.message}. Falling back to env/localhost.`);\n }\n\n // No target/api-url given and no usable registry: preserve the old\n // `mesh artifacts get` no-flag behavior \u2014 never throw here.\n const fallbackUrl = process.env.AGENT_API_URL || process.env.API_URL || \"http://localhost:8787\";\n return { apiBaseUrl: stripSlash(fallbackUrl), loginContext: opts.context || DEFAULT_AUTH_CONTEXT };\n}\n\nasync function authHeaders(target: AgentApiTarget): Promise<Record<string, string>> {\n if (target.token) return { Authorization: `Bearer ${target.token}` };\n const ctx = target.loginContext || DEFAULT_AUTH_CONTEXT;\n const token = await getValidToken(ctx);\n if (token) return { Authorization: `Bearer ${token}` };\n if (LOCAL_URL_RE.test(target.apiBaseUrl)) return { \"X-Forwarded-User\": \"dev-user\", \"X-Forwarded-Email\": \"dev@localhost\" };\n throw new TargetResolutionError(`No valid credentials for context \"${ctx}\". Run: mesh login ${ctx}`);\n}\n\n/**\n * Fetch an agent-api path on the resolved target, with auth. Caller checks\n * status.\n *\n * `redirect: \"manual\"` is deliberate: an unauthenticated `/v1` call against a\n * deployed agent 302s to Zitadel. With the default `redirect: \"follow\"`,\n * fetch follows it and returns a `200` HTML login page \u2014 `describeHttpError`'s\n * auth branch never fires and the caller sees a raw JSON-parse error instead\n * of auth guidance. With `\"manual\"`, the redirect surfaces as a Response with\n * `type: \"opaqueredirect\"` (status 0), which `describeHttpError` already maps\n * to the \"auth did not reach the agent\" message.\n */\nexport async function agentApiFetch(target: AgentApiTarget, apiPath: string): Promise<Response> {\n const headers = await authHeaders(target);\n return fetch(`${target.apiBaseUrl}${apiPath}`, { headers, redirect: \"manual\" });\n}\n\nconst NETWORK_ERROR_PATTERN = /ECONNREFUSED|fetch failed|ENOTFOUND|EAI_AGAIN/;\n\n/**\n * Turn a thrown fetch error into local-vs-remote-aware guidance. A bare\n * `ECONNREFUSED`/`fetch failed` (also `ENOTFOUND`/`EAI_AGAIN`) means\n * something different depending on the target: against a LOCAL apiBaseUrl it\n * almost always means the local `mesh dev` agent API isn't running; against\n * a REMOTE one it means a down host, a DNS typo, a dropped VPN/tailscale\n * connection, or (occasionally) an auth redirect that the fetch layer\n * couldn't follow. Only actual network throws get this treatment \u2014 every\n * other error (including ones `describeHttpError` already produced) passes\n * through unchanged so callers can log it without double guidance.\n */\nexport function describeNetworkError(err: unknown, target: AgentApiTarget): string {\n const message = err instanceof Error ? err.message : String(err);\n if (!NETWORK_ERROR_PATTERN.test(message)) return message;\n\n if (LOCAL_URL_RE.test(target.apiBaseUrl)) {\n return \"Is the agent API running? Start it with: mesh dev\";\n }\n\n const loginContext = target.loginContext ?? DEFAULT_AUTH_CONTEXT;\n return (\n `Couldn't reach ${target.apiBaseUrl} \u2014 check the URL/VPN/tailscale, ` +\n `or \\`mesh login ${loginContext}\\` if it's an auth redirect.`\n );\n}\n\n/**\n * Shared, target-aware renderer for a non-ok agent-api response. Used by\n * both `mesh conversations` (list/show/artifacts) and `mesh artifacts get`\n * so there is exactly one place that turns an HTTP failure into human\n * guidance \u2014 no more dev-oriented \"restart the API process\" advice, no more\n * a second parallel renderer for `show`'s 503 special-case.\n *\n * `ctx.id` (a conversation id, when the caller has one) enables the\n * `mesh temporal recover-conversation <id>` hint on a `conversation_unavailable`\n * 503 and is echoed in the 404 message for context.\n *\n * Response shapes are verified against\n * `packages/agent-sdk/src/agent-api/server.ts` \u2014 do not re-infer:\n * - 404 \u2192 `{ error: \"conversation not found\", conversationId }`.\n * - 503 conversation_unavailable \u2192 `{ error: \"conversation_unavailable\",\n * conversationId, detail: \"<text>\" }` \u2014 human text is under `detail`,\n * NOT `message`.\n */\nexport async function describeHttpError(\n res: Response,\n target: AgentApiTarget,\n ctx?: { id?: string },\n): Promise<string> {\n const isRedirect = res.redirected || res.type === \"opaqueredirect\" || res.status === 302;\n if (res.status === 401 || res.status === 403 || isRedirect) {\n const loginContext = target.loginContext ?? DEFAULT_AUTH_CONTEXT;\n return `auth did not reach the agent \u2014 run \\`mesh login ${loginContext}\\``;\n }\n\n if (res.status === 404) {\n const idPart = ctx?.id ? ` (${ctx.id})` : \"\";\n return `conversation/artifact not found${idPart}, or not owned by this identity \u2014 run \\`mesh conversations list\\` to see valid ids.`;\n }\n\n const bodyText = await res.text();\n\n if (res.status === 503) {\n try {\n const parsed = JSON.parse(bodyText) as { error?: string; detail?: string };\n if (parsed.error === \"conversation_unavailable\") {\n const message = parsed.detail ?? bodyText;\n const recoverHint = ctx?.id ? `\\ntry: mesh temporal recover-conversation ${ctx.id}` : \"\";\n return `${message}${recoverHint}`;\n }\n } catch {\n // Not JSON, or not the shape we expect \u2014 fall through to the generic message.\n }\n }\n\n return `agent-api error ${res.status}: ${bodyText || res.statusText} (${target.apiBaseUrl})`;\n}\n", "/**\n * mesh artifacts \u2014 manage workflow artifacts from AI agent conversations\n *\n * Commands:\n * mesh artifacts get <ref> Download artifact files to local directory\n *\n * Ref format: <conversationId>:<artifactId>\n * - Full: mesh artifacts get conv-abc123:workflow-artifact\n * - Short: mesh artifacts get conv-abc123 (defaults to \"workflow-artifact\")\n */\n\nimport { Command } from \"commander\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport { logError, logInfo, logSuccess, logWarn } from \"../utils/log.js\";\nimport { agentApiFetch, describeHttpError, describeNetworkError, resolveTarget, type AgentApiTarget } from \"./agent-api-client.js\";\nconst DEFAULT_ARTIFACT_ID = \"workflow-artifact\";\n\ninterface ExportBundle {\n version: number;\n conversationId: string;\n artifactId: string;\n primaryWorkflow: string;\n overview: string | null;\n files: Array<{\n name: string;\n filename: string;\n code: string;\n }>;\n ir: unknown;\n exportedAt: string;\n}\n\n/**\n * Parse an artifact ref: \"conversationId:artifactId\" or just \"conversationId\".\n */\nfunction parseRef(ref: string): { conversationId: string; artifactId: string } {\n const colonIdx = ref.indexOf(\":\");\n if (colonIdx === -1) {\n return { conversationId: ref, artifactId: DEFAULT_ARTIFACT_ID };\n }\n return {\n conversationId: ref.slice(0, colonIdx),\n artifactId: ref.slice(colonIdx + 1),\n };\n}\n\nconst DEFAULT_AUTH_CONTEXT = \"mesh.dev\";\n\nasync function fetchExportBundle(\n target: AgentApiTarget,\n conversationId: string,\n artifactId: string,\n): Promise<ExportBundle> {\n const apiPath = `/v1/conversations/${encodeURIComponent(conversationId)}/artifacts/${encodeURIComponent(artifactId)}/export`;\n const response = await agentApiFetch(target, apiPath);\n\n if (!response.ok) {\n throw new Error(await describeHttpError(response, target, { id: conversationId }));\n }\n\n return (await response.json()) as ExportBundle;\n}\n\nasync function getArtifact(\n ref: string,\n options: { output?: string },\n target: AgentApiTarget,\n): Promise<void> {\n const { conversationId, artifactId } = parseRef(ref);\n logInfo(`Fetching ${conversationId}:${artifactId} from ${target.apiBaseUrl}\u2026`);\n\n const bundle = await fetchExportBundle(target, conversationId, artifactId);\n // Determine output directory\n const outputDir = options.output\n ?? path.join(\"workflows\", bundle.primaryWorkflow);\n\n // Create directory\n fs.mkdirSync(outputDir, { recursive: true });\n\n let filesWritten = 0;\n\n // Write workflow source files\n for (const file of bundle.files) {\n const filePath = path.join(outputDir, file.filename);\n fs.writeFileSync(filePath, file.code, \"utf-8\");\n logSuccess(` ${file.filename}`);\n filesWritten++;\n }\n\n // Write README.md from overview\n if (bundle.overview) {\n const readmePath = path.join(outputDir, \"README.md\");\n fs.writeFileSync(readmePath, bundle.overview, \"utf-8\");\n logSuccess(` README.md`);\n filesWritten++;\n }\n\n // Write IR as JSON \u2014 always present, essential for IR-only artifacts\n // (from update_workflow) that have no source files.\n if (bundle.ir) {\n const irPath = path.join(outputDir, \"workflow-ir.json\");\n fs.writeFileSync(irPath, JSON.stringify(bundle.ir, null, 2), \"utf-8\");\n logSuccess(` workflow-ir.json`);\n filesWritten++;\n }\n\n // Write metadata file (conversation ref, IR for tooling)\n const metaPath = path.join(outputDir, \".workflow-meta.json\");\n const meta = {\n conversationId: bundle.conversationId,\n artifactId,\n primaryWorkflow: bundle.primaryWorkflow,\n exportedAt: bundle.exportedAt,\n files: bundle.files.map((f) => f.filename),\n };\n fs.writeFileSync(metaPath, JSON.stringify(meta, null, 2), \"utf-8\");\n\n console.log();\n logSuccess(\n `Exported ${filesWritten} files to ${outputDir}/`,\n );\n\n if (bundle.files.length > 1) {\n const primary = bundle.files.find((f) => f.name === bundle.primaryWorkflow);\n if (primary) {\n logInfo(`Entry point: ${primary.filename}`);\n }\n }\n\n logInfo(`Ref: ${conversationId}:${artifactId}`);\n}\n\nexport function registerArtifactsCommands(program: Command): void {\n const artifacts = program\n .command(\"artifacts\")\n .description(\"Manage workflow artifacts from AI agent conversations\");\n\n artifacts\n .command(\"get <ref>\")\n .description(\n \"Download artifact files from an agent conversation\\n\\n\" +\n \"Ref format: <conversationId>:<artifactId>\\n\" +\n ` Short form uses default artifactId \"${DEFAULT_ARTIFACT_ID}\"`,\n )\n .option(\"-o, --output <dir>\", \"Output directory (default: workflows/<workflowName>)\")\n .option(\"--target <name>\", \"Named agent target from the agent-targets registry\")\n .option(\"--api-url <url>\", \"Agent API URL (overrides --target; ad-hoc, no registry lookup)\")\n .option(\"--context <ctx>\", `Zitadel auth context, used with --api-url (default: ${DEFAULT_AUTH_CONTEXT})`)\n .action(async (ref: string, opts: { output?: string; target?: string; apiUrl?: string; context?: string }) => {\n // Resolved outside the try so a network-error catch below can give\n // local-vs-remote-aware guidance (`describeNetworkError` needs the\n // target). If resolution itself throws (bad --target), there's no\n // target to reason about \u2014 just report the resolution error.\n let target: AgentApiTarget;\n try {\n target = resolveTarget(opts);\n } catch (error) {\n logError(error instanceof Error ? error.message : String(error));\n process.exitCode = 1;\n return;\n }\n\n try {\n await getArtifact(ref, opts, target);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n logError(message);\n\n // `describeHttpError` covers every HTTP-level failure mode (auth,\n // not-found, 503, generic) with target-aware messages already baked\n // into the thrown message, so it round-trips through here as `hint\n // === message` and is not re-logged. Only a genuine network throw\n // (ECONNREFUSED/\"fetch failed\"/ENOTFOUND/EAI_AGAIN) \u2014 nothing\n // listening at apiBaseUrl, a down host, a DNS typo, a dropped\n // VPN/tailscale connection \u2014 gets guidance here, and it differs for\n // a local vs. remote target (see `describeNetworkError`).\n const hint = describeNetworkError(error, target);\n if (hint !== message) {\n logWarn(hint);\n logWarn(\"Or specify the URL: mesh artifacts get <ref> --api-url https://your-agent-api.example.com\");\n }\n\n process.exitCode = 1;\n }\n });\n}\n", "/**\n * mesh cluster access \u2014 `mesh kubectl` / `mesh logs` / `mesh exec` against a\n * deployed app's EKS cluster, authenticated as the app's Zitadel deployer role\n * (MESH-2060).\n *\n * Reuses exactly what `mesh dev` already does internally: assume the app's\n * deployer role, build a session kubeconfig from the platform `eks` SSM export\n * (`aws eks get-token` \u2014 needs neither `eks:DescribeCluster` nor a readable\n * `~/.kube/config`, which macOS TCC blocks for non-FDA shells), and shell out to\n * kubectl with `KUBECONFIG` set.\n *\n * The deployer role's cluster RBAC is namespace-scoped to the tenant's\n * namespaces (verified live: the `<tenant>-<env>-deployers` group grants\n * pods/log/exec read in the app's namespace), so every command defaults to the\n * app's own namespace and callers can still `-n <other>` within the tenant.\n */\n\nimport { spawnSync } from \"node:child_process\";\nimport { Command } from \"commander\";\nimport { logError, logInfo } from \"../utils/log.js\";\nimport {\n findAppRoot,\n findStackConfigs,\n getCurrentStack,\n pulumiStackOutput,\n readStackConfig,\n} from \"../utils/pulumi.js\";\nimport { resolveAwsCredentials, derivePlatformContext } from \"../utils/aws-auth.js\";\nimport {\n ensureKubeconfig,\n resolveHubPlatformName,\n type EnsureKubeconfigFailure,\n} from \"../utils/kubeconfig.js\";\nimport { probeCredentials } from \"./login.js\";\nimport { credProbeToPreflightError } from \"../utils/pulumi-run.js\";\n\ninterface ClusterAccess {\n kubeconfigPath: string;\n namespace: string;\n stack: string;\n}\n\n/**\n * Assume the app's deployer role, resolve the deployed app's platform env +\n * namespace from stack output, and materialize a session kubeconfig. Throws with\n * an actionable message on any failure (missing app dir, unresolved creds,\n * undeployed stack, unresolvable cluster).\n */\nasync function resolveClusterAccess(opts: { stack?: string }): Promise<ClusterAccess> {\n const appRoot = findAppRoot(process.cwd());\n if (!appRoot) {\n throw new Error(\n \"Not in a Mesh app directory (no Pulumi.yaml found). Run from an app directory.\",\n );\n }\n const stack = opts.stack ?? getCurrentStack(appRoot);\n if (!stack) {\n const stacks = findStackConfigs(appRoot);\n throw new Error(\n \"No Pulumi stack selected.\\n\" +\n (stacks.length > 0\n ? `Available: ${stacks.join(\", \")}\\nUse --stack <name> (the deployed stack, e.g. dev).`\n : \"No stack configs found in this directory.\"),\n );\n }\n const sa = [\"--stack\", stack];\n\n // Assume the app's deployer role \u2014 same path as `mesh dev` / `mesh temporal`.\n const deployerRole = readStackConfig(appRoot, stack, \"mesh:deployerRole\");\n const ctx = derivePlatformContext(appRoot, stack);\n const resolved = deployerRole\n ? await resolveAwsCredentials(deployerRole, appRoot, stack)\n : null;\n // Login preflight: name the credential problem up front instead of failing\n // deep inside the kubectl `aws eks get-token` exec plugin.\n if (deployerRole && !resolved && !process.env.AWS_ACCESS_KEY_ID) {\n const pf = ctx\n ? credProbeToPreflightError(await probeCredentials(ctx, deployerRole), ctx)\n : null;\n throw new Error(\n pf?.message ??\n `Couldn't resolve AWS credentials. Run: mesh login ${ctx ?? \"mesh.dev\"} --device`,\n );\n }\n const awsEnv = resolved?.env;\n const region = readStackConfig(appRoot, stack, \"aws:region\");\n if (awsEnv && region && !awsEnv.AWS_REGION) awsEnv.AWS_REGION = region;\n // Thread the resolved creds into this process so ensureKubeconfig's SSM read\n // and the kubectl `aws eks get-token` exec plugin run credentialed.\n if (awsEnv) Object.assign(process.env, awsEnv);\n\n // Read the deployed app output for platform env + namespace (mirrors the\n // reader in `mesh temporal`; the `app` struct's `dev` field is secret-tainted,\n // and pulumiStackOutput transparently retries with --show-secrets).\n let appOutput: { namespace?: string; app?: string; dev?: DevishOutput } & DevishOutput;\n let devOutput: DevishOutput;\n try {\n appOutput = JSON.parse(pulumiStackOutput(appRoot, \"app\", sa, awsEnv));\n devOutput = appOutput.dev ?? appOutput;\n } catch {\n try {\n devOutput = JSON.parse(pulumiStackOutput(appRoot, \"dev\", sa, awsEnv));\n appOutput = devOutput;\n } catch {\n throw new Error(\n `Could not read stack output for '${stack}'. Ensure the app is deployed: mesh deploy up`,\n );\n }\n }\n const platformEnv = devOutput?.platform?.env ?? \"dev\";\n // The HUB platform name (e.g. \"trabian\") \u2014 cluster data lives under it, not\n // under a hardcoded \"mesh\" (MESH-2515). Same axis `mesh dev` uses for the\n // bastion; \"mesh\" is only the default hub.\n const platformName = resolveHubPlatformName(devOutput?.platform);\n const namespace = appOutput?.namespace ?? devOutput?.namespace;\n if (!namespace) {\n throw new Error(`No namespace found in stack output for '${stack}'.`);\n }\n\n // Build a session kubeconfig from the platform eks SSM export. Key the session\n // file on platformName + platformEnv too, so two apps on DIFFERENT platforms\n // that share a stack name (e.g. both \"dev\") don't race on the same kubeconfig\n // path.\n let failure: EnsureKubeconfigFailure | undefined;\n const kubeconfigPath = await ensureKubeconfig(\n platformName,\n platformEnv,\n `mesh-cluster-${platformName}-${platformEnv}-${stack}`,\n { onError: (f) => (failure = f) },\n );\n if (!kubeconfigPath) {\n throw new Error(clusterResolveErrorMessage(platformName, platformEnv, failure));\n }\n return { kubeconfigPath, namespace, stack };\n}\n\n/**\n * Render the \"couldn't resolve the EKS cluster\" failure with the parameter\n * tried and the real exception. The pre-MESH-2515 message guessed \"you have\n * SSM read access\" at every failure \u2014 which sent three investigations after a\n * permission that was never missing when the actual cause was the wrong\n * platform name in the SSM path.\n */\nexport function clusterResolveErrorMessage(\n platformName: string,\n platformEnv: string,\n failure?: EnsureKubeconfigFailure,\n): string {\n const parameter = failure?.parameter ?? `/mesh-platform/${platformName}/${platformEnv}/core/eks`;\n const err = failure?.error;\n const detail =\n err instanceof Error\n ? `${err.name}: ${err.message}`\n : err !== undefined\n ? String(err)\n : \"no cluster data returned\";\n return (\n `Could not resolve the EKS cluster for platform '${platformName}/${platformEnv}' from SSM.\\n` +\n ` Parameter tried: ${parameter}\\n` +\n ` Failure: ${detail}\\n` +\n \"If this platform name is wrong, check the app's `mesh:platform` stack config \" +\n \"(the hub platform name, e.g. `trabian`) \u2014 an AccessDeniedException here usually \" +\n \"means the WRONG platform path, not missing SSM permissions.\"\n );\n}\n\ninterface DevishOutput {\n namespace?: string;\n app?: string;\n platform?: { env?: string; tenant?: string; name?: string };\n}\n\nconst NS_FLAGS = new Set([\"-n\", \"--namespace\", \"-A\", \"--all-namespaces\"]);\n/**\n * Whether the user already scoped the namespace. Deliberately only detects the\n * split forms (`-n foo`, `--namespace foo`, `--namespace=foo`, `-A`), NOT the\n * smashed short form `-nfoo`: our default `-n <ns>` is PREPENDED, and kubectl's\n * pflag lets the later (user-supplied) `-nfoo` win, so a missed detection here is\n * harmless. Do not \"fix\" this into an append \u2014 that would let our default win\n * over the user's intent.\n */\nexport function hasNamespaceFlag(args: string[]): boolean {\n return args.some((a) => NS_FLAGS.has(a) || a.startsWith(\"--namespace=\"));\n}\n\n/**\n * Run kubectl with the session kubeconfig, defaulting the namespace to the app's\n * own unless the caller already scoped it. Returns the child exit code.\n */\nfunction runKubectl(\n access: ClusterAccess,\n args: string[],\n opts: { defaultNamespace?: boolean } = {},\n): number {\n const finalArgs =\n opts.defaultNamespace !== false && !hasNamespaceFlag(args)\n ? [\"-n\", access.namespace, ...args]\n : args;\n const res = spawnSync(\"kubectl\", finalArgs, {\n stdio: \"inherit\",\n env: { ...process.env, KUBECONFIG: access.kubeconfigPath },\n });\n if (res.error) {\n const e = res.error as NodeJS.ErrnoException;\n if (e.code === \"ENOENT\") {\n logError(\"kubectl not found on PATH. Install kubectl to use mesh cluster commands.\");\n } else {\n logError(`Failed to run kubectl: ${e.message}`);\n }\n return 1;\n }\n return res.status ?? 0;\n}\n\n/**\n * Translate an ergonomic log/exec target into kubectl selector args.\n * - `deployment/x` / `pod/x` (contains `/`) \u2192 passed through\n * - `k=v` (contains `=`) \u2192 label selector `-l k=v`\n * - bare `<service>` \u2192 `-l app=<service>` (the reliable\n * per-service label; deployment names == service names)\n */\nexport function targetToSelector(target: string): string[] {\n if (target.includes(\"/\")) return [target];\n if (target.includes(\"=\")) return [\"-l\", target];\n return [\"-l\", `app=${target}`];\n}\n\nexport function registerClusterCommands(program: Command): void {\n // `mesh kubectl [args\u2026]` \u2014 passthrough. Help is delegated to kubectl so\n // `mesh kubectl get --help` works; run `mesh kubectl` with no args to see it.\n program\n .command(\"kubectl\")\n .description(\"Run kubectl against the app's cluster (deployer role + SSM kubeconfig)\")\n .option(\"--stack <stack>\", \"Deployed Pulumi stack (default: current selection)\")\n .allowUnknownOption(true)\n // Forward every positional (kubectl subcommand + args) verbatim. Commander\n // v13 flips the default to ERROR on excess args, so declare it explicitly \u2014\n // a routine dependency bump must not silently break the passthrough.\n .allowExcessArguments(true)\n .helpOption(false)\n .action(async (opts: { stack?: string }, cmd: Command) => {\n try {\n const access = await resolveClusterAccess({ stack: opts.stack });\n // Context line to stderr so stdout stays clean for piping.\n process.stderr.write(\n `\u2192 kubectl \u00B7 ns ${access.namespace} \u00B7 stack ${access.stack}\\n`,\n );\n process.exit(runKubectl(access, cmd.args));\n } catch (e) {\n logError((e as Error).message);\n process.exit(1);\n }\n });\n\n // `mesh logs [target]` \u2014 ergonomic kubectl logs against the app's namespace.\n program\n .command(\"logs [target]\")\n .description(\"Tail logs from the app's pods (kubectl logs; target = service, deployment/x, or k=v)\")\n .option(\"--stack <stack>\", \"Deployed Pulumi stack (default: current selection)\")\n .option(\"-f, --follow\", \"Stream new logs\")\n .option(\"--tail <n>\", \"Lines from the end of the logs\", \"200\")\n .option(\"-c, --container <name>\", \"Container name\")\n .option(\"--previous\", \"Logs from the previous container instance (crash debugging)\")\n .action(\n async (\n target: string | undefined,\n opts: { stack?: string; follow?: boolean; tail?: string; container?: string; previous?: boolean },\n ) => {\n try {\n const access = await resolveClusterAccess({ stack: opts.stack });\n if (!target) {\n logInfo(\n `Which service? Pods in ${access.namespace}:\\n` +\n \"Then: mesh logs <service> (e.g. mesh logs demo-agent-worker)\\n\",\n );\n process.exit(runKubectl(access, [\"get\", \"pods\"]));\n }\n const kargs = [\"logs\", ...targetToSelector(target), \"--prefix\", \"--tail\", opts.tail ?? \"200\"];\n if (opts.follow) kargs.push(\"-f\");\n if (opts.container) kargs.push(\"-c\", opts.container);\n if (opts.previous) kargs.push(\"--previous\");\n process.exit(runKubectl(access, kargs));\n } catch (e) {\n logError((e as Error).message);\n process.exit(1);\n }\n },\n );\n\n // `mesh exec <target> -- <cmd\u2026>` \u2014 exec into one of the app's pods.\n program\n .command(\"exec <target> [cmd...]\")\n .description(\"Exec a command in the app's pod (kubectl exec; target = service or deployment/x)\")\n .option(\"--stack <stack>\", \"Deployed Pulumi stack (default: current selection)\")\n .option(\"-c, --container <name>\", \"Container name\")\n .action(\n async (\n target: string,\n cmdParts: string[],\n opts: { stack?: string; container?: string },\n ) => {\n try {\n const access = await resolveClusterAccess({ stack: opts.stack });\n // exec needs a single pod; a bare service resolves to its deployment.\n const podRef = target.includes(\"/\") ? target : `deployment/${target}`;\n const command = cmdParts.length > 0 ? cmdParts : [\"sh\"];\n const kargs = [\"exec\"];\n kargs.push(process.stdout.isTTY ? \"-it\" : \"-i\");\n kargs.push(podRef);\n if (opts.container) kargs.push(\"-c\", opts.container);\n kargs.push(\"--\", ...command);\n process.exit(runKubectl(access, kargs));\n } catch (e) {\n logError((e as Error).message);\n process.exit(1);\n }\n },\n );\n}\n", "/**\n * Builds the `enrichVcs` dep for `mesh conversations pull` by resolving a\n * token + vcs URL for the target, then delegating to the shared\n * `createVcsFolderReader` in `@mesh-tech/agent-targets` (same folder logic the\n * MCP `agent_pull_conversation` tool uses).\n */\nimport { createVcsFolderReader, deriveVcsBaseUrl, type VcsFolderReader } from \"@mesh-tech/agent-targets\";\nimport type { AgentApiTarget } from \"./agent-api-client.js\";\nimport { getValidToken } from \"./login.js\";\nimport { logWarn } from \"../utils/log.js\";\n\n/**\n * Resolve a token + vcs base URL for `target`, returning a `VcsFolderReader`\n * ({ enrichVcs, cleanup }) or `undefined` (with a warning) when no token or vcs\n * URL can be derived \u2014 so the pull proceeds IR-only rather than failing.\n */\nexport async function buildVcsEnricher(target: AgentApiTarget): Promise<VcsFolderReader | undefined> {\n const vcsBaseUrl = deriveVcsBaseUrl(target.apiBaseUrl);\n if (!vcsBaseUrl) {\n logWarn(`could not derive a vcs URL from ${target.apiBaseUrl}; skipping design-folder enrichment (--no-vcs to silence)`);\n return undefined;\n }\n const token = target.token ?? (await getValidToken(target.loginContext ?? \"mesh.dev\"));\n if (!token) {\n logWarn(`no vcs token for context \"${target.loginContext ?? \"mesh.dev\"}\"; skipping design-folder enrichment`);\n return undefined;\n }\n return createVcsFolderReader({ vcsBaseUrl, token });\n}\n", "/**\n * mesh conversations \u2014 read a deployed Mesh agent's conversations\n *\n * Commands:\n * mesh conversations list List conversations visible to the caller\n * mesh conversations show <id> Render a conversation's transcript\n * mesh conversations artifacts <id> List a conversation's artifacts\n *\n * Discovery-first: resolves a target (registry name, --api-url, or\n * fallback) via `resolveTarget`/`agentApiFetch` (Task 3) and renders a\n * table (TTY) or JSON (piped / --json).\n */\n\nimport { Command } from \"commander\";\n// renderMessageContent is needed synchronously by the exported formatter;\n// safe at top level since agent-targets' exports are source-mapped. The\n// heavy pull/writeBundle pair stays lazily imported in the pull action.\nimport { renderMessageContent } from \"@mesh-tech/agent-targets\";\nimport { buildVcsEnricher } from \"./vcs-enrich.js\";\nimport { logError, logInfo, logWarn } from \"../utils/log.js\";\nimport {\n agentApiFetch,\n describeHttpError,\n describeNetworkError,\n resolveTarget,\n TargetResolutionError,\n type AgentApiTarget,\n} from \"./agent-api-client.js\";\n\nexport interface ConversationSummary {\n id: string;\n title?: string;\n updatedAt?: string;\n lastUpdated?: string;\n}\n\nconst MAX_TITLE_LEN = 40;\n\nfunction truncate(s: string, max: number): string {\n return s.length > max ? s.slice(0, max - 1) + \"\u2026\" : s;\n}\n\n/**\n * Pure formatter: JSON verbatim (compact \u2014 agents parse this, so it's kept\n * dense rather than pretty-printed) when `asJson`, else a simple aligned\n * ID/TITLE/UPDATED table. Tolerant of missing title/updatedAt/lastUpdated\n * and an empty list.\n */\nexport function formatConversations(list: ConversationSummary[], asJson: boolean): string {\n if (asJson) {\n return JSON.stringify(list);\n }\n\n if (list.length === 0) {\n return \"(no conversations)\";\n }\n\n const rows = list.map((c) => ({\n id: c.id ?? \"\",\n title: truncate(c.title ?? \"\", MAX_TITLE_LEN),\n updated: c.updatedAt ?? c.lastUpdated ?? \"\",\n }));\n\n const idWidth = Math.max(\"ID\".length, ...rows.map((r) => r.id.length));\n const titleWidth = Math.max(\"TITLE\".length, ...rows.map((r) => r.title.length));\n\n const pad = (s: string, width: number) => s.padEnd(width);\n\n const header = `${pad(\"ID\", idWidth)} ${pad(\"TITLE\", titleWidth)} UPDATED`;\n const lines = rows.map((r) => `${pad(r.id, idWidth)} ${pad(r.title, titleWidth)} ${r.updated}`);\n\n return [header, ...lines].join(\"\\n\");\n}\n\nexport interface TranscriptMessage {\n role: string;\n /** Plain string, or an AI SDK array of content parts (rendered via renderMessageContent). */\n content?: unknown;\n /** Present on assistant turns that invoked tools; shape varies by agent-sdk version. */\n toolCalls?: unknown[];\n /** Artifact ids/refs produced or referenced by this turn. */\n artifactRefs?: unknown[];\n}\n\nexport interface TranscriptBody {\n messages?: TranscriptMessage[];\n}\n\n/** Compact a list of tool-call/artifact-ref entries to a comma-joined summary. */\nfunction summarizeRefs(items: unknown[]): string {\n return items\n .map((item) => {\n if (typeof item === \"string\") return item;\n if (item && typeof item === \"object\") {\n const rec = item as Record<string, unknown>;\n const label = rec.id ?? rec.name ?? rec.toolName;\n if (typeof label === \"string\") return label;\n }\n return \"?\";\n })\n .join(\", \");\n}\n\n/**\n * Pure formatter: JSON verbatim (compact) when `asJson`, else one `role:\n * content` block per message (blank-line separated). Tolerant of a missing\n * `content` (renders `role: ` with nothing after it) and an empty/missing\n * `messages` array. When a message carries `toolCalls`/`artifactRefs`, notes\n * them compactly on an indented line beneath the block.\n */\nexport function formatTranscript(body: TranscriptBody, asJson: boolean): string {\n if (asJson) {\n return JSON.stringify(body);\n }\n\n const messages = body.messages ?? [];\n if (messages.length === 0) {\n return \"(no messages)\";\n }\n\n return messages\n .map((m) => {\n const lines = [`${m.role}: ${renderMessageContent(m.content)}`];\n if (Array.isArray(m.toolCalls) && m.toolCalls.length > 0) {\n lines.push(` tool-calls: ${summarizeRefs(m.toolCalls)}`);\n }\n if (Array.isArray(m.artifactRefs) && m.artifactRefs.length > 0) {\n lines.push(` artifacts: ${summarizeRefs(m.artifactRefs)}`);\n }\n return lines.join(\"\\n\");\n })\n .join(\"\\n\\n\");\n}\n\nexport interface ArtifactSummary {\n id: string;\n kind?: string;\n title?: string;\n}\n\n/**\n * Pure formatter: JSON verbatim (compact) when `asJson`, else an\n * `ARTIFACT-ID \u00B7 KIND \u00B7 TITLE` table plus a trailing download hint (using\n * `refHint` \u2014 the conversation id \u2014 and the first artifact's id as the\n * copy-pasteable example). Tolerant of missing kind/title and an empty list\n * (no download hint when there's nothing to download).\n */\nexport function formatArtifacts(list: ArtifactSummary[], asJson: boolean, refHint: string): string {\n if (asJson) {\n return JSON.stringify(list);\n }\n\n if (list.length === 0) {\n return \"(no artifacts)\";\n }\n\n const rows = list.map((a) => ({\n id: a.id ?? \"\",\n kind: a.kind ?? \"\",\n title: a.title ?? \"\",\n }));\n\n const idWidth = Math.max(\"ARTIFACT-ID\".length, ...rows.map((r) => r.id.length));\n const kindWidth = Math.max(\"KIND\".length, ...rows.map((r) => r.kind.length));\n const pad = (s: string, width: number) => s.padEnd(width);\n\n const header = `${pad(\"ARTIFACT-ID\", idWidth)} \u00B7 ${pad(\"KIND\", kindWidth)} \u00B7 TITLE`;\n const lines = rows.map((r) => `${pad(r.id, idWidth)} \u00B7 ${pad(r.kind, kindWidth)} \u00B7 ${r.title}`);\n const exampleId = rows[0]?.id ?? \"\";\n\n return [header, ...lines, \"\", `Download: mesh artifacts get ${refHint}:${exampleId}`].join(\"\\n\");\n}\n\ninterface ConversationCmdOpts {\n target?: string;\n apiUrl?: string;\n context?: string;\n json?: boolean;\n}\n\ninterface PullCmdOpts extends ConversationCmdOpts {\n output?: string;\n /** commander sets these false when `--no-recursive` / `--no-vcs` is passed (default true). */\n recursive?: boolean;\n vcs?: boolean;\n}\n\n/** Add the shared `--target/--api-url/--context/--json` option set (same across list/show/artifacts). */\nfunction withTargetOptions(cmd: Command): Command {\n return cmd\n .option(\"--target <name>\", \"Named agent target from the agent-targets registry\")\n .option(\"--api-url <url>\", \"Agent API URL (overrides --target; ad-hoc, no registry lookup)\")\n .option(\"--context <ctx>\", \"Zitadel auth context, used with --api-url (default: mesh.dev)\")\n .option(\"--json\", \"Emit JSON (default when stdout is not a TTY)\");\n}\n\n/**\n * Shared resolve \u2192 fetch \u2192 format \u2192 print flow for a conversations verb.\n * `ctx.id` (the conversation id, when the verb has one) is passed through to\n * `describeHttpError` so it can echo it in the 404 message and offer the\n * `mesh temporal recover-conversation <id>` hint on a 503\n * `conversation_unavailable` response (formerly `show`'s own special-case;\n * now folded into the one shared renderer).\n */\nasync function runConversationsVerb<T>(\n opts: ConversationCmdOpts,\n apiPath: string,\n format: (body: T, asJson: boolean) => string,\n ctx?: { id?: string },\n): Promise<void> {\n // Declared outside the try so a network-error catch can give\n // local-vs-remote-aware guidance (`describeNetworkError` needs the\n // target); stays undefined if `resolveTarget` itself is what threw.\n let target: AgentApiTarget | undefined;\n try {\n target = resolveTarget(opts);\n const res = await agentApiFetch(target, apiPath);\n\n if (!res.ok) {\n throw new Error(await describeHttpError(res, target, ctx));\n }\n\n const body = (await res.json()) as T;\n const asJson = opts.json ?? !process.stdout.isTTY;\n process.stdout.write(format(body, asJson) + \"\\n\");\n } catch (error) {\n reportCliError(error, target);\n }\n}\n\n/**\n * Symmetric with `mesh artifacts get`'s catch: `describeHttpError` failures\n * already carry target-aware guidance in their message (so `hint === message`\n * and nothing further is logged), while a genuine network throw\n * (ECONNREFUSED/\"fetch failed\"/ENOTFOUND/EAI_AGAIN) gets an extra\n * local-vs-remote hint via `describeNetworkError`.\n */\nfunction reportCliError(error: unknown, target?: AgentApiTarget): void {\n if (error instanceof TargetResolutionError) {\n logError(error.message);\n } else {\n const message = error instanceof Error ? error.message : String(error);\n logError(message);\n\n if (target) {\n const hint = describeNetworkError(error, target);\n if (hint !== message) logWarn(hint);\n }\n }\n process.exitCode = 1;\n}\n\nexport function registerConversationsCommands(program: Command): void {\n const group = program\n .command(\"conversations\")\n .alias(\"conv\")\n .description(\"Read a deployed Mesh agent's conversations (list, show, artifacts)\");\n\n withTargetOptions(\n group\n .command(\"list\")\n .description(\"List the caller's conversations on an agent target\"),\n ).action(async (opts: ConversationCmdOpts) => {\n await runConversationsVerb(opts, \"/v1/conversations\", (body: { conversations?: ConversationSummary[] }, asJson) =>\n formatConversations(body.conversations ?? [], asJson),\n );\n });\n\n withTargetOptions(\n group\n .command(\"show <id>\")\n .description(\"Render a conversation's transcript\"),\n ).action(async (id: string, opts: ConversationCmdOpts) => {\n await runConversationsVerb(\n opts,\n `/v1/conversations/${encodeURIComponent(id)}`,\n (body: TranscriptBody, asJson) => formatTranscript(body, asJson),\n { id },\n );\n });\n\n withTargetOptions(\n group\n .command(\"artifacts <id>\")\n .description(\"List a conversation's artifacts\"),\n ).action(async (id: string, opts: ConversationCmdOpts) => {\n await runConversationsVerb(\n opts,\n `/v1/conversations/${encodeURIComponent(id)}/artifacts`,\n (body: { artifacts?: ArtifactSummary[] }, asJson) => formatArtifacts(body.artifacts ?? [], asJson, id),\n { id },\n );\n });\n\n group\n .command(\"pull <id>\")\n .description(\"Pull a conversation + its designs/UI + recursive subagent transcripts into a bundle\")\n .option(\"--target <name>\", \"Named agent target from the agent-targets registry\")\n .option(\"--api-url <url>\", \"Agent API URL (overrides --target)\")\n .option(\"--context <ctx>\", \"Zitadel auth context (default: mesh.dev)\")\n .option(\"-o, --output <dir>\", \"Write the bundle directory here (prints JSON when omitted)\")\n .option(\"--no-recursive\", \"Only pull direct subagents (default: recurse the delegate tree)\")\n .option(\"--no-vcs\", \"Skip pulling each design's own vcs folder (docs/manifest); IR-only\")\n .action(async (id: string, opts: PullCmdOpts) => {\n // Lazy: an unbuilt/unresolvable agent-targets must degrade only this\n // command, never brick the whole CLI at boot (src/program.ts imports all\n // command modules eagerly).\n const { pullConversation, writeBundle } = await import(\"@mesh-tech/agent-targets\");\n let target: AgentApiTarget | undefined;\n let enricher: Awaited<ReturnType<typeof buildVcsEnricher>>;\n try {\n target = resolveTarget(opts);\n const resolved = target;\n enricher = opts.vcs === false ? undefined : await buildVcsEnricher(resolved);\n const bundle = await pullConversation(\n { fetchApi: (apiPath: string) => agentApiFetch(resolved, apiPath), enrichVcs: enricher?.enrichVcs },\n id,\n { recursive: opts.recursive !== false, hintTarget: opts.target },\n );\n if (opts.output) {\n const written = await writeBundle(bundle, opts.output);\n logInfo(`wrote ${written.length} files \u2192 ${opts.output}`);\n if (bundle.warnings.length) {\n logWarn(\n `${bundle.warnings.length} warning(s): ${bundle.warnings\n .map((w) => `${w.stage}:${w.ref ?? \"\"}`)\n .join(\", \")}`,\n );\n }\n } else {\n process.stdout.write(JSON.stringify(bundle) + \"\\n\");\n }\n } catch (error) {\n reportCliError(error, target);\n } finally {\n await enricher?.cleanup();\n }\n });\n}\n", "/**\n * mesh skills sync \u2014 agent-skill distribution (design \u00A77.2, AC D1/D2).\n *\n * Two layers, one command:\n *\n * 1. BASE skills (how to build with Mesh \u2014 the CLI's own skills/) are\n * installed into the repo's `.claude/skills/mesh-<name>/SKILL.md`.\n * CLI-managed: files carry a managed marker and are only overwritten\n * when they carry it (hand-edited copies are left alone with a warning).\n *\n * 2. PACKAGE skills (patterns shipping inside @mesh-tech/* dependencies,\n * TanStack-Intent-discoverable) surface via the Intent gate: the exact\n * hook mechanism mesh-platform committed in PR #2356, vendored into the\n * CLI (deterministic, offline \u2014 no interactive installer):\n * - .intent/hooks/intent-claude-gate.mjs (SessionStart catalog +\n * edit gate; invokes the REPO-PINNED `pnpm exec intent`)\n * - .claude/settings.json SessionStart hook (JSON-merged, idempotent)\n * - AGENTS.md fence (<!-- intent-skills:start/end -->) for\n * non-Claude agents\n *\n * `mesh skills sync --check` is the CI/doctor form: exits 1 listing what is\n * missing or stale, changes nothing. `mesh create-app` runs a best-effort\n * sync after scaffolding so a fresh Claude session in a fresh repo sees both\n * skill layers with zero manual setup (D1).\n */\n\nimport { Command } from \"commander\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport { execFileSync } from \"child_process\";\nimport { logInfo, logSuccess, logWarn } from \"../utils/log.js\";\nimport { MeshCliError } from \"../utils/errors.js\";\nimport { findPackageRoot } from \"./local/stack.js\";\n\nconst MANAGED_MARKER = \"<!-- managed-by: mesh skills sync \u2014 edits are overwritten; copy content elsewhere to customize -->\";\nconst FENCE_START = \"<!-- intent-skills:start -->\";\nconst HOOK_RELATIVE = path.join(\".intent\", \"hooks\", \"intent-claude-gate.mjs\");\n\n/** The repo root skills sync targets: the enclosing git root, else cwd. */\nexport function resolveTargetRoot(startDir = process.cwd()): string {\n try {\n return execFileSync(\"git\", [\"rev-parse\", \"--show-toplevel\"], {\n cwd: startDir,\n encoding: \"utf-8\",\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n }).trim();\n } catch {\n return startDir;\n }\n}\n\nfunction cliAsset(...segments: string[]): string {\n return path.join(findPackageRoot(), ...segments);\n}\n\n/** Base skills shipped in the CLI package (skills/<name>/SKILL.md). */\nfunction listBaseSkills(): Array<{ name: string; source: string }> {\n const dir = cliAsset(\"skills\");\n if (!fs.existsSync(dir)) return [];\n return fs\n .readdirSync(dir, { withFileTypes: true })\n .filter((entry) => entry.isDirectory() && fs.existsSync(path.join(dir, entry.name, \"SKILL.md\")))\n .map((entry) => ({ name: entry.name, source: path.join(dir, entry.name, \"SKILL.md\") }));\n}\n\n/** Managed content = source SKILL.md with the marker after its frontmatter. */\nfunction renderManagedSkill(source: string): string {\n const raw = fs.readFileSync(source, \"utf-8\");\n const frontmatter = raw.match(/^(---\\n[\\s\\S]*?\\n---\\n)/)?.[1];\n if (!frontmatter) return `${MANAGED_MARKER}\\n\\n${raw}`;\n return `${frontmatter}\\n${MANAGED_MARKER}\\n${raw.slice(frontmatter.length)}`;\n}\n\ninterface SyncItem {\n label: string;\n /** \"ok\" | \"write\" (missing/stale, sync will fix) | \"skip\" (hand-edited) */\n state: \"ok\" | \"write\" | \"skip\";\n apply?: () => void;\n}\n\nfunction planSync(root: string): SyncItem[] {\n const items: SyncItem[] = [];\n\n // 1. Base skills \u2192 .claude/skills/mesh-<name>/SKILL.md\n for (const skill of listBaseSkills()) {\n const target = path.join(root, \".claude\", \"skills\", `mesh-${skill.name}`, \"SKILL.md\");\n const desired = renderManagedSkill(skill.source);\n const label = `.claude/skills/mesh-${skill.name}/SKILL.md (base skill)`;\n if (!fs.existsSync(target)) {\n items.push({\n label,\n state: \"write\",\n apply: () => {\n fs.mkdirSync(path.dirname(target), { recursive: true });\n fs.writeFileSync(target, desired);\n },\n });\n } else {\n const current = fs.readFileSync(target, \"utf-8\");\n if (current === desired) {\n items.push({ label, state: \"ok\" });\n } else if (current.includes(MANAGED_MARKER)) {\n items.push({ label, state: \"write\", apply: () => fs.writeFileSync(target, desired) });\n } else {\n items.push({ label: `${label} \u2014 exists without the managed marker, leaving as-is`, state: \"skip\" });\n }\n }\n }\n\n // 2. Intent gate hook (CLI-managed generated file \u2014 kept current)\n const hookSource = cliAsset(\"assets\", \"intent\", \"intent-claude-gate.mjs\");\n const hookTarget = path.join(root, HOOK_RELATIVE);\n const hookDesired = fs.readFileSync(hookSource, \"utf-8\");\n const hookCurrent = fs.existsSync(hookTarget) ? fs.readFileSync(hookTarget, \"utf-8\") : null;\n items.push(\n hookCurrent === hookDesired\n ? { label: `${HOOK_RELATIVE} (Intent gate)`, state: \"ok\" }\n : {\n label: `${HOOK_RELATIVE} (Intent gate)`,\n state: \"write\",\n apply: () => {\n fs.mkdirSync(path.dirname(hookTarget), { recursive: true });\n fs.writeFileSync(hookTarget, hookDesired, { mode: 0o755 });\n },\n },\n );\n\n // 3. .claude/settings.json SessionStart hook (JSON merge, idempotent)\n const settingsPath = path.join(root, \".claude\", \"settings.json\");\n let settings: any = {};\n try {\n settings = JSON.parse(fs.readFileSync(settingsPath, \"utf-8\"));\n } catch {\n settings = {};\n }\n const sessionStart: any[] = settings?.hooks?.SessionStart ?? [];\n const hasHook = sessionStart.some((entry: any) =>\n (entry?.hooks ?? []).some((h: any) => JSON.stringify(h?.args ?? h?.command ?? \"\").includes(\"intent-claude-gate.mjs\")),\n );\n items.push(\n hasHook\n ? { label: \".claude/settings.json (SessionStart Intent hook)\", state: \"ok\" }\n : {\n label: \".claude/settings.json (SessionStart Intent hook)\",\n state: \"write\",\n apply: () => {\n settings.hooks = settings.hooks ?? {};\n settings.hooks.SessionStart = settings.hooks.SessionStart ?? [];\n settings.hooks.SessionStart.push({\n matcher: \"startup|resume|clear|compact\",\n hooks: [\n {\n type: \"command\",\n command: \"node\",\n args: [\"${CLAUDE_PROJECT_DIR}/.intent/hooks/intent-claude-gate.mjs\"],\n timeout: 10,\n statusMessage: \"Loading Intent skill catalog\",\n },\n ],\n });\n fs.mkdirSync(path.dirname(settingsPath), { recursive: true });\n fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 1) + \"\\n\");\n },\n },\n );\n\n // 4. AGENTS.md fence (non-Claude agents discover Intent skills too)\n const agentsPath = path.join(root, \"AGENTS.md\");\n const fence = fs.readFileSync(cliAsset(\"assets\", \"intent\", \"agents-fence.md\"), \"utf-8\");\n const agentsCurrent = fs.existsSync(agentsPath) ? fs.readFileSync(agentsPath, \"utf-8\") : null;\n items.push(\n agentsCurrent?.includes(FENCE_START)\n ? { label: \"AGENTS.md (intent-skills fence)\", state: \"ok\" }\n : {\n label: \"AGENTS.md (intent-skills fence)\",\n state: \"write\",\n apply: () => {\n const next = agentsCurrent ? `${fence}\\n${agentsCurrent}` : `${fence}\\n# Agent Instructions\\n`;\n fs.writeFileSync(agentsPath, next);\n },\n },\n );\n\n return items;\n}\n\n/** Run a sync (or check). Returns true when everything is in place. */\nexport function syncSkills(root: string, opts: { check?: boolean } = {}): boolean {\n const items = planSync(root);\n let dirty = false;\n for (const item of items) {\n if (item.state === \"ok\") continue;\n if (item.state === \"skip\") {\n logWarn(item.label);\n continue;\n }\n dirty = true;\n if (opts.check) {\n logWarn(`missing/stale: ${item.label}`);\n } else {\n item.apply?.();\n logSuccess(`synced: ${item.label}`);\n }\n }\n if (!dirty) {\n logInfo(`Agent skills are in sync (${root})`);\n }\n return !dirty;\n}\n\nexport function registerSkillsCommands(program: Command): void {\n const skills = program.command(\"skills\").description(\"Agent-skill distribution (base skills + Intent discovery)\");\n\n skills\n .command(\"sync\")\n .description(\n \"Install the base building-with-Mesh skills into .claude/skills/ and wire TanStack-Intent discovery (hook + settings + AGENTS.md fence) for package skills\",\n )\n .option(\"--check\", \"verify only (CI/doctor): exit 1 when anything is missing or stale\", false)\n .option(\"--root <path>\", \"target repo root (default: enclosing git root)\")\n .action((opts: { check: boolean; root?: string }) => {\n const root = path.resolve(opts.root ?? resolveTargetRoot());\n const ok = syncSkills(root, { check: opts.check });\n if (opts.check && !ok) {\n throw new MeshCliError(\"Agent skills are missing or stale.\", {\n remediation: { command: \"mesh skills sync\" },\n });\n }\n });\n}\n", "/**\n * mesh create-app - Scaffold a new tenant application\n *\n * Three modes:\n * 1. Legacy: `mesh create-app --template workflow --tenant x --name y`\n * 2. Composable (flags): `mesh create-app --tenant x --name y --primitives service,database`\n * 3. Interactive: `mesh create-app` (prompts when TTY detected and flags missing)\n *\n * All options can be passed as flags for agent/CI usage (no TTY required).\n */\n\nimport { Command } from \"commander\";\nimport * as fs from \"fs\";\nimport * as os from \"os\";\nimport * as path from \"path\";\nimport { fileURLToPath } from \"url\";\nimport Handlebars from \"handlebars\";\nimport { logInfo, logSuccess, logError, logWarn } from \"../utils/index.js\";\nimport { resolveTargetRoot, syncSkills } from \"./skills.js\";\nimport { findPackageRoot } from \"./local/stack.js\";\n\n// Get package root by walking up until we find package.json with our package name.\n// Works from both src/commands/ (tsx) and dist/src/commands/ (compiled).\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\nconst packageRoot = findPackageRoot(__dirname);\n\n// Available templates\nconst TEMPLATES = {\n workflow: \"Hono API + Temporal worker + hello workflow (Pulumi/app-kit)\",\n \"api-auth\": \"Hono API with platform auth: authn (Zitadel JWT) + authz (SpiceDB)\",\n \"api-role-gating\":\n \"Hono API with role-gating authz: authn (Zitadel JWT) + coarse-role checks on Zitadel project roles, in-process (no SpiceDB)\",\n \"external-service\":\n \"Hono API calling a third-party vendor via platform-managed credentials (ExternalService + mock for `mesh dev --externals`)\",\n} as const;\n\ntype TemplateName = keyof typeof TEMPLATES;\n\n/** Removed templates \u2192 what replaced them (named in the unknown-template error). */\nconst REMOVED_TEMPLATES: Record<string, string> = {\n \"temporal-api-worker\": \"renamed to 'workflow'\",\n \"api-web-db\": \"removed (SST-based) \u2014 use --primitives service,database\",\n};\n\n// Available primitives for composable mode\nconst PRIMITIVES = {\n service: \"HTTP Service (API with Hono)\",\n database: \"Database (PostgreSQL via Prisma)\",\n temporal: \"Temporal (workflow orchestration)\",\n bucket: \"S3 Bucket (file storage)\",\n} as const;\n\ntype PrimitiveName = keyof typeof PRIMITIVES;\n\n/**\n * Hub platform account IDs \u2014 the AWS account hosting a shared tenant's\n * `{tenant}-{env}-apps-deployer` role. Shared tenants (acme, \u2026) deploy into the\n * hub account, so the generated `mesh:deployerRole` ARN resolves against this map.\n * `mesh` is the only hub today; add entries as new hubs come online.\n */\nconst HUB_ACCOUNTS: Record<string, string> = {\n mesh: \"159923586610\",\n};\n\n/**\n * Walk up from `dir` looking for a `pnpm-workspace.yaml` \u2014 the app lives inside a\n * pnpm monorepo, so `@mesh-tech/*` deps should be `workspace:*` (link local source)\n * rather than pinned registry versions the local workspace doesn't publish.\n */\nfunction isInsideMonorepo(dir: string): boolean {\n let cur = path.resolve(dir);\n while (cur !== path.dirname(cur)) {\n if (fs.existsSync(path.join(cur, \"pnpm-workspace.yaml\"))) return true;\n cur = path.dirname(cur);\n }\n return false;\n}\n\n/**\n * Deployer-role ARN for a shared tenant on a known hub, or a clearly-marked\n * `ACCOUNT_ID` placeholder when the hub account is unknown (the generated config\n * comments the fill-in step in that case).\n */\nfunction resolveDeployerRoleArn(tenant: string, platformName: string, env: string): string {\n const account = HUB_ACCOUNTS[platformName] ?? \"ACCOUNT_ID\";\n return `arn:aws:iam::${account}:role/${tenant}-${env}-apps-deployer`;\n}\n\nconst VALID_PRIMITIVES = Object.keys(PRIMITIVES) as PrimitiveName[];\n\n// =============================================================================\n// Standalone apps-repo bootstrap\n// =============================================================================\n\n/**\n * A fresh standalone tenant-apps repo (empty clone of {tenant}-mesh-apps) is\n * bootstrappable when the cwd is a git repo root that has none of the layouts\n * `resolveAppDir` looks for. Previously create-app exited with \"Tenant\n * directory not found: tenants/<t>/\" here \u2014 even though the app-tenant\n * doctor's Repo-shape check names create-app as the fix (\"workspace files\n * included\"), so the command must actually deliver them.\n */\nexport function shouldBootstrapAppsRepo(cwd: string): boolean {\n return (\n fs.existsSync(path.join(cwd, \".git\")) &&\n !isInsideMonorepo(cwd) &&\n !fs.existsSync(path.join(cwd, \"package.json\")) &&\n !fs.existsSync(path.join(cwd, \"tenants\")) &&\n !fs.existsSync(path.join(cwd, \"apps\"))\n );\n}\n\n/**\n * Generate the repo-level files of a standalone tenant-apps repo (the\n * trabian-mesh-apps shape): pnpm workspace over apps/*, private root\n * package.json, scoped CodeArtifact .npmrc, base tsconfig, .gitignore, README.\n * Only writes files that don't already exist; returns what it created.\n */\nexport function bootstrapAppsRepo(cwd: string, tenant: string): string[] {\n const templateDir = path.join(packageRoot, \"templates\", \"apps-repo\");\n const registryAccount = HUB_ACCOUNTS.mesh;\n const context = {\n repoName: path.basename(cwd),\n tenant,\n tenantTitle: tenant\n .split(\"-\")\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\n .join(\" \"),\n registryUrl: `https://mesh-platform-${registryAccount}.d.codeartifact.us-east-2.amazonaws.com/npm/mesh-packages/`,\n };\n\n const staging = fs.mkdtempSync(path.join(os.tmpdir(), \"mesh-apps-repo-\"));\n try {\n copyTemplate(templateDir, staging, context);\n // npm strips dotfiles from published tarballs, so the template ships\n // `gitignore`/`npmrc` and the bootstrap restores the real names.\n for (const [from, to] of [\n [\"gitignore\", \".gitignore\"],\n [\"npmrc\", \".npmrc\"],\n ] as const) {\n const p = path.join(staging, from);\n if (fs.existsSync(p)) fs.renameSync(p, path.join(staging, to));\n }\n\n const created: string[] = [];\n for (const entry of fs.readdirSync(staging)) {\n const dest = path.join(cwd, entry);\n if (fs.existsSync(dest)) continue;\n fs.cpSync(path.join(staging, entry), dest, { recursive: true });\n created.push(entry);\n }\n fs.mkdirSync(path.join(cwd, \"apps\"), { recursive: true });\n created.push(\"apps/\");\n return created;\n } finally {\n fs.rmSync(staging, { recursive: true, force: true });\n }\n}\n\nfunction maybeBootstrapAppsRepo(cwd: string, tenant: string, test: boolean): void {\n if (test || !shouldBootstrapAppsRepo(cwd)) return;\n const created = bootstrapAppsRepo(cwd, tenant);\n logInfo(`Standalone apps repo detected \u2014 bootstrapped workspace files: ${created.join(\", \")}`);\n}\n\ninterface CreateAppOptions {\n tenant?: string;\n name?: string;\n template?: string;\n primitives?: string;\n test: boolean;\n}\n\n// Register Handlebars helpers\nHandlebars.registerHelper(\"titleCase\", (str: string) => {\n return str\n .split(\"-\")\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(\" \");\n});\n\n/**\n * Check if we're in an interactive terminal\n */\nfunction isInteractive(): boolean {\n return Boolean(process.stdin.isTTY && process.stdout.isTTY);\n}\n\n/**\n * Run interactive prompts to gather missing options.\n * Only called when TTY is available and required options are missing.\n */\nasync function promptForOptions(options: CreateAppOptions): Promise<{\n tenant: string;\n name: string;\n primitives: PrimitiveName[];\n}> {\n // Dynamic imports so non-interactive usage doesn't load inquirer\n const { default: input } = await import(\"@inquirer/input\");\n const { default: checkbox } = await import(\"@inquirer/checkbox\");\n\n const tenant =\n options.tenant ??\n (await input({\n message: \"Tenant name\",\n validate: (v) => (v.length > 0 ? true : \"Tenant name is required\"),\n }));\n\n const name =\n options.name ??\n (await input({\n message: \"App name\",\n validate: (v) => (v.length > 0 ? true : \"App name is required\"),\n }));\n\n let primitives: PrimitiveName[];\n if (options.primitives) {\n primitives = parsePrimitives(options.primitives);\n } else {\n primitives = await checkbox<PrimitiveName>({\n message: \"Select primitives\",\n choices: VALID_PRIMITIVES.map((p) => ({\n name: PRIMITIVES[p],\n value: p,\n checked: p === \"service\", // service checked by default\n })),\n });\n if (primitives.length === 0) {\n primitives = [\"service\"];\n }\n }\n\n // Database and bucket place files in api/ \u2014 ensure service is included\n if (primitives.includes(\"database\") && !primitives.includes(\"service\")) {\n primitives.push(\"service\");\n logInfo(\"Added 'service' \u2014 database files live in the api/ directory.\");\n }\n if (primitives.includes(\"bucket\") && !primitives.includes(\"service\")) {\n primitives.push(\"service\");\n logInfo(\"Added 'service' \u2014 bucket requires an API service for S3 helpers.\");\n }\n\n return { tenant, name, primitives };\n}\n\n/**\n * Recursively copy a directory, processing .hbs templates\n */\nexport function copyTemplate(\n srcDir: string,\n destDir: string,\n context: Record<string, unknown>\n): void {\n const entries = fs.readdirSync(srcDir, { withFileTypes: true });\n\n for (const entry of entries) {\n const srcPath = path.join(srcDir, entry.name);\n let destName = entry.name;\n\n // Remove .hbs extension for template files\n if (destName.endsWith(\".hbs\")) {\n destName = destName.slice(0, -4);\n }\n\n // File names can be templated too (e.g. Pulumi.{{tenant}}-{{env}}.yaml.hbs)\n if (destName.includes(\"{{\")) {\n destName = Handlebars.compile(destName)(context);\n }\n\n const destPath = path.join(destDir, destName);\n\n if (entry.isDirectory()) {\n fs.mkdirSync(destPath, { recursive: true });\n copyTemplate(srcPath, destPath, context);\n } else if (entry.name.endsWith(\".hbs\")) {\n // Process Handlebars template\n const templateContent = fs.readFileSync(srcPath, \"utf-8\");\n const template = Handlebars.compile(templateContent);\n const output = template(context);\n fs.writeFileSync(destPath, output);\n } else {\n // Copy file as-is\n fs.copyFileSync(srcPath, destPath);\n }\n }\n}\n\n/**\n * Parse and validate primitive selections from comma-separated string\n */\nfunction parsePrimitives(input: string): PrimitiveName[] {\n const selected = input.split(\",\").map((s) => s.trim().toLowerCase());\n const invalid = selected.filter(\n (s) => !VALID_PRIMITIVES.includes(s as PrimitiveName)\n );\n if (invalid.length > 0) {\n logError(`Unknown primitives: ${invalid.join(\", \")}`);\n logInfo(`Available primitives: ${VALID_PRIMITIVES.join(\", \")}`);\n process.exit(1);\n }\n return selected as PrimitiveName[];\n}\n\n/**\n * Resolve output directory for the app\n */\nfunction resolveAppDir(\n cwd: string,\n tenant: string,\n name: string,\n test: boolean\n): string {\n const baseDir = test ? \"tests/tenants\" : \"tenants\";\n\n const possiblePaths = [\n path.join(cwd, baseDir, tenant, \"apps\"),\n path.join(cwd, \"..\", tenant, \"apps\"),\n path.join(cwd, \"apps\"),\n ];\n\n let appsDir = possiblePaths.find((p) => fs.existsSync(p));\n\n if (!appsDir) {\n appsDir = path.join(cwd, baseDir, tenant, \"apps\");\n\n if (!fs.existsSync(path.join(cwd, baseDir, tenant))) {\n logError(`Tenant directory not found: ${baseDir}/${tenant}/`);\n logInfo(\"Create the tenant directory first, or run from within it.\");\n process.exit(1);\n }\n\n if (!fs.existsSync(appsDir)) {\n logInfo(`Creating apps directory: ${appsDir}`);\n fs.mkdirSync(appsDir, { recursive: true });\n }\n }\n\n return path.join(appsDir, name);\n}\n\n/**\n * Generate a composable app from fragments\n */\nfunction generateComposableApp(\n appDir: string,\n context: {\n name: string;\n tenant: string;\n service: boolean;\n database: boolean;\n temporal: boolean;\n bucket: boolean;\n region: string;\n /** True when scaffolding inside this pnpm monorepo \u2192 `@mesh-tech/*` = `workspace:*`. */\n workspaceDeps: boolean;\n /** Fully-resolved `mesh:deployerRole` ARN (or an `ACCOUNT_ID` placeholder). */\n deployerRoleArn: string;\n }\n): void {\n const fragmentsDir = path.join(packageRoot, \"fragments\");\n\n // 1. Always copy base fragment\n const baseDir = path.join(fragmentsDir, \"base\");\n if (!fs.existsSync(baseDir)) {\n logError(`Fragments directory not found: ${baseDir}`);\n logInfo(\"Make sure the mesh-cli package is installed correctly.\");\n process.exit(1);\n }\n copyTemplate(baseDir, appDir, context);\n\n // 2. Copy primitive-specific fragments\n if (context.service) {\n const serviceDir = path.join(fragmentsDir, \"service\");\n if (!fs.existsSync(serviceDir)) {\n throw new Error(`Fragment directory not found: ${serviceDir}`);\n }\n copyTemplate(serviceDir, appDir, context);\n }\n\n if (context.database) {\n const dbDir = path.join(fragmentsDir, \"database\");\n if (!fs.existsSync(dbDir)) {\n throw new Error(`Fragment directory not found: ${dbDir}`);\n }\n copyTemplate(dbDir, appDir, context);\n }\n\n if (context.temporal) {\n const temporalDir = path.join(fragmentsDir, \"temporal\");\n if (!fs.existsSync(temporalDir)) {\n throw new Error(`Fragment directory not found: ${temporalDir}`);\n }\n copyTemplate(temporalDir, appDir, context);\n }\n\n if (context.bucket) {\n const bucketDir = path.join(fragmentsDir, \"bucket\");\n if (!fs.existsSync(bucketDir)) {\n throw new Error(`Fragment directory not found: ${bucketDir}`);\n }\n copyTemplate(bucketDir, appDir, context);\n }\n\n // 3. Always generate AGENTS.md\n const agentsDir = path.join(fragmentsDir, \"agents\");\n if (fs.existsSync(agentsDir)) {\n copyTemplate(agentsDir, appDir, context);\n }\n}\n\nexport function registerCreateAppCommand(program: Command): void {\n program\n .command(\"create-app\")\n .description(\"Scaffold a new tenant application\")\n .option(\"--tenant <tenant>\", \"Tenant name (e.g., acme)\")\n .option(\"--name <name>\", \"Application name (e.g., billing)\")\n .option(\n \"--template <template>\",\n `Legacy template: ${Object.keys(TEMPLATES).join(\", \")}`\n )\n .option(\n \"--primitives <primitives>\",\n `Comma-separated primitives: ${VALID_PRIMITIVES.join(\", \")} (default: service)`\n )\n .option(\"--test\", \"Create in tests/tenants/ directory\", false)\n .action(async (options: CreateAppOptions) => {\n // Legacy template mode \u2014 requires all flags\n if (options.template) {\n if (!options.tenant || !options.name) {\n logError(\"--tenant and --name are required with --template\");\n process.exit(1);\n }\n await runLegacyTemplate(\n options.tenant,\n options.name,\n options.template,\n options.test\n );\n return;\n }\n\n // Composable mode \u2014 interactive or flag-based\n let tenant: string;\n let name: string;\n let primitives: PrimitiveName[];\n\n const needsPrompt =\n !options.tenant || !options.name || !options.primitives;\n\n if (needsPrompt && isInteractive()) {\n // Interactive: prompt for missing values\n const prompted = await promptForOptions(options);\n tenant = prompted.tenant;\n name = prompted.name;\n primitives = prompted.primitives;\n } else if (needsPrompt) {\n // Non-interactive but missing flags\n if (!options.tenant) {\n logError(\"--tenant is required (no TTY for interactive mode)\");\n process.exit(1);\n }\n if (!options.name) {\n logError(\"--name is required (no TTY for interactive mode)\");\n process.exit(1);\n }\n tenant = options.tenant;\n name = options.name;\n primitives = options.primitives\n ? parsePrimitives(options.primitives)\n : [\"service\"];\n } else {\n tenant = options.tenant!;\n name = options.name!;\n primitives = parsePrimitives(options.primitives!);\n }\n\n // Database and bucket place files in api/ \u2014 ensure service is included\n if (primitives.includes(\"database\") && !primitives.includes(\"service\")) {\n primitives.push(\"service\");\n logInfo(\"Added 'service' \u2014 database files live in the api/ directory.\");\n }\n if (primitives.includes(\"bucket\") && !primitives.includes(\"service\")) {\n primitives.push(\"service\");\n logInfo(\"Added 'service' \u2014 bucket requires an API service for S3 helpers.\");\n }\n\n await runComposable(tenant, name, primitives, options.test);\n });\n}\n\nasync function runLegacyTemplate(\n tenant: string,\n name: string,\n template: string,\n test: boolean\n): Promise<void> {\n if (!Object.keys(TEMPLATES).includes(template)) {\n const removed = REMOVED_TEMPLATES[template];\n logError(`Unknown template: ${template}${removed ? ` (${removed})` : \"\"}`);\n logInfo(`Available templates:`);\n for (const [tplName, desc] of Object.entries(TEMPLATES)) {\n console.log(` ${tplName.padEnd(20)} - ${desc}`);\n }\n process.exit(1);\n }\n\n logInfo(`Creating app '${name}' for tenant '${tenant}'...`);\n logInfo(`Template: ${template} (${TEMPLATES[template as TemplateName]})`);\n if (test) {\n logInfo(\"Creating in tests/ directory\");\n }\n\n maybeBootstrapAppsRepo(process.cwd(), tenant, test);\n const appDir = resolveAppDir(process.cwd(), tenant, name, test);\n\n if (fs.existsSync(appDir)) {\n logError(`App directory already exists: ${appDir}`);\n process.exit(1);\n }\n\n const templateDir = path.join(packageRoot, \"templates\", template);\n if (!fs.existsSync(templateDir)) {\n logError(`Template not found: ${templateDir}`);\n process.exit(1);\n }\n\n fs.mkdirSync(appDir, { recursive: true });\n try {\n copyTemplate(templateDir, appDir, { name, tenant });\n logSuccess(`Created app at ${appDir}`);\n } catch (error) {\n logError(`Failed to create app: ${error}`);\n fs.rmSync(appDir, { recursive: true, force: true });\n process.exit(1);\n }\n\n autoSyncSkills(appDir);\n printLegacyNextSteps(appDir, template as TemplateName);\n}\n\n/** Best-effort skills sync after scaffolding (design D1): a fresh Claude\n * session in the repo sees the base skills + Intent discovery immediately. */\nfunction autoSyncSkills(appDir: string): void {\n try {\n syncSkills(resolveTargetRoot(appDir));\n } catch (err) {\n logWarn(`Agent-skill sync skipped: ${err instanceof Error ? err.message : err} \u2014 run: mesh skills sync`);\n }\n}\n\nasync function runComposable(\n tenant: string,\n name: string,\n primitives: PrimitiveName[],\n test: boolean\n): Promise<void> {\n logInfo(`Creating app '${name}' for tenant '${tenant}'...`);\n logInfo(`Primitives: ${primitives.join(\", \")}`);\n if (test) {\n logInfo(\"Creating in tests/ directory\");\n }\n\n maybeBootstrapAppsRepo(process.cwd(), tenant, test);\n const appDir = resolveAppDir(process.cwd(), tenant, name, test);\n\n if (fs.existsSync(appDir)) {\n logError(`App directory already exists: ${appDir}`);\n process.exit(1);\n }\n\n // Platform defaults (the generated Pulumi config targets the mesh hub / dev).\n const region = \"us-east-2\";\n const platformName = \"mesh\";\n const platformEnv = \"dev\";\n\n const context = {\n name,\n tenant,\n service: primitives.includes(\"service\"),\n database: primitives.includes(\"database\"),\n temporal: primitives.includes(\"temporal\"),\n bucket: primitives.includes(\"bucket\"),\n region,\n // Link local source when generating inside this monorepo; pin only for\n // out-of-repo tenant repos that install `@mesh-tech/*` from the registry.\n workspaceDeps: isInsideMonorepo(appDir),\n deployerRoleArn: resolveDeployerRoleArn(tenant, platformName, platformEnv),\n };\n\n fs.mkdirSync(appDir, { recursive: true });\n\n try {\n generateComposableApp(appDir, context);\n logSuccess(`Created app at ${appDir}`);\n } catch (error) {\n logError(`Failed to create app: ${error}`);\n fs.rmSync(appDir, { recursive: true, force: true });\n process.exit(1);\n }\n\n // Check for config.ts\n const configPath = path.join(path.dirname(appDir), \"config.ts\");\n if (!fs.existsSync(configPath)) {\n logWarn(`No config.ts found at ${configPath}`);\n logInfo(\"You may need to create a shared config.ts for tenant apps.\");\n }\n\n autoSyncSkills(appDir);\n printComposableNextSteps(appDir, context);\n}\n\nfunction printLegacyNextSteps(appDir: string, _template: TemplateName): void {\n const configPath = path.join(path.dirname(appDir), \"config.ts\");\n if (!fs.existsSync(configPath)) {\n logWarn(`No config.ts found at ${configPath}`);\n logInfo(\"You may need to create a shared config.ts for tenant apps.\");\n }\n\n console.log(\"\");\n logSuccess(\"App created successfully!\");\n console.log(\"\");\n console.log(\"Next steps:\");\n console.log(` cd ${appDir}`);\n console.log(\" pnpm install\");\n\n console.log(\" pnpm mesh dev\");\n\n console.log(\"\");\n console.log(\"To deploy:\");\n console.log(\" pnpm mesh deploy up\");\n console.log(\"\");\n}\n\nfunction printComposableNextSteps(\n appDir: string,\n context: {\n service: boolean;\n database: boolean;\n temporal: boolean;\n bucket: boolean;\n }\n): void {\n console.log(\"\");\n logSuccess(\"App created successfully!\");\n console.log(\"\");\n console.log(\"Generated:\");\n console.log(\" index.ts Pulumi app definition\");\n console.log(\" AGENTS.md AI agent instructions\");\n console.log(\" CLAUDE.md Bridges AGENTS.md into Claude Code (@AGENTS.md)\");\n if (context.service) {\n console.log(\" api/ HTTP service (Hono)\");\n }\n if (context.temporal) {\n console.log(\" worker/ Temporal worker\");\n }\n if (context.database) {\n console.log(\" prisma/ Database schema\");\n }\n if (context.bucket) {\n console.log(\" api/src/storage.ts S3 helpers\");\n }\n console.log(\"\");\n console.log(\"Next steps:\");\n console.log(` cd ${appDir}`);\n console.log(\" pnpm install\");\n console.log(\" mesh stack init # personal dev stack (deploy: false)\");\n console.log(\" mesh deploy up --yes # deploy via the stack's deployer role\");\n console.log(\" mesh dev # run locally\");\n console.log(\"\");\n}\n", "/**\n * mesh db connect - Start DB tunnel for manual psql access\n *\n * Usage:\n * mesh db connect --tenant mesh --env dev-temporal\n */\n\nimport { spawn } from \"child_process\";\nimport {\n detectContext,\n getPlatformBastionInfo,\n logInfo,\n logError,\n} from \"../../utils/index.js\";\n\ninterface ConnectOptions {\n tenant?: string;\n env?: string;\n}\n\nexport async function connectCommand(options: ConnectOptions): Promise<void> {\n // Resolve tenant/env - explicit or auto-detect\n let tenant: string;\n let platformEnv: string;\n\n if (options.tenant && options.env) {\n tenant = options.tenant;\n platformEnv = options.env;\n logInfo(`Explicit mode: Tenant=${tenant}, Env=${platformEnv}`);\n } else if (options.tenant || options.env) {\n logError(\"Both --tenant and --env are required\");\n logInfo(\"Usage: mesh db connect --tenant mesh --env dev-temporal\");\n process.exit(1);\n } else {\n const ctx = detectContext();\n tenant = ctx.tenant;\n platformEnv = ctx.platformEnv;\n logInfo(`Auto-detected: Tenant=${tenant}, Env=${platformEnv}`);\n }\n\n const bastion = await getPlatformBastionInfo(tenant, platformEnv);\n const rdsService = bastion.services.rds;\n\n if (!rdsService) {\n logError(\"RDS service not available in platform bastion\");\n process.exit(1);\n }\n\n console.log(\"\");\n logInfo(`Tunnel will forward localhost:5432 \u2192 ${rdsService.host}:${rdsService.port}`);\n console.log(\"\");\n logInfo(\"In another terminal, connect with:\");\n console.log(\" psql -h localhost -p 5432 -U <username> -d <database>\");\n console.log(\"\");\n logInfo(\"Or use: mesh db credentials --tenant ... --env ... --app ...\");\n console.log(\"\");\n logInfo(\"Press Ctrl+C to stop the tunnel\");\n console.log(\"\");\n\n // Start SSM tunnel\n const tunnel = spawn(\n \"aws\",\n [\n \"ssm\",\n \"start-session\",\n \"--target\",\n bastion.instanceId,\n \"--document-name\",\n \"AWS-StartPortForwardingSessionToRemoteHost\",\n \"--parameters\",\n JSON.stringify({\n host: [rdsService.host],\n portNumber: [String(rdsService.port)],\n localPortNumber: [\"5432\"],\n }),\n ],\n { stdio: \"inherit\" }\n );\n\n tunnel.on(\"error\", (err) => {\n console.error(\"Failed to start tunnel:\", err.message);\n process.exit(1);\n });\n\n tunnel.on(\"exit\", (code) => {\n process.exit(code ?? 0);\n });\n}\n", "/**\n * mesh db credentials - Print database credentials\n *\n * Usage:\n * mesh db credentials --tenant mesh --env dev-temporal --app rdc --app-tenant encore --app-stage dev\n */\n\nimport {\n detectContext,\n getDatabaseUrl,\n logInfo,\n logError,\n} from \"../../utils/index.js\";\n\ninterface CredentialsOptions {\n tenant?: string;\n env?: string;\n app?: string;\n appTenant?: string;\n appStage?: string;\n}\n\nexport async function credentialsCommand(\n options: CredentialsOptions\n): Promise<void> {\n // Resolve platform tenant/env\n let platformTenant: string;\n let platformEnv: string;\n\n if (options.tenant && options.env) {\n platformTenant = options.tenant;\n platformEnv = options.env;\n logInfo(`Platform: Tenant=${platformTenant}, Env=${platformEnv}`);\n } else if (options.tenant || options.env) {\n logError(\"Both --tenant and --env are required\");\n logInfo(\"Usage: mesh db credentials --tenant mesh --env dev-temporal --app rdc --app-tenant encore --app-stage dev\");\n process.exit(1);\n } else {\n const ctx = detectContext();\n platformTenant = ctx.tenant;\n platformEnv = ctx.platformEnv;\n logInfo(`Auto-detected: Tenant=${platformTenant}, Env=${platformEnv}`);\n }\n\n // Resolve app credentials\n const appTenant = options.appTenant ?? platformTenant;\n const appStage = options.appStage ?? platformEnv;\n const appName = options.app;\n\n if (appName) {\n logInfo(`App credentials: tenant=${appTenant}, stage=${appStage}, app=${appName}`);\n }\n\n // Get DATABASE_URL\n const databaseUrl = await getDatabaseUrl(appTenant, appStage, { app: appName });\n const parsed = new URL(databaseUrl);\n\n console.log(\"\");\n console.log(\"Database Credentials:\");\n console.log(` Host: ${parsed.hostname}`);\n console.log(` Port: ${parsed.port || 5432}`);\n console.log(` Database: ${parsed.pathname.slice(1)}`);\n console.log(` Username: ${parsed.username}`);\n console.log(` Password: ${decodeURIComponent(parsed.password)}`);\n console.log(\"\");\n console.log(\"DATABASE_URL:\");\n console.log(` ${databaseUrl}`);\n console.log(\"\");\n console.log(\"For tunnel usage (localhost:5432):\");\n const tunnelUrl = new URL(databaseUrl);\n tunnelUrl.hostname = \"localhost\";\n tunnelUrl.port = \"5432\";\n console.log(` ${tunnelUrl.toString()}`);\n console.log(\"\");\n}\n", "/**\n * mesh db env - Export DATABASE_URL for shell\n *\n * Usage: eval $(mesh db env --tenant mesh --env dev-temporal --app rdc --app-tenant encore --app-stage dev)\n */\n\nimport {\n detectContext,\n getDatabaseUrl,\n rewriteDatabaseUrl,\n logInfo,\n logError,\n} from \"../../utils/index.js\";\n\ninterface EnvOptions {\n tenant?: string;\n env?: string;\n app?: string;\n appTenant?: string;\n appStage?: string;\n}\n\nexport async function envCommand(options: EnvOptions): Promise<void> {\n // Resolve platform tenant/env\n let platformTenant: string;\n let platformEnv: string;\n\n if (options.tenant && options.env) {\n platformTenant = options.tenant;\n platformEnv = options.env;\n // Use stderr for info so stdout is clean for eval\n console.error(`\u2139 Platform: Tenant=${platformTenant}, Env=${platformEnv}`);\n } else if (options.tenant || options.env) {\n logError(\"Both --tenant and --env are required\");\n logInfo(\"Usage: eval $(mesh db env --tenant mesh --env dev-temporal --app rdc --app-tenant encore --app-stage dev)\");\n process.exit(1);\n } else {\n const ctx = detectContext();\n platformTenant = ctx.tenant;\n platformEnv = ctx.platformEnv;\n console.error(`\u2139 Auto-detected: Tenant=${platformTenant}, Env=${platformEnv}`);\n }\n\n // Resolve app credentials\n const appTenant = options.appTenant ?? platformTenant;\n const appStage = options.appStage ?? platformEnv;\n const appName = options.app;\n\n if (appName) {\n console.error(`\u2139 App credentials: tenant=${appTenant}, stage=${appStage}, app=${appName}`);\n }\n\n // Get DATABASE_URL and rewrite for tunnel\n const rawUrl = await getDatabaseUrl(appTenant, appStage, { app: appName });\n const tunnelUrl = rewriteDatabaseUrl(rawUrl, { endpoint: \"localhost:5432\" });\n const parsed = new URL(tunnelUrl);\n\n // Output export statements (to stdout for eval).\n // WARNING: Contains plaintext credentials. Use only with:\n // eval \"$(mesh db env ...)\"\n // Do NOT run bare \u2014 credentials will appear in terminal and shell history.\n console.log(`export DATABASE_URL=\"${tunnelUrl}\"`);\n console.log('export DB_HOST=\"localhost\"');\n console.log('export DB_PORT=\"5432\"');\n console.log(`export DB_NAME=\"${parsed.pathname.slice(1)}\"`);\n console.log(`export DB_USERNAME=\"${parsed.username}\"`);\n console.log(`export DB_PASSWORD=\"${decodeURIComponent(parsed.password)}\"`);\n}\n", "/**\n * mesh db psql - Connect to database with psql\n *\n * Usage:\n * mesh db psql --tenant mesh --env dev-temporal --app rdc --app-tenant encore --app-stage dev\n */\n\nimport { spawn, ChildProcess } from \"child_process\";\nimport * as net from \"net\";\nimport {\n detectContext,\n getPlatformBastionInfo,\n getDatabaseUrl,\n logInfo,\n logSuccess,\n logError,\n} from \"../../utils/index.js\";\n\ninterface PsqlOptions {\n tenant?: string;\n env?: string;\n app?: string;\n appTenant?: string;\n appStage?: string;\n}\n\n/**\n * Start SSM tunnel in background and wait for it to be ready.\n */\nasync function startTunnelBackground(\n instanceId: string,\n rdsHost: string,\n rdsPort: number,\n localPort: number\n): Promise<ChildProcess> {\n logInfo(\"Starting tunnel in background...\");\n\n const tunnel = spawn(\n \"aws\",\n [\n \"ssm\",\n \"start-session\",\n \"--target\",\n instanceId,\n \"--document-name\",\n \"AWS-StartPortForwardingSessionToRemoteHost\",\n \"--parameters\",\n JSON.stringify({\n host: [rdsHost],\n portNumber: [String(rdsPort)],\n localPortNumber: [String(localPort)],\n }),\n ],\n { stdio: [\"ignore\", \"ignore\", \"ignore\"] }\n );\n\n // Wait for tunnel to be ready (port listening)\n const maxAttempts = 15;\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n if (tunnel.exitCode !== null) {\n throw new Error(\"Tunnel process died\");\n }\n\n const isListening = await checkPort(localPort);\n if (isListening) {\n logSuccess(`Tunnel started (PID: ${tunnel.pid})`);\n return tunnel;\n }\n\n await sleep(1000);\n }\n\n tunnel.kill();\n throw new Error(`Tunnel failed to start after ${maxAttempts} seconds`);\n}\n\nfunction checkPort(port: number): Promise<boolean> {\n return new Promise((resolve) => {\n const socket = new net.Socket();\n socket.setTimeout(500);\n socket.on(\"connect\", () => { socket.destroy(); resolve(true); });\n socket.on(\"timeout\", () => { socket.destroy(); resolve(false); });\n socket.on(\"error\", () => { socket.destroy(); resolve(false); });\n socket.connect(port, \"localhost\");\n });\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport async function psqlCommand(options: PsqlOptions): Promise<void> {\n // Resolve platform tenant/env\n let platformTenant: string;\n let platformEnv: string;\n\n if (options.tenant && options.env) {\n platformTenant = options.tenant;\n platformEnv = options.env;\n logInfo(`Platform: Tenant=${platformTenant}, Env=${platformEnv}`);\n } else if (options.tenant || options.env) {\n logError(\"Both --tenant and --env are required\");\n logInfo(\"Usage: mesh db psql --tenant mesh --env dev-temporal --app rdc --app-tenant encore --app-stage dev\");\n process.exit(1);\n } else {\n const ctx = detectContext();\n platformTenant = ctx.tenant;\n platformEnv = ctx.platformEnv;\n logInfo(`Auto-detected: Tenant=${platformTenant}, Env=${platformEnv}`);\n }\n\n // Resolve app credentials\n const appTenant = options.appTenant ?? platformTenant;\n const appStage = options.appStage ?? platformEnv;\n const appName = options.app;\n\n if (appName) {\n logInfo(`App credentials: tenant=${appTenant}, stage=${appStage}, app=${appName}`);\n }\n\n // Check for psql\n const psqlCheck = spawn(\"which\", [\"psql\"]);\n await new Promise<void>((resolve, reject) => {\n psqlCheck.on(\"exit\", (code) => {\n if (code !== 0) {\n logError(\"psql not found. Install with: brew install postgresql\");\n reject(new Error(\"psql not found\"));\n } else {\n resolve();\n }\n });\n });\n\n // Get bastion and start tunnel\n const bastion = await getPlatformBastionInfo(platformTenant, platformEnv);\n const rdsService = bastion.services.rds;\n\n if (!rdsService) {\n logError(\"RDS service not available in platform bastion\");\n process.exit(1);\n }\n\n const tunnel = await startTunnelBackground(\n bastion.instanceId,\n rdsService.host,\n rdsService.port,\n 5432\n );\n\n // Cleanup on exit\n const cleanup = () => {\n logInfo(\"Stopping tunnel...\");\n tunnel.kill();\n };\n process.on(\"exit\", cleanup);\n process.on(\"SIGINT\", cleanup);\n process.on(\"SIGTERM\", cleanup);\n\n // Get DATABASE_URL and parse credentials\n const databaseUrl = await getDatabaseUrl(appTenant, appStage, { app: appName });\n const parsed = new URL(databaseUrl);\n const username = parsed.username;\n const password = decodeURIComponent(parsed.password);\n const database = parsed.pathname.slice(1);\n\n console.log(\"\");\n logInfo(`Connecting to ${database} as ${username}...`);\n console.log(\"\");\n\n // Run psql\n const psql = spawn(\n \"psql\",\n [\"-h\", \"localhost\", \"-p\", \"5432\", \"-U\", username, \"-d\", database],\n {\n stdio: \"inherit\",\n env: { ...process.env, PGPASSWORD: password },\n }\n );\n\n psql.on(\"exit\", (code) => {\n cleanup();\n process.exit(code ?? 0);\n });\n}\n", "/**\n * mesh db exec - Run any command with database connection\n *\n * Three modes of operation:\n *\n * 1. Explicit mode (recommended for ad-hoc use):\n * mesh db exec --tenant=<tenant> --env=<env> [--ssl=require] -- <command>\n * - Uses explicit tenant/env to find platform bastion\n * - Starts tunnel if needed\n * - Similar to: mesh tunnel --tenant mesh --env dev\n *\n * 2. Direct mode (for sst dev integration):\n * mesh db exec --secret=<arn> [--ssl=require] -- <command>\n * - Uses secret ARN directly, expects tunnel already running\n * - Ideal for sst.config.ts devCommand\n *\n * 3. Discovery mode (legacy, auto-detection):\n * mesh db exec [--stage=<stage>] -- <command>\n * - Auto-discovers tenant/env from filesystem and config files\n * - Can be fragile if project structure doesn't match expected patterns\n * - Starts tunnel if needed\n *\n * Examples:\n * # Explicit mode (recommended)\n * mesh db exec --tenant mesh --env dev --ssl=require -- npx prisma db push\n * mesh db exec -t mesh -e dev -- npx prisma migrate dev\n *\n * # Direct mode (in sst.config.ts)\n * mesh db exec --secret=arn:aws:secretsmanager:... --ssl=require -- pnpm dev\n *\n * # Discovery mode (legacy)\n * mesh db exec -- npx prisma db push\n * mesh db exec --stage=dev -- npx prisma migrate dev\n */\n\nimport { spawn, ChildProcess } from \"child_process\";\nimport * as net from \"net\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport {\n SecretsManagerClient,\n GetSecretValueCommand,\n} from \"@aws-sdk/client-secrets-manager\";\nimport {\n detectContext,\n getPlatformBastionInfo,\n getDatabaseUrl,\n rewriteDatabaseUrl,\n logInfo,\n logSuccess,\n logError,\n logWarn,\n} from \"../../utils/index.js\";\n\nconst DEFAULT_LOCAL_PORT = 5432;\nconst MAX_RETRIES = 12;\nconst RETRY_DELAY_MS = 5000;\n\n/**\n * Find SST outputs by looking in current and parent directories.\n */\nfunction findSstOutputs(): {\n databaseUrl?: string;\n databaseName?: string;\n secretArn?: string;\n rootDir: string;\n} | null {\n let dir = process.cwd();\n const root = path.parse(dir).root;\n\n while (dir !== root) {\n const outputsPath = path.join(dir, \".sst\", \"outputs.json\");\n if (fs.existsSync(outputsPath)) {\n try {\n const content = fs.readFileSync(outputsPath, \"utf-8\");\n const outputs = JSON.parse(content);\n\n if (outputs.databaseUrl) {\n const secretArnMatch = outputs.databaseUrl.match(/secretArn=([^&]+)/);\n const secretArn = secretArnMatch\n ? decodeURIComponent(secretArnMatch[1])\n : undefined;\n\n return {\n databaseUrl: outputs.databaseUrl,\n databaseName: outputs.databaseName,\n secretArn,\n rootDir: dir,\n };\n }\n } catch {\n // Ignore parse errors, continue searching\n }\n }\n dir = path.dirname(dir);\n }\n\n return null;\n}\n\nexport interface ExecOptions {\n /** Platform tenant for bastion lookup */\n tenant?: string;\n /** Platform environment for bastion lookup */\n env?: string;\n /** App name for credentials path */\n app?: string;\n /** Tenant for app credentials (if different from platform tenant) */\n appTenant?: string;\n /** Stage for app credentials */\n appStage?: string;\n /** Secret ARN for direct mode */\n secret?: string;\n /** SSL mode */\n ssl?: string;\n /** Local tunnel port */\n port?: string;\n}\n\nfunction checkPort(port: number): Promise<boolean> {\n return new Promise((resolve) => {\n const socket = new net.Socket();\n socket.setTimeout(500);\n socket.on(\"connect\", () => { socket.destroy(); resolve(true); });\n socket.on(\"timeout\", () => { socket.destroy(); resolve(false); });\n socket.on(\"error\", () => { socket.destroy(); resolve(false); });\n socket.connect(port, \"localhost\");\n });\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nasync function startTunnelBackground(\n instanceId: string,\n rdsEndpoint: string,\n rdsPort: number,\n localPort: number\n): Promise<ChildProcess> {\n logInfo(\"Starting database tunnel...\");\n\n const tunnel = spawn(\n \"aws\",\n [\n \"ssm\",\n \"start-session\",\n \"--target\",\n instanceId,\n \"--document-name\",\n \"AWS-StartPortForwardingSessionToRemoteHost\",\n \"--parameters\",\n JSON.stringify({\n host: [rdsEndpoint],\n portNumber: [String(rdsPort)],\n localPortNumber: [String(localPort)],\n }),\n ],\n { stdio: [\"ignore\", \"ignore\", \"ignore\"] }\n );\n\n const maxAttempts = 15;\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n if (tunnel.exitCode !== null) {\n throw new Error(\"Tunnel process died\");\n }\n if (await checkPort(localPort)) {\n logSuccess(`Tunnel started (PID: ${tunnel.pid})`);\n return tunnel;\n }\n await sleep(1000);\n }\n\n tunnel.kill();\n throw new Error(`Tunnel failed to start after ${maxAttempts} seconds`);\n}\n\n/**\n * Fetch secret from Secrets Manager with retry logic for provisioning delays.\n */\nasync function fetchSecretWithRetry(\n client: SecretsManagerClient,\n secretId: string\n): Promise<Record<string, string>> {\n let lastError: Error | undefined;\n\n for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {\n try {\n const response = await client.send(\n new GetSecretValueCommand({ SecretId: secretId })\n );\n\n if (!response.SecretString) {\n throw new Error(`Secret ${secretId} has no string value`);\n }\n\n return JSON.parse(response.SecretString);\n } catch (error) {\n lastError = error as Error;\n const isNotFound = (error as { name?: string }).name === \"ResourceNotFoundException\";\n\n if (isNotFound && attempt < MAX_RETRIES) {\n logWarn(`Secret not found (attempt ${attempt}/${MAX_RETRIES}), waiting...`);\n await sleep(RETRY_DELAY_MS);\n continue;\n }\n throw error;\n }\n }\n\n throw lastError;\n}\n\nexport async function execCommand(\n commandArgs: string[],\n options: ExecOptions\n): Promise<void> {\n if (commandArgs.length === 0) {\n logError(\"No command specified\");\n logInfo(\"Usage: mesh db exec [options] -- <command> [args...]\");\n logInfo(\"\");\n logInfo(\"Options:\");\n logInfo(\" -t, --tenant <tenant> Platform tenant (e.g., mesh)\");\n logInfo(\" -e, --env <env> Platform environment (e.g., dev)\");\n logInfo(\" --secret <arn> Use secret ARN directly (skips SSM discovery)\");\n logInfo(\" --db-host <host> Database host (skips SSM lookup)\");\n logInfo(\" --ssl <mode> SSL mode: require, no-verify, disable\");\n logInfo(\" --port <port> Local port for tunnel (default: 5432)\");\n logInfo(\" --stage <stage> Stage for legacy discovery mode\");\n logInfo(\"\");\n logInfo(\"Examples:\");\n logInfo(\" # Explicit mode (recommended)\");\n logInfo(\" mesh db exec --tenant mesh --env dev --ssl=require -- npx prisma db push\");\n logInfo(\"\");\n logInfo(\" # Direct mode (with existing tunnel)\");\n logInfo(\" mesh db exec --secret=arn:aws:... --ssl=require -- pnpm dev\");\n process.exit(1);\n }\n\n const localPort = options.port ? parseInt(options.port, 10) : DEFAULT_LOCAL_PORT;\n const secretsManager = new SecretsManagerClient({});\n let tunnel: ChildProcess | null = null;\n let databaseUrl: string | undefined;\n\n // ==========================================================================\n // Direct mode: --secret provided, use it directly\n // ==========================================================================\n if (options.secret) {\n logInfo(`Direct mode: using secret ${options.secret}`);\n\n // Check if tunnel is running\n const tunnelExists = await checkPort(localPort);\n if (!tunnelExists) {\n logError(`No tunnel found on port ${localPort}`);\n logInfo(\"In direct mode, start a tunnel first with: mesh db connect\");\n logInfo(\"Or use discovery mode (without --secret) to auto-start tunnel\");\n process.exit(1);\n }\n logSuccess(`Using existing tunnel on port ${localPort}`);\n\n // Fetch secret\n logInfo(`Fetching credentials from secret...`);\n const secret = await fetchSecretWithRetry(secretsManager, options.secret);\n\n // Secret should contain DATABASE_URL directly (new format)\n if (secret.DATABASE_URL) {\n databaseUrl = secret.DATABASE_URL;\n logSuccess(\"Got DATABASE_URL from secret\");\n } else if (secret.username && secret.password) {\n // Legacy format with individual fields\n const dbName = secret.dbname ?? secret.database ?? \"postgres\";\n databaseUrl = `postgresql://${secret.username}:${encodeURIComponent(secret.password)}@localhost:${localPort}/${dbName}`;\n logSuccess(`Got credentials for user: ${secret.username}`);\n } else {\n logError(\"Secret must contain DATABASE_URL or username/password fields\");\n process.exit(1);\n }\n\n // Rewrite DATABASE_URL for local tunnel\n try {\n const parsed = new URL(databaseUrl);\n parsed.hostname = \"localhost\";\n parsed.port = String(localPort);\n\n // Apply SSL mode if specified\n if (options.ssl) {\n parsed.searchParams.set(\"sslmode\", options.ssl);\n if (options.ssl === \"require\" || options.ssl === \"no-verify\") {\n parsed.searchParams.set(\"sslaccept\", \"accept_invalid_certs\");\n }\n }\n\n databaseUrl = parsed.toString();\n } catch {\n logWarn(\"Could not parse DATABASE_URL for rewriting\");\n }\n }\n // ==========================================================================\n // Discovery mode: find credentials via SSM lookups\n // ==========================================================================\n else {\n // Use explicit --tenant/--env if provided, otherwise fall back to detectContext\n let platformTenant: string;\n let platformEnv: string;\n\n if (options.tenant && options.env) {\n // Explicit mode: use provided tenant/env directly (like tunnel command)\n platformTenant = options.tenant;\n platformEnv = options.env;\n logInfo(`Explicit mode: Platform Tenant=${platformTenant}, Platform Env=${platformEnv}`);\n } else if (options.tenant || options.env) {\n // Partial explicit mode - warn and require both\n logError(\"Both --tenant and --env are required when using explicit mode\");\n logInfo(\"Usage: mesh db exec --tenant mesh --env dev-temporal --app rdc --app-tenant encore --app-stage dev -- <command>\");\n logInfo(\"Or omit both to use auto-detection\");\n process.exit(1);\n } else {\n // Auto-detection mode (legacy behavior)\n const ctx = detectContext();\n platformTenant = ctx.tenant;\n platformEnv = ctx.platformEnv;\n logInfo(`Discovery mode: Platform=${platformEnv}, Tenant=${platformTenant}`);\n }\n\n // For credentials, use app-specific options if provided, else fall back to platform values\n const appTenant = options.appTenant ?? platformTenant;\n const appStage = options.appStage ?? platformEnv;\n const appName = options.app;\n\n if (appName) {\n logInfo(`App credentials: tenant=${appTenant}, stage=${appStage}, app=${appName}`);\n }\n\n const tunnelExists = await checkPort(localPort);\n\n // Try SST outputs first (fast path when sst dev is running)\n const sstOutputs = findSstOutputs();\n\n if (sstOutputs?.secretArn && tunnelExists) {\n logInfo(`Found SST outputs in: ${sstOutputs.rootDir}`);\n\n try {\n const secret = await fetchSecretWithRetry(secretsManager, sstOutputs.secretArn);\n\n if (secret.DATABASE_URL) {\n databaseUrl = rewriteDatabaseUrl(secret.DATABASE_URL, {\n endpoint: `localhost:${localPort}`,\n sslMode: options.ssl,\n });\n logSuccess(`Using DATABASE_URL from SST outputs`);\n }\n } catch {\n logWarn(\"Could not fetch from SST outputs, falling back to credential lookup\");\n }\n }\n\n // Lookup credentials from Secrets Manager if not found in SST outputs\n if (!databaseUrl) {\n // Start tunnel if needed\n if (!tunnelExists) {\n const bastion = await getPlatformBastionInfo(platformTenant, platformEnv);\n const rdsService = bastion.services.rds;\n if (!rdsService) {\n throw new Error(\"RDS service not available in platform bastion\");\n }\n tunnel = await startTunnelBackground(\n bastion.instanceId,\n rdsService.host,\n rdsService.port,\n localPort\n );\n } else {\n logSuccess(`Using existing tunnel on port ${localPort}`);\n }\n\n // Get DATABASE_URL and rewrite for tunnel\n const rawUrl = await getDatabaseUrl(appTenant, appStage, { app: appName });\n databaseUrl = rewriteDatabaseUrl(rawUrl, {\n endpoint: `localhost:${localPort}`,\n sslMode: options.ssl,\n });\n }\n }\n\n // ==========================================================================\n // Set NODE_TLS_REJECT_UNAUTHORIZED for SSL through tunnels\n // ==========================================================================\n const env: NodeJS.ProcessEnv = { ...process.env, DATABASE_URL: databaseUrl };\n\n if (options.ssl === \"require\" || options.ssl === \"no-verify\") {\n env.NODE_TLS_REJECT_UNAUTHORIZED = \"0\";\n logInfo(\"Set NODE_TLS_REJECT_UNAUTHORIZED=0 for SSL through tunnel\");\n }\n\n // ==========================================================================\n // Cleanup and run command\n // ==========================================================================\n const cleanup = () => {\n if (tunnel) {\n logInfo(\"Stopping tunnel...\");\n tunnel.kill();\n }\n };\n process.on(\"exit\", cleanup);\n process.on(\"SIGINT\", cleanup);\n process.on(\"SIGTERM\", cleanup);\n\n const [cmd, ...args] = commandArgs;\n logInfo(`Running: ${commandArgs.join(\" \")}`);\n console.log(\"\");\n\n const child = spawn(cmd!, args, { stdio: \"inherit\", env });\n\n child.on(\"exit\", (code: number | null) => {\n cleanup();\n process.exit(code ?? 0);\n });\n\n child.on(\"error\", (err: Error) => {\n logError(`Failed to run command: ${err.message}`);\n cleanup();\n process.exit(1);\n });\n}\n", "/**\n * Database commands\n *\n * mesh db connect - Start tunnel for manual psql access\n * mesh db credentials - Print database credentials\n * mesh db env - Export DATABASE_URL for shell\n * mesh db psql - Connect to database via psql\n * mesh db exec - Run any command with database connection\n */\n\nimport { Command } from \"commander\";\nimport { connectCommand } from \"./connect.js\";\nimport { credentialsCommand } from \"./credentials.js\";\nimport { envCommand } from \"./env.js\";\nimport { psqlCommand } from \"./psql.js\";\nimport { execCommand } from \"./exec.js\";\n\nexport function registerDbCommands(program: Command): void {\n const db = program\n .command(\"db\")\n .description(\"Database utilities\");\n\n db.command(\"connect\")\n .description(\"Start DB tunnel for manual psql access\")\n .option(\"-t, --tenant <tenant>\", \"Platform tenant (e.g., mesh)\")\n .option(\"-e, --env <env>\", \"Platform environment (e.g., dev-temporal)\")\n .action(connectCommand);\n\n db.command(\"credentials\")\n .alias(\"creds\")\n .description(\"Print database credentials\")\n .option(\"-t, --tenant <tenant>\", \"Platform tenant (e.g., mesh)\")\n .option(\"-e, --env <env>\", \"Platform environment (e.g., dev-temporal)\")\n .option(\"-a, --app <app>\", \"App name for credentials path (e.g., rdc)\")\n .option(\"--app-tenant <tenant>\", \"Tenant for app credentials (e.g., encore)\")\n .option(\"--app-stage <stage>\", \"Stage for app credentials (e.g., dev)\")\n .action(credentialsCommand);\n\n db.command(\"env\")\n .description(\"Export DATABASE_URL for current shell (use with eval)\")\n .option(\"-t, --tenant <tenant>\", \"Platform tenant (e.g., mesh)\")\n .option(\"-e, --env <env>\", \"Platform environment (e.g., dev-temporal)\")\n .option(\"-a, --app <app>\", \"App name for credentials path (e.g., rdc)\")\n .option(\"--app-tenant <tenant>\", \"Tenant for app credentials (e.g., encore)\")\n .option(\"--app-stage <stage>\", \"Stage for app credentials (e.g., dev)\")\n .action(envCommand);\n\n db.command(\"psql\")\n .description(\"Connect to database with psql\")\n .option(\"-t, --tenant <tenant>\", \"Platform tenant (e.g., mesh)\")\n .option(\"-e, --env <env>\", \"Platform environment (e.g., dev-temporal)\")\n .option(\"-a, --app <app>\", \"App name for credentials path (e.g., rdc)\")\n .option(\"--app-tenant <tenant>\", \"Tenant for app credentials (e.g., encore)\")\n .option(\"--app-stage <stage>\", \"Stage for app credentials (e.g., dev)\")\n .action(psqlCommand);\n\n db.command(\"exec\")\n .description(\"Run any command with database connection\")\n .option(\"-t, --tenant <tenant>\", \"Platform tenant for bastion lookup (e.g., mesh)\")\n .option(\"-e, --env <env>\", \"Platform environment for bastion lookup (e.g., dev-temporal)\")\n .option(\"-a, --app <app>\", \"App name for credentials path (e.g., rdc)\")\n .option(\"--app-tenant <tenant>\", \"Tenant for app credentials if different from platform (e.g., encore)\")\n .option(\"--app-stage <stage>\", \"Stage for app credentials (e.g., dev)\")\n .option(\"--secret <arn>\", \"Use secret ARN directly (skips SSM discovery)\")\n .option(\"--ssl <mode>\", \"SSL mode: require, no-verify, disable\")\n .option(\"--port <port>\", \"Local tunnel port (default: 5432)\")\n .argument(\"<command...>\", \"Command and arguments to run\")\n .action(execCommand);\n}\n", "/**\n * Deploy preflight \u2014 guard `mesh deploy` (pulumi up/preview/destroy/refresh) in a\n * DEPLOY repo against a stale `node_modules` (MESH-2266).\n *\n * The hazard: a teammate pulls a `@mesh-tech/*` version bump (package.json +\n * pnpm-lock.yaml move together in the commit) but forgets `pnpm install`, so\n * `node_modules` still links the OLD version. The pulumi program then evaluates\n * OLD component code and produces a plan that DELETES resources the new code would\n * keep \u2014 the exact incident that showed `VpnJoinBroker` (+~40 resources) as a\n * delete on mesh-dev when node_modules lagged the 1.0.1 bump. This is the same\n * stale-artifact class as the monorepo stale-dist detector (MESH-2019) and the\n * canonical CLI (MESH-2261), one layer up with higher stakes.\n *\n * The check is cheap and precise: compare each `@mesh-tech/*` version the LOCKFILE\n * says should be installed against what is ACTUALLY installed in `node_modules`.\n * A mismatch means `pnpm install` hasn't run since the lockfile changed. We only\n * gate program-EVALUATING ops (a stale install can't corrupt `whoami`/`stack\n * output`), and source-linked deps (`link:`/`file:`/dev-link pnpmfile) are skipped\n * \u2014 they are intentionally pointed at live source and never \"stale\".\n */\nimport { existsSync, readFileSync } from 'node:fs';\nimport { dirname, join, relative } from 'node:path';\nimport { parse as parseYaml } from 'yaml';\nimport { logWarn } from './log.js';\n\n/** A `@mesh-tech/*` dep whose installed version differs from the lockfile's. */\nexport interface DepMismatch {\n name: string;\n /** Version the lockfile says should be installed. */\n expected: string;\n /** Version actually resolvable in node_modules, or null if not installed. */\n installed: string | null;\n}\n\n/** Package-name prefixes whose version drift changes the pulumi plan. */\nconst GATED_PREFIXES = ['@mesh-tech/'] as const;\n\n/** pulumi ops that EVALUATE the program (a stale install can produce a wrong plan). */\nexport const PROGRAM_EVAL_OPS = new Set(['up', 'preview', 'destroy', 'refresh', 'import']);\n\n/** Env escape hatch \u2014 set truthy to skip the preflight (e.g. deliberate local link testing). */\nexport const SKIP_ENV = 'MESH_SKIP_DEPLOY_PREFLIGHT';\n\nfunction isGated(name: string): boolean {\n return GATED_PREFIXES.some((p) => name.startsWith(p));\n}\n\n/**\n * A lockfile `version:` is checkable only when it's a concrete published version.\n * `link:\u2026`/`file:\u2026` (dev-link pnpmfile, local tarballs) point at live source and\n * are never stale; anything not starting with a digit isn't a comparable version.\n * Peer/patch suffixes (`1.0.1(react@18)`) are stripped to the bare version.\n */\nexport function normalizeLockVersion(raw: unknown): string | null {\n if (typeof raw !== 'string' || raw.length === 0) return null;\n const bare = raw.split('(')[0]!.trim();\n return /^\\d/.test(bare) ? bare : null;\n}\n\n/**\n * Pure: extract the gated (`@mesh-tech/*`), concretely-versioned deps for one\n * importer of a parsed pnpm-lock document \u2192 `{ name: expectedVersion }`.\n *\n * Handles the pnpm v9 shape (`{ specifier, version }` per dep) and the older flat\n * shape (`name: \"1.0.1\"`). Unknown importer \u2192 `{}` (nothing checkable).\n */\nexport function extractImporterMeshVersions(\n lockDoc: unknown,\n importerRel: string,\n): Record<string, string> {\n const out: Record<string, string> = {};\n const importers = (lockDoc as { importers?: Record<string, unknown> } | null)?.importers;\n const importer = importers?.[importerRel] as Record<string, unknown> | undefined;\n if (!importer) return out;\n for (const group of ['dependencies', 'devDependencies', 'optionalDependencies'] as const) {\n const deps = importer[group] as Record<string, unknown> | undefined;\n if (!deps) continue;\n for (const [name, entry] of Object.entries(deps)) {\n if (!isGated(name)) continue;\n const raw = typeof entry === 'string' ? entry : (entry as { version?: unknown })?.version;\n const version = normalizeLockVersion(raw);\n if (version) out[name] = version;\n }\n }\n return out;\n}\n\n/**\n * Pure: diff the lockfile's expected versions against the installed ones. A dep\n * is a mismatch when the installed version differs (or it isn't installed).\n */\nexport function diffLockVsInstalled(\n expected: Record<string, string>,\n installed: Record<string, string | null>,\n): DepMismatch[] {\n const out: DepMismatch[] = [];\n for (const [name, exp] of Object.entries(expected)) {\n const got = installed[name] ?? null;\n if (got !== exp) out.push({ name, expected: exp, installed: got });\n }\n return out;\n}\n\n/** Walk up from `startDir` to the nearest directory containing a `pnpm-lock.yaml`. */\nexport function findPnpmLock(startDir: string): string | null {\n let dir = startDir;\n for (;;) {\n const candidate = join(dir, 'pnpm-lock.yaml');\n if (existsSync(candidate)) return candidate;\n const parent = dirname(dir);\n if (parent === dir) return null;\n dir = parent;\n }\n}\n\n/**\n * Read the installed version of `name` from `fromDir`'s `node_modules`, or null.\n *\n * Reads `node_modules/<name>/package.json` DIRECTLY (following pnpm's symlink into\n * the store) rather than `require.resolve(`${name}/package.json`)`: Node's exports\n * gate throws `ERR_PACKAGE_PATH_NOT_EXPORTED` for the many `@mesh-tech/*` packages\n * whose `exports` omit `./package.json` (e.g. `tsconfig`, `pulumi-utils`) \u2014 which\n * would return null \u2192 a FALSE \"stale\" hard-stop on a correctly-installed repo that\n * `pnpm install` can't clear. A plain read sidesteps the gate and stays scoped to\n * THIS importer's node_modules instead of walking up to a hoisted copy owned by\n * another importer (MESH-2266 review).\n */\nfunction readInstalledVersion(fromDir: string, name: string): string | null {\n try {\n const pkgPath = join(fromDir, 'node_modules', name, 'package.json');\n const version = (JSON.parse(readFileSync(pkgPath, 'utf8')) as { version?: string }).version;\n return typeof version === 'string' ? version : null;\n } catch {\n return null;\n }\n}\n\n/**\n * Check that the `@mesh-tech/*` deps installed in `appRoot`'s `node_modules` match\n * what the pnpm lockfile says. Returns the list of mismatches (empty = fresh), or\n * `null` when the check does not apply (no lockfile \u2014 not a pnpm repo, or the\n * monorepo running without one). IO wrapper around the pure helpers above.\n */\nexport function checkDeployDepsFresh(appRoot: string): DepMismatch[] | null {\n const lockPath = findPnpmLock(appRoot);\n if (!lockPath) return null;\n let lockDoc: unknown;\n try {\n lockDoc = parseYaml(readFileSync(lockPath, 'utf8'));\n } catch {\n // Don't block the deploy on our own parse failure \u2014 but a silently-disabled\n // safety guard is worse than a noisy one, so surface that the check is off.\n logWarn(\n `deploy preflight: could not parse ${lockPath} \u2014 skipping the stale-node_modules check.`,\n );\n return null;\n }\n const importerRel = relative(dirname(lockPath), appRoot) || '.';\n const expected = extractImporterMeshVersions(lockDoc, importerRel);\n const names = Object.keys(expected);\n if (names.length === 0) return [];\n const installed: Record<string, string | null> = {};\n for (const name of names) installed[name] = readInstalledVersion(appRoot, name);\n return diffLockVsInstalled(expected, installed);\n}\n\n/** Human-readable stale-deps report (mirrors the stale-dist detector's style). */\nexport function formatStaleDepsError(mismatches: DepMismatch[]): string {\n const lines = [\n `\u2717 ${mismatches.length} @mesh-tech/* dep${mismatches.length === 1 ? '' : 's'} in node_modules ` +\n `do not match the lockfile \u2014 run pnpm install before deploying:`,\n '',\n ];\n for (const m of mismatches) {\n lines.push(\n ` \u2022 ${m.name} \u2014 installed ${m.installed ?? '(missing)'}, lockfile wants ${m.expected}`,\n );\n }\n lines.push(\n '',\n ' A stale node_modules makes pulumi evaluate OLD component code and can plan to',\n ' DELETE resources the current code would keep (MESH-2266). Fix:',\n '',\n ' pnpm install',\n '',\n ` To bypass this check (rarely correct): ${SKIP_ENV}=1 mesh deploy \u2026`,\n );\n return lines.join('\\n');\n}\n\n/**\n * Gate a `mesh deploy` invocation: if `op` evaluates the pulumi program and the\n * deploy repo's `node_modules` is stale vs the lockfile, print the fix and exit\n * non-zero BEFORE pulumi runs. No-op for non-evaluating ops, a fresh install, a\n * non-pnpm repo, or when the skip env is set. Kept side-effecting (log + exit) so\n * `deploy.ts` stays a thin wiring layer; the decision logic is pure above.\n */\nexport function assertDeployDepsFresh(appRoot: string, op: string): void {\n if (!PROGRAM_EVAL_OPS.has(op)) return;\n if (process.env[SKIP_ENV]) return;\n const mismatches = checkDeployDepsFresh(appRoot);\n if (!mismatches || mismatches.length === 0) return;\n process.stderr.write(formatStaleDepsError(mismatches) + '\\n');\n process.exit(1);\n}\n", "/**\n * mesh deploy \u2014 Pulumi passthrough with automatic deployer role assumption.\n *\n * Credential resolution order:\n * 1. If AWS credentials already in environment (CI/CD) \u2192 use directly\n * 2. If ~/.config/mesh/credentials.json has a valid token for the\n * platform context \u2192 AssumeRoleWithWebIdentity (Zitadel JWT)\n * 3. Fallback \u2192 AssumeRole via current AWS session (SSO)\n *\n * The platform context (e.g., \"mesh.dev\") is derived from `mesh:platform`\n * in the Pulumi stack config file (read directly from YAML, no AWS needed).\n *\n * Setup:\n * pulumi config set mesh:deployerRole arn:aws:iam::123456789012:role/acme-dev-apps-deployer\n *\n * Examples:\n * mesh deploy preview\n * mesh deploy up --yes\n * mesh deploy stack output dev --json\n * mesh deploy destroy\n */\n\nimport { Command } from \"commander\";\nimport { execFileSync } from \"child_process\";\nimport { logError, logWarn } from \"../utils/log.js\";\nimport { findAppRoot, getCurrentStack, readStackConfig } from \"../utils/pulumi.js\";\nimport { resolvePulumiEnv } from \"../utils/pulumi-run.js\";\nimport { assertDeployDepsFresh } from \"../utils/deploy-preflight.js\";\nimport { resolveWorktreeIdentity, stackNeedsWorktreeIsolation } from \"../utils/worktree-identity.js\";\n\n// =============================================================================\n// Helpers\n// =============================================================================\n\n// Pulumi ops that take no `-s/--stack` at all \u2014 appending one makes pulumi\n// reject the command (\"unknown flag: --stack\").\nconst OPS_WITHOUT_STACK_FLAG = new Set([\n \"whoami\", \"version\", \"plugin\", \"login\", \"logout\", \"about\", \"org\", \"env\", \"help\",\n]);\n// `pulumi stack <sub>` subcommands whose stack is a POSITIONAL arg (or none),\n// so `-s` either conflicts (\"only one of --stack or argument stack name\") or is\n// rejected. `stack output`/`export`/`import`/`history` DO take `-s`, so they are\n// deliberately absent here and get the flag.\nconst STACK_SUBCOMMANDS_WITHOUT_FLAG = new Set([\n \"rm\", \"select\", \"init\", \"rename\", \"unselect\", \"ls\",\n]);\n\n/**\n * Build the pulumi arg list from the user's (stack-stripped) `mesh deploy` args.\n * Defaults to `up` when no subcommand is given, then appends the resolved\n * `-s <stack>` ONLY for ops that accept it \u2014 never for no-stack ops (`whoami`,\n * `version`, `plugin`) or positional-stack lifecycle ops (`stack rm <name>`),\n * which a forced `-s` used to break. Pure \u2014 unit-tested.\n */\nexport function buildPulumiArgs(pulumiArgs: string[], stack: string): string[] {\n const base = pulumiArgs.length === 0 || pulumiArgs[0]?.startsWith(\"-\")\n ? [\"up\", ...pulumiArgs]\n : [...pulumiArgs];\n const op = base[0];\n const takesStackFlag =\n !!op &&\n !OPS_WITHOUT_STACK_FLAG.has(op) &&\n !(op === \"stack\" && STACK_SUBCOMMANDS_WITHOUT_FLAG.has(base[1] ?? \"\"));\n return takesStackFlag ? [...base, \"-s\", stack] : base;\n}\n\n/**\n * Parse --stack or -s from the args array.\n */\nexport function parseStackFromArgs(args: string[]): string | null {\n for (let i = 0; i < args.length; i++) {\n if (args[i] === \"--stack\" || args[i] === \"-s\") {\n return args[i + 1] ?? null;\n }\n if (args[i]?.startsWith(\"--stack=\")) {\n return args[i]!.split(\"=\")[1] ?? null;\n }\n }\n return null;\n}\n\n/**\n * Remove `--stack`/`-s` (and its value) from the args \u2014 it is mesh's stack\n * SELECTOR (picks the target + which deployer role to assume), not a pulumi flag\n * to forward verbatim. `buildPulumiArgs` re-adds a `-s` only for ops that accept\n * one, so ops like `whoami` don't receive a rejected `--stack`.\n */\nexport function stripStackFromArgs(args: string[]): void {\n for (let i = args.length - 1; i >= 0; i--) {\n if (args[i] === \"--stack\" || args[i] === \"-s\") {\n args.splice(i, 2);\n } else if (args[i]?.startsWith(\"--stack=\")) {\n args.splice(i, 1);\n }\n }\n}\n\n// =============================================================================\n// Command\n// =============================================================================\n\nexport function registerDeployCommand(program: Command): void {\n program\n .command(\"deploy\")\n .description(\"Run pulumi with the app's deployer role (passthrough)\")\n .allowUnknownOption(true)\n .allowExcessArguments(true)\n .helpOption(false) // Don't consume --help, pass it to pulumi\n .action(async (_opts, cmd) => {\n const pulumiArgs = cmd.args as string[];\n\n // Find app root\n const appRoot = findAppRoot(process.cwd());\n if (!appRoot) {\n logError(\"No Pulumi.yaml found. Run from within a Pulumi app directory.\");\n process.exit(1);\n }\n\n // Determine the stack to credential against \u2014 from --stack/-s (mesh's\n // selector), else the currently-selected stack \u2014 then STRIP it from the\n // args. `buildPulumiArgs` re-adds `-s <stack>` only for ops that accept it,\n // so ops with a positional stack (`stack rm <name>`) or none (`whoami`)\n // aren't broken by a forced/rejected `-s`.\n const stack = parseStackFromArgs(pulumiArgs) ?? getCurrentStack(appRoot);\n stripStackFromArgs(pulumiArgs);\n if (!stack) {\n logError(\n \"Could not determine stack. Either:\\n\" +\n \" - Pass --stack <name> (e.g., mesh deploy up --stack dev-<you> --yes)\\n\" +\n \" - Create a personal dev stack first: mesh stack init (it prints the exact --stack command)\"\n );\n process.exit(1);\n }\n\n // Worktree-collision guard (MESH-2013 Slice 3): a personal deploy:false\n // stack whose name carries no worktree token collides with the same stack\n // deployed from another worktree \u2014 identical SSM export paths\n // (ParameterAlreadyExists) and Temporal namespace. Warn on mutating ops\n // from a LINKED worktree so the failure names itself before pulumi hits it.\n const op = pulumiArgs.length === 0 || pulumiArgs[0]?.startsWith(\"-\") ? \"up\" : pulumiArgs[0];\n\n // Stale-node_modules guard (MESH-2266): before evaluating the pulumi program,\n // verify the installed @mesh-tech/* deps match the lockfile. A stale install\n // makes pulumi evaluate OLD component code and can plan to DELETE resources\n // the current code keeps. Hard-stops with `pnpm install` on mismatch; a no-op\n // for read-only ops, a fresh install, a non-pnpm repo, or the skip env.\n assertDeployDepsFresh(appRoot, op ?? \"up\");\n\n if (op === \"up\" || op === \"destroy\") {\n const wt = resolveWorktreeIdentity(appRoot);\n const isPersonal = readStackConfig(appRoot, stack, \"mesh:deploy\") === \"false\";\n if (isPersonal && stackNeedsWorktreeIsolation(stack, wt)) {\n logWarn(\n `Stack \"${stack}\" carries no worktree token, but you're in linked worktree \"${wt.slug}\".\\n` +\n ` Deploying it from multiple worktrees at once collides on SSM export paths\\n` +\n ` (ParameterAlreadyExists) and the Temporal namespace. To isolate this worktree:\\n` +\n ` mesh stack init --worktree\\n` +\n ` Continuing with \"${stack}\" \u2014 pass --stack to target a different one.`,\n );\n }\n }\n\n // Login preflight + deployer-role assumption (shared chokepoint,\n // MESH-2085): resolves creds with a clear \"run mesh login --device\"\n // message on an expired/absent session, instead of failing deep in pulumi.\n const credEnv = await resolvePulumiEnv({ appRoot, stack });\n\n // Build environment \u2014 inherit current env, override AWS creds,\n // remove AWS_PROFILE so the assumed creds are used\n const env = { ...process.env, ...credEnv };\n delete env.AWS_PROFILE;\n\n // Default to \"up\" when no Pulumi subcommand is provided\n const finalArgs = buildPulumiArgs(pulumiArgs, stack);\n\n // Exec pulumi with the assumed role, targeting the resolved stack\n try {\n execFileSync(\"pulumi\", finalArgs, {\n cwd: appRoot,\n env,\n stdio: \"inherit\",\n });\n } catch (err: any) {\n // execFileSync throws on non-zero exit. The output was already\n // printed via stdio: \"inherit\", so just exit with the same code.\n process.exit(err.status ?? 1);\n }\n });\n}\n", "/**\n * The `docs.json` contract \u2014 the one file that turns a directory into portal\n * content, and the reserved-name list that keeps internal material\n * unpublishable even inside an opted-in directory.\n *\n * The reserved list is the safety property of the whole design: it is frozen,\n * deliberately coarse, and matched case-insensitively against every path\n * segment at any depth. Publishing internal material takes TWO mistakes \u2014\n * adding a `docs.json` to a directory that holds it AND moving the material\n * out of a reserved directory. Keep the list coarse; when a document should be\n * public, move the document to a publishable directory rather than narrowing\n * the list.\n */\n\nimport { z } from \"zod\";\n\n/**\n * Directory/file names that never publish, at any depth beneath a doc root.\n * Matched case-insensitively against each individual path segment.\n *\n * Evidence-derived from the repo's own `docs/` tree (plans/, superpowers/,\n * incidents/, handoffs/, HRAN/, reviews/, runbooks/, proposals/, designs/,\n * templates/ hold the internal corpus) plus the tooling directories that must\n * never leak (node_modules, __tests__, .claude, .pi) and the generic internal\n * markers (archive, internal, drafts).\n */\nexport const RESERVED_SEGMENTS: readonly string[] = [\n \"plans\",\n \"designs\",\n \"proposals\",\n \"incidents\",\n \"handoffs\",\n \"reviews\",\n \"runbooks\",\n \"hran\",\n \"superpowers\",\n \"templates\",\n \"archive\",\n \"internal\",\n \"drafts\",\n \"node_modules\",\n \"__tests__\",\n \".claude\",\n \".pi\",\n];\n\n/**\n * A doc root's declaration. Everything else about the site is derived from the\n * tree, never declared \u2014 this schema is deliberately tiny, and STRICT: an\n * unknown key is a typo the author meant something by, so it fails validation\n * rather than being silently ignored.\n */\nexport const docsJsonSchema = z\n .object({\n /** Section label in the nav, e.g. \"Building apps\". */\n title: z.string().min(1),\n /**\n * Section position in the nav. Ties break alphabetically by title, so two\n * sections can never fight over a slot nondeterministically.\n */\n order: z.number().int().default(50),\n /**\n * Route prefix for the section. Defaults to the slugified title. The\n * empty string is legal and means \"this section lives at the site root\" \u2014\n * exactly one root should do that (the front door, `docs/portal`).\n */\n slug: z\n .string()\n .regex(\n /^$|^[a-z0-9]+(?:-[a-z0-9]+)*$/,\n 'slug must be lower-kebab-case or \"\"',\n )\n .optional(),\n /**\n * Escape hatch: explicit repo-relative paths to publish that live outside\n * any natural doc root (a package README, a repo-root policy file). Expected\n * to hold a handful of entries across the whole repo \u2014 adding one is a\n * deliberate, reviewable act. Paths under a reserved segment are refused.\n */\n include: z.array(z.string().min(1)).default([]),\n })\n .strict();\n\nexport type DocsJson = z.infer<typeof docsJsonSchema>;\n\n/** True when one path segment is a reserved name (case-insensitive). */\nexport function isReservedSegment(segment: string): boolean {\n const lowered = segment.toLowerCase();\n return RESERVED_SEGMENTS.some((reserved) => reserved === lowered);\n}\n\n/**\n * True when ANY segment of a repo-relative path is reserved. This is the\n * fail-closed check the CI gate runs over every assembled output path.\n */\nexport function hasReservedSegment(relPath: string): boolean {\n return relPath.split(\"/\").some(isReservedSegment);\n}\n\n/** Lower-kebab-case form of a title or filename stem, for routes. */\nexport function slugify(value: string): string {\n return (\n value\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\") || \"index\"\n );\n}\n", "/**\n * Doc-root discovery.\n *\n * The one rule of the portal: **a directory publishes its markdown if, and\n * only if, it contains a `docs.json`.** This module finds those directories,\n * validates their declarations, and walks them for publishable pages \u2014\n * skipping any path with a reserved segment (at any depth) and any `README.md`\n * (a README is the directory's GitHub face, not portal content; a root that\n * wants one published names it in `include[]`, the escape hatch).\n *\n * Discovery is purely about *which files* publish. Reading their content \u2014\n * titles, front-matter, links \u2014 is assembly's job (`assemble.ts`).\n */\n\nimport { existsSync, readdirSync, readFileSync, statSync } from \"node:fs\";\nimport path from \"node:path\";\n\nimport type { DocsJson } from \"./schema.js\";\nimport { docsJsonSchema, hasReservedSegment, slugify } from \"./schema.js\";\n\n/** A validated doc root. */\nexport interface DocRoot {\n /** Repo-relative directory holding the docs.json, posix separators. */\n dir: string;\n config: DocsJson;\n /** Route prefix \u2014 `config.slug` or the slugified title. \"\" means site root. */\n slug: string;\n}\n\n/** One publishable markdown file. */\nexport interface DiscoveredPage {\n /** Repo-relative source path, posix separators. */\n source: string;\n /** The root that claimed it. */\n root: DocRoot;\n /**\n * Route path inside the section, no leading slash \u2014 e.g.\n * `primitives/service`. \"\" for the section's own index page.\n */\n routePath: string;\n /** True when the page came from `include[]` rather than the tree walk. */\n included: boolean;\n}\n\nexport interface Discovery {\n roots: DocRoot[];\n pages: DiscoveredPage[];\n /** Every structural problem found, human-readable. Non-empty fails --check. */\n errors: string[];\n}\n\n/**\n * Directories the walk never descends into while LOOKING FOR roots. This list\n * is about walk performance and sanity (`.git`, build output), and is\n * deliberately separate from the reserved list, which is about publish\n * safety. `node_modules` is on both: it is huge, and it must never publish.\n */\nconst ROOT_WALK_SKIP = new Set([\n \".git\",\n \"node_modules\",\n \"dist\",\n \".turbo\",\n \".next\",\n \".deploy\",\n \".generated\",\n \"coverage\",\n \".portal\",\n \".vercel\",\n \".wrangler\",\n]);\n\n/**\n * The route a page gets inside its section: the path relative to the root,\n * each segment slugified, the `.md` dropped, and a trailing `index` collapsed\n * so a directory's index page serves at the directory's route.\n */\nexport function routePathFor(relPath: string): string {\n const withoutExt = relPath.replace(/\\.md$/i, \"\");\n const parts = withoutExt.split(\"/\").map(slugify);\n // A trailing `index` segment collapses: the file serves at its directory's\n // route (a root-level index.md is the section's own landing page).\n if (parts[parts.length - 1] === \"index\") parts.pop();\n return parts.join(\"/\");\n}\n\n/** Recursively collect `*.md` files under `dir`, skipping reserved segments. */\nfunction walkMarkdown(\n absDir: string,\n relDir: string,\n errors: string[],\n rootDir: string,\n): string[] {\n const out: string[] = [];\n let entries;\n try {\n entries = readdirSync(absDir, { withFileTypes: true });\n } catch {\n return out;\n }\n\n for (const entry of entries) {\n const rel = relDir ? `${relDir}/${entry.name}` : entry.name;\n if (hasReservedSegment(entry.name)) {\n // Reserved names are silently skipped in the walk \u2014 exclusion here is\n // the normal case, not an error. The gate separately asserts that\n // nothing reserved ever reaches the OUTPUT (fail-closed).\n continue;\n }\n const abs = path.join(absDir, entry.name);\n if (entry.isDirectory()) {\n if (entry.name === \"node_modules\" || entry.name.startsWith(\".\")) continue;\n out.push(...walkMarkdown(abs, rel, errors, rootDir));\n } else if (entry.isFile() && entry.name.toLowerCase().endsWith(\".md\")) {\n // A README is the directory's GitHub face \u2014 it does not publish via the\n // walk. The include[] escape hatch is how a README becomes a page.\n if (entry.name.toLowerCase() === \"readme.md\") continue;\n out.push(rel);\n } else if (\n entry.isFile() &&\n entry.name === \"docs.json\" &&\n relDir !== \"\" // the root's own docs.json is the declaration, not content\n ) {\n errors.push(\n `nested doc root: ${rootDir}/.../${rel} \u2014 a docs.json inside another doc root is ambiguous; give it its own sibling root or remove it`,\n );\n }\n }\n return out;\n}\n\n/**\n * Find every doc root under `repoRoot`, validate it, and collect its pages.\n *\n * The walk looks for `docs.json` files anywhere in the repo (excluding the\n * ROOT_WALK_SKIP directories), so a package opts in by adding one file and\n * nothing else. Roots are sorted by (order, title); pages within a root are\n * sorted by route path so assembly is deterministic.\n */\nexport function discoverDocRoots(repoRoot: string): Discovery {\n const errors: string[] = [];\n const roots: DocRoot[] = [];\n\n const findRoots = (\n absDir: string,\n relDir: string,\n insideReserved: boolean,\n ): void => {\n let entries;\n try {\n entries = readdirSync(absDir, { withFileTypes: true });\n } catch {\n return;\n }\n\n const hasDocsJson = entries.some(\n (e) => e.isFile() && e.name === \"docs.json\",\n );\n if (hasDocsJson) {\n const rel = relDir || \".\";\n if (insideReserved || (relDir && hasReservedSegment(relDir))) {\n // Fail-closed: a root under a reserved directory is the \"mistake one\"\n // half of the leak scenario. Refusing it here means even a deliberate\n // docs.json in docs/plans/ publishes nothing.\n errors.push(\n `doc root ${rel}/ is under a reserved segment \u2014 it publishes nothing. Move the content out of the reserved directory instead.`,\n );\n } else {\n const root = loadRoot(absDir, rel, errors);\n // An invalid declaration publishes NOTHING \u2014 assembling pages under a\n // guessed title/slug could put content at routes nobody reviewed.\n if (root) roots.push(root);\n }\n // Never look for further roots inside a claimed root \u2014 a nested\n // docs.json is reported by the page walk instead (ambiguous ownership).\n return;\n }\n\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n if (ROOT_WALK_SKIP.has(entry.name)) continue;\n // Dot-directories are tooling, not content \u2014 ALL of them, so a\n // .pi/docs.json is skipped here exactly like a .claude one. The page\n // walk does the same, so a root found there could never publish anyway.\n if (entry.name.startsWith(\".\")) continue;\n const rel = relDir ? `${relDir}/${entry.name}` : entry.name;\n findRoots(\n path.join(absDir, entry.name),\n rel,\n insideReserved || hasReservedSegment(entry.name),\n );\n }\n };\n\n findRoots(repoRoot, \"\", false);\n\n const pages: DiscoveredPage[] = [];\n for (const root of roots) {\n const absRoot = path.join(repoRoot, root.dir);\n const relFiles = walkMarkdown(absRoot, \"\", errors, root.dir);\n for (const relPath of relFiles.sort()) {\n pages.push({\n source: root.dir === \".\" ? relPath : `${root.dir}/${relPath}`,\n root,\n routePath: routePathFor(relPath),\n included: false,\n });\n }\n\n for (const includePath of root.config.include) {\n const normalized = includePath\n .replace(/\\\\/g, \"/\")\n .replace(/^\\.\\//, \"\")\n .replace(/\\/+$/, \"\");\n if (hasReservedSegment(normalized)) {\n errors.push(\n `${root.dir}/docs.json includes ${normalized}, which is under a reserved segment \u2014 include[] cannot pull internal material into the site`,\n );\n continue;\n }\n if (!normalized.toLowerCase().endsWith(\".md\")) {\n errors.push(\n `${root.dir}/docs.json includes ${normalized}, which is not a markdown file`,\n );\n continue;\n }\n if (!existsSync(path.join(repoRoot, normalized))) {\n errors.push(\n `${root.dir}/docs.json includes ${normalized}, which does not exist`,\n );\n continue;\n }\n if (pages.some((p) => p.source === normalized)) continue; // walked already\n const stem = path.posix.basename(normalized).replace(/\\.md$/i, \"\");\n pages.push({\n source: normalized,\n root,\n // An included README is the section's index page \u2014 \"a package README\n // is its natural overview page\". Anything else routes by its stem.\n routePath: stem.toLowerCase() === \"readme\" ? \"\" : slugify(stem),\n included: true,\n });\n }\n }\n\n // Route collisions are authoring mistakes two files cannot both survive \u2014\n // catch them at discovery so the failure names both sources.\n const seenRoutes = new Map<string, string>();\n for (const page of pages) {\n const route = [page.root.slug, page.routePath].filter(Boolean).join(\"/\");\n const existing = seenRoutes.get(route);\n if (existing) {\n errors.push(\n `route collision: ${page.source} and ${existing} both map to /${route || \"(site root)\"}`,\n );\n }\n seenRoutes.set(route, page.source);\n }\n\n roots.sort(\n (a, b) =>\n a.config.order - b.config.order ||\n a.config.title.localeCompare(b.config.title),\n );\n\n return { roots, pages, errors };\n}\n\n/** Parse and validate one root's docs.json. Returns null (and records why) when invalid \u2014 an invalid declaration publishes nothing. */\nfunction loadRoot(\n absDir: string,\n relDir: string,\n errors: string[],\n): DocRoot | null {\n const configPath = path.join(absDir, \"docs.json\");\n let raw: unknown;\n try {\n raw = JSON.parse(readFileSync(configPath, \"utf-8\"));\n } catch (error) {\n errors.push(\n `${relDir}/docs.json is not valid JSON: ${error instanceof Error ? error.message : String(error)}`,\n );\n return null;\n }\n\n const parsed = docsJsonSchema.safeParse(raw);\n if (!parsed.success) {\n for (const issue of parsed.error.issues) {\n errors.push(\n `${relDir}/docs.json: ${issue.path.join(\".\") || \"(root)\"}: ${issue.message}`,\n );\n }\n return null;\n }\n\n const config = parsed.data;\n const slug = config.slug ?? slugify(config.title);\n return { dir: relDir, config, slug };\n}\n\n/** What exists at `candidate`, or null. Link resolution needs the file/dir split for blob-vs-tree URLs. */\nexport function pathKind(candidate: string): \"file\" | \"dir\" | null {\n try {\n const stat = statSync(candidate);\n return stat.isDirectory() ? \"dir\" : \"file\";\n } catch {\n return null;\n }\n}\n", "/**\n * Assembly: turn the discovered doc roots into a plain content tree plus a\n * navigation manifest, ready for a docs renderer (Zudoku today) to build.\n *\n * The seam of the whole design is here: assembly's output is a directory of\n * markdown files, a generated `zudoku.config.ts`, and a publish manifest.\n * Nothing downstream knows about Mesh; nothing upstream knows about Zudoku.\n *\n * What assembly does, per page:\n * - derives the title (front-matter `title:` \u2192 first `#` heading \u2192 filename)\n * and writes it into the assembled front-matter, so nav labels and page\n * titles can never drift apart\n * - rewrites links: a relative link between two published files is correct\n * *on disk* but meaningless at a route, so published targets become\n * routes, unpublished-but-real files become repo blob links (reported as\n * `external`), and links that resolve to nothing are reported `broken`\n * - footers the page with the exact repo file it came from, so a reader who\n * spots a mistake knows where to fix it\n *\n * It also emits the publish manifest \u2014 every source path that made it into\n * the site \u2014 which the CI gate uploads and diffs so growing the public\n * surface is a thing a reviewer sees.\n */\n\nimport { execFileSync } from \"node:child_process\";\nimport { mkdirSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { parse as parseYaml } from \"yaml\";\n\nimport type { DiscoveredPage, Discovery } from \"./discover.js\";\nimport { pathKind } from \"./discover.js\";\nimport { hasReservedSegment } from \"./schema.js\";\n\nexport type LinkIssueKind = \"broken\" | \"external\";\n\nexport interface LinkIssue {\n kind: LinkIssueKind;\n /** Route of the page whose markdown contains the link. */\n page: string;\n /** The href exactly as written in the source markdown. */\n href: string;\n}\n\nexport interface AssembledPage {\n /** Repo-relative source path. */\n source: string;\n /** Absolute site route, e.g. \"/building-apps/primitives/service\" or \"/\". */\n route: string;\n /** Route without the leading slash \u2014 also the assembled file's stem path. */\n filePath: string;\n title: string;\n sectionTitle: string;\n sectionOrder: number;\n sectionSlug: string;\n /** Position within its directory: front-matter `order:` \u2192 undefined (filename sort). */\n order?: number;\n}\n\nexport interface PublishManifest {\n version: 1;\n count: number;\n /** Every repo-relative source path that made it into the site, sorted. */\n sources: string[];\n}\n\nexport interface AssembleResult {\n outDir: string;\n pages: AssembledPage[];\n navigation: unknown[];\n brokenLinks: LinkIssue[];\n externalLinks: LinkIssue[];\n publishManifest: PublishManifest;\n /** Fail-closed assertion data: assembled output paths containing a reserved segment. */\n reservedViolations: string[];\n}\n\nconst DEFAULT_REPO_URL = \"https://github.com/mesh-tech/mesh-platform\";\nconst DEFAULT_IGNORE_LINK_PREFIXES = [\"node_modules/\"];\n\n// ---------------------------------------------------------------------------\n// Front-matter\n// ---------------------------------------------------------------------------\n\ninterface FrontMatter {\n data: Record<string, unknown>;\n body: string;\n hasFrontMatter: boolean;\n}\n\n/**\n * Split a markdown document into front-matter and body. Only a `---` fence on\n * the very first line counts \u2014 a horizontal rule later in the prose is not\n * front-matter. A YAML parse failure is not fatal: the document is treated as\n * having no front-matter (the heading/filename title fallbacks still apply),\n * because one bad page must not take the whole site down at assemble time.\n */\nexport function splitFrontMatter(markdown: string): FrontMatter {\n const normalized = markdown.replace(/^\\uFEFF/, \"\");\n if (!normalized.startsWith(\"---\\n\") && !normalized.startsWith(\"---\\r\\n\")) {\n return { data: {}, body: markdown, hasFrontMatter: false };\n }\n const end = normalized.indexOf(\"\\n---\", 4);\n if (end === -1) return { data: {}, body: markdown, hasFrontMatter: false };\n\n const rawBlock = normalized.slice(4, end);\n const bodyStart = normalized.indexOf(\"\\n\", end + 1);\n const body = (\n bodyStart === -1 ? \"\" : normalized.slice(bodyStart + 1)\n ).replace(/^\\r?\\n/, \"\");\n\n try {\n const data = parseYaml(rawBlock) as unknown;\n if (data && typeof data === \"object\" && !Array.isArray(data)) {\n return {\n data: data as Record<string, unknown>,\n body,\n hasFrontMatter: true,\n };\n }\n } catch {\n // fall through to the no-front-matter shape\n }\n return { data: {}, body, hasFrontMatter: true };\n}\n\n/** Serialize front-matter data + body back into a markdown document. */\nfunction joinFrontMatter(data: Record<string, unknown>, body: string): string {\n const lines = Object.entries(data).map(([key, value]) => {\n if (typeof value === \"number\" || typeof value === \"boolean\")\n return `${key}: ${value}`;\n const text = String(value);\n // Quote only when YAML would misread the bare form.\n return /^[\\w .,'\u2019()/-]+$/.test(text)\n ? `${key}: ${text}`\n : `${key}: ${JSON.stringify(text)}`;\n });\n return `---\\n${lines.join(\"\\n\")}\\n---\\n\\n${body.replace(/^\\s*\\n/, \"\")}`;\n}\n\n// ---------------------------------------------------------------------------\n// Title derivation\n// ---------------------------------------------------------------------------\n\n/** First `#` heading text, or undefined. Headings inside code fences don't count. */\nfunction firstHeading(body: string): string | undefined {\n let inFence = false;\n for (const line of body.split(\"\\n\")) {\n if (/^\\s*(```|~~~)/.test(line)) {\n inFence = !inFence;\n continue;\n }\n if (inFence) continue;\n const match = /^#\\s+(.+?)\\s*#*\\s*$/.exec(line);\n if (match) return match[1]!.trim();\n }\n return undefined;\n}\n\n/** Titleize a filename stem for the filename-fallback case: `hub-dev-local` \u2192 \"Hub dev local\". */\nfunction titleizeStem(stem: string): string {\n const words = stem.replace(/[-_]+/g, \" \").trim();\n return words.charAt(0).toUpperCase() + words.slice(1);\n}\n\n/**\n * The title derivation order, fixed by the design: front-matter `title:` \u2192\n * first `#` heading \u2192 filename. `sidebar_label` wins for the nav when present\n * (Zudoku honours it), but the document still gets its real title.\n */\nexport function deriveTitle(\n frontMatter: Record<string, unknown>,\n body: string,\n source: string,\n): string {\n const fmTitle = frontMatter.title;\n if (typeof fmTitle === \"string\" && fmTitle.trim()) return fmTitle.trim();\n const heading = firstHeading(body);\n if (heading) return heading;\n const stem = path.posix.basename(source).replace(/\\.md$/i, \"\");\n return titleizeStem(stem);\n}\n\n// ---------------------------------------------------------------------------\n// Link rewriting\n// ---------------------------------------------------------------------------\n\n/**\n * A careful markdown link scanner. Regexes over raw markdown false-positive on\n * link-shaped text inside code fences and inline code, which this corpus is\n * full of, so the scanner tracks:\n *\n * - fenced code blocks (``` / ~~~, possibly indented, closed by a matching fence)\n * - inline code spans (a run of N backticks closes only on a run of N)\n * - inline links/images `[text](href \"title\")` / `![alt](src)`\n * - reference definitions `[id]: href` at line start\n * - autolinks `<https://\u2026>` (absolute already \u2014 left alone)\n *\n * Reference-style link USES (`[text][id]`) resolve through the collected\n * definitions; the definition itself is rewritten, so uses follow for free.\n */\ninterface LinkHit {\n /** Start offset of the href within the document. */\n start: number;\n /** End offset (exclusive) of the href. */\n end: number;\n href: string;\n}\n\nfunction scanLinks(markdown: string): LinkHit[] {\n const hits: LinkHit[] = [];\n const lines = markdown.split(\"\\n\");\n let offset = 0;\n let inFence: { marker: string } | null = null;\n\n for (const line of lines) {\n const fenceMatch = /^(\\s{0,3})(`{3,}|~{3,})/.exec(line);\n if (fenceMatch) {\n if (!inFence) {\n inFence = { marker: fenceMatch[2]![0]! };\n } else if (fenceMatch[2]!.startsWith(inFence.marker)) {\n inFence = null;\n }\n offset += line.length + 1;\n continue;\n }\n if (inFence) {\n offset += line.length + 1;\n continue;\n }\n\n // Reference definitions: [id]: href \u2014 the href runs to end of line\n // (optionally followed by a title). Rewrite in place.\n const refDef = /^ {0,3}\\[[^\\]]+\\]:\\s*(\\S+)/.exec(line);\n if (refDef) {\n const href = refDef[1]!;\n const start = offset + line.indexOf(href);\n hits.push({ start, end: start + href.length, href });\n offset += line.length + 1;\n continue;\n }\n\n // Inline links/images, skipping inline code spans.\n let i = 0;\n while (i < line.length) {\n const ch = line[i]!;\n if (ch === \"`\") {\n const run = /^`+/.exec(line.slice(i))![0];\n const close = line.indexOf(run, i + run.length);\n i = close === -1 ? line.length : close + run.length;\n continue;\n }\n if (ch === \"<\") {\n const close = line.indexOf(\">\", i);\n i = close === -1 ? line.length : close + 1;\n continue;\n }\n if (ch === \"!\" && line[i + 1] === \"[\") {\n i = scanBracketLink(line, i + 1, offset, hits);\n continue;\n }\n if (ch === \"[\") {\n i = scanBracketLink(line, i, offset, hits);\n continue;\n }\n i++;\n }\n offset += line.length + 1;\n }\n return hits;\n}\n\n/**\n * At `line[i] === \"[\"`, try to read `[...](href \u2026)` or `[...][id]`. Only the\n * `(...)` form carries an inline href we can rewrite; reference uses are\n * covered by rewriting their definitions.\n */\nfunction scanBracketLink(\n line: string,\n open: number,\n lineOffset: number,\n hits: LinkHit[],\n): number {\n const closeBracket = line.indexOf(\"]\", open);\n if (closeBracket === -1) return line.length;\n if (line[closeBracket + 1] !== \"(\") return closeBracket + 1;\n\n let j = closeBracket + 2;\n while (j < line.length && /\\s/.test(line[j]!)) j++;\n if (line[j] === \"<\") {\n const end = line.indexOf(\">\", j);\n if (end === -1) return line.length;\n hits.push({\n start: lineOffset + j + 1,\n end: lineOffset + end,\n href: line.slice(j + 1, end),\n });\n return end + 1;\n }\n const closeParen = line.indexOf(\")\", j);\n if (closeParen === -1) return line.length;\n const inner = line.slice(j, closeParen).trim();\n // href may be followed by a \"title\" \u2014 split on the first space.\n const space = inner.search(/\\s/);\n const href = space === -1 ? inner : inner.slice(0, space);\n if (href) {\n const start = lineOffset + line.indexOf(href, j);\n hits.push({ start, end: start + href.length, href });\n }\n return closeParen + 1;\n}\n\nexport interface LinkResolution {\n href: string;\n issue?: LinkIssue;\n}\n\n/**\n * Remove HTML comments (`<!-- \u2026 -->`, single- or multi-line) from a page body.\n * They are invisible in any rendered output by definition \u2014 the source file\n * keeps them \u2014 and multi-line comments currently crash Zudoku's MDX plugin\n * (`chunks[startIndex].slice is not a function`), which turns one authored\n * comment into a failed site build. Fenced code blocks are left alone: a doc\n * *teaching* HTML comments shows them as code, and that code must survive.\n */\nexport function stripHtmlComments(body: string): string {\n const lines = body.split(\"\\n\");\n const out: string[] = [];\n let inFence = false;\n let inComment = false;\n\n for (const line of lines) {\n if (/^\\s*(```|~~~)/.test(line)) {\n if (!inComment) inFence = !inFence;\n if (!inComment) out.push(line);\n continue;\n }\n if (inFence) {\n out.push(line);\n continue;\n }\n\n let rest = line;\n let rebuilt = \"\";\n while (rest.length > 0) {\n if (inComment) {\n const end = rest.indexOf(\"-->\");\n if (end === -1) {\n rest = \"\";\n break;\n }\n inComment = false;\n rest = rest.slice(end + 3);\n continue;\n }\n const start = rest.indexOf(\"<!--\");\n if (start === -1) {\n rebuilt += rest;\n break;\n }\n rebuilt += rest.slice(0, start);\n inComment = true;\n rest = rest.slice(start + 4);\n }\n // A line that held only a comment collapses to nothing; a line with prose\n // around a comment keeps its prose.\n if (rebuilt.trim() !== \"\" || !inComment)\n out.push(rebuilt.replace(/\\s+$/, \"\"));\n }\n\n return out.join(\"\\n\").replace(/\\n{3,}/g, \"\\n\\n\");\n}\n\nfunction isAbsoluteHref(href: string): boolean {\n return /^(?:[a-z][a-z0-9+.-]*:|\\/\\/)/i.test(href);\n}\n\nfunction normalizeRepoPath(value: string): string {\n return path.posix\n .normalize(value.replace(/\\\\/g, \"/\"))\n .replace(/^\\.\\//, \"\")\n .replace(/\\/+$/, \"\");\n}\n\nfunction splitHash(href: string): [string, string] {\n const index = href.indexOf(\"#\");\n return index === -1\n ? [href, \"\"]\n : [href.slice(0, index), href.slice(index + 1)];\n}\n\n/**\n * Resolve one link, exactly the #3503 semantics with routes instead of slugs:\n *\n * - anchors, absolute URLs, mailto: \u2192 untouched\n * - an `ignoreLinkPrefixes` match \u2192 untouched (declared deliberately\n * unresolvable \u2014 the app-kit README's `node_modules/\u2026` guidance exists in\n * a tenant's install, never in this repo)\n * - a file the portal publishes \u2192 that page's route\n * - a directory whose index/README the portal publishes \u2192 that route\n * - a real repo file the portal does not publish \u2192 a repo blob link\n * (reported `external`)\n * - nothing \u2192 reported `broken`\n * - a site-rooted path (`/guides/x`) \u2192 validated against the route set, so a\n * typo'd route fails the gate instead of shipping as a 404\n */\nexport function resolveLink(args: {\n href: string;\n pageRoute: string;\n sourceDir: string;\n sourceIndex: Map<string, AssembledPage>;\n routes: Set<string>;\n ignoreLinkPrefixes: string[];\n /** Exists-on-disk probe (file OR directory); returns \"file\" | \"dir\" | null. */\n pathKind: (repoRelPath: string) => \"file\" | \"dir\" | null;\n repoUrl: string;\n}): LinkResolution {\n const { href, pageRoute, sourceDir, sourceIndex, routes, repoUrl } = args;\n\n if (href.startsWith(\"#\") || isAbsoluteHref(href)) return { href };\n if (args.ignoreLinkPrefixes.some((prefix) => href.startsWith(prefix)))\n return { href };\n\n const [rawTarget, rawHash] = splitHash(href);\n const hash = rawHash ? `#${rawHash}` : \"\";\n if (rawTarget === \"\") return { href };\n\n // Site-rooted route reference.\n if (rawTarget.startsWith(\"/\")) {\n const route = rawTarget.replace(/\\/$/, \"\") || \"/\";\n return routes.has(route)\n ? { href: `${route}${hash}` }\n : { href, issue: { kind: \"broken\", page: pageRoute, href } };\n }\n\n const repoPath = normalizeRepoPath(path.posix.join(sourceDir, rawTarget));\n\n const page = sourceIndex.get(repoPath);\n if (page) return { href: `${page.route}${hash}` };\n\n // A link to a directory conventionally means its index page.\n for (const candidate of [`${repoPath}/index.md`]) {\n const indexPage = sourceIndex.get(normalizeRepoPath(candidate));\n if (indexPage) return { href: `${indexPage.route}${hash}` };\n }\n\n const kind = args.pathKind(repoPath);\n if (kind !== null) {\n const base = repoUrl.replace(/\\/$/, \"\").replace(/\\/(blob|tree)$/, \"\");\n return {\n href: `${base}/${kind === \"dir\" ? \"tree\" : \"blob\"}/main/${repoPath}${hash}`,\n issue: { kind: \"external\", page: pageRoute, href },\n };\n }\n\n return { href, issue: { kind: \"broken\", page: pageRoute, href } };\n}\n\n/** Rewrite every link in a page body, collecting issues. */\nexport function rewriteLinks(args: {\n body: string;\n page: AssembledPage;\n sourceIndex: Map<string, AssembledPage>;\n routes: Set<string>;\n ignoreLinkPrefixes: string[];\n pathKind: (repoRelPath: string) => \"file\" | \"dir\" | null;\n repoUrl: string;\n}): { body: string; issues: LinkIssue[] } {\n const issues: LinkIssue[] = [];\n const hits = scanLinks(args.body);\n if (hits.length === 0) return { body: args.body, issues };\n\n const sourceDir = path.posix.dirname(args.page.source);\n let out = \"\";\n let cursor = 0;\n for (const hit of hits) {\n const resolution = resolveLink({\n href: hit.href,\n pageRoute: args.page.route,\n sourceDir,\n sourceIndex: args.sourceIndex,\n routes: args.routes,\n ignoreLinkPrefixes: args.ignoreLinkPrefixes,\n pathKind: args.pathKind,\n repoUrl: args.repoUrl,\n });\n out += args.body.slice(cursor, hit.start) + resolution.href;\n cursor = hit.end;\n if (resolution.issue) issues.push(resolution.issue);\n }\n out += args.body.slice(cursor);\n return { body: out, issues };\n}\n\n// ---------------------------------------------------------------------------\n// Assembly\n// ---------------------------------------------------------------------------\n\nexport interface AssembleOptions {\n repoRoot: string;\n discovery: Discovery;\n /** Directory the assembled markdown tree is written to. */\n outDir: string;\n repoUrl?: string;\n ignoreLinkPrefixes?: string[];\n /**\n * Version string stamped into the footer + version.json \u2014 the fixed\n * lockstep group's version post-`changeset version`. Undefined outside a\n * release build.\n */\n meshBaseline?: string;\n /** Short commit the build is from. */\n commit?: string;\n}\n\n/** A page's full route: section slug + route path. \"/\" for the site home. */\nexport function pageRoute(page: DiscoveredPage): string {\n const joined = [page.root.slug, page.routePath].filter(Boolean).join(\"/\");\n return `/${joined}`.replace(/\\/$/, \"\") || \"/\";\n}\n\n/** The assembled file path (no leading slash, with extension). */\nexport function pageFilePath(route: string): string {\n return route === \"/\" ? \"index.md\" : `${route.slice(1)}.md`;\n}\n\n/**\n * Assemble the discovered pages into `outDir`. Pure function of the repo tree\n * \u2014 the same inputs always produce the same tree, manifest, and navigation.\n */\nexport function assemblePortal(options: AssembleOptions): AssembleResult {\n const { repoRoot, discovery, outDir } = options;\n const repoUrl = options.repoUrl ?? DEFAULT_REPO_URL;\n const ignoreLinkPrefixes =\n options.ignoreLinkPrefixes ?? DEFAULT_IGNORE_LINK_PREFIXES;\n\n // Build the page model first: routes must all exist before any link can be\n // rewritten against them.\n const pages: AssembledPage[] = discovery.pages.map((page) => {\n const route = pageRoute(page);\n return {\n source: page.source,\n route,\n filePath: pageFilePath(route),\n title: \"\",\n sectionTitle: page.root.config.title,\n sectionOrder: page.root.config.order,\n sectionSlug: page.root.slug,\n };\n });\n\n const sourceIndex = new Map<string, AssembledPage>(\n pages.map((p) => [normalizeRepoPath(p.source), p]),\n );\n const routes = new Set(pages.map((p) => p.route));\n\n const brokenLinks: LinkIssue[] = [];\n const externalLinks: LinkIssue[] = [];\n\n rmSync(outDir, { recursive: true, force: true });\n mkdirSync(outDir, { recursive: true });\n\n for (const page of pages) {\n const raw = readFileSync(path.join(repoRoot, page.source), \"utf-8\");\n const frontMatter = splitFrontMatter(raw);\n const title = deriveTitle(frontMatter.data, frontMatter.body, page.source);\n page.title = title;\n const order = frontMatter.data.order;\n if (typeof order === \"number\" && Number.isFinite(order)) page.order = order;\n\n const rewritten = rewriteLinks({\n body: stripHtmlComments(frontMatter.body),\n page,\n sourceIndex,\n routes,\n ignoreLinkPrefixes,\n pathKind: (rel) => pathKind(path.join(repoRoot, rel)),\n repoUrl,\n });\n for (const issue of rewritten.issues) {\n (issue.kind === \"broken\" ? brokenLinks : externalLinks).push(issue);\n }\n\n // Front-matter: keep the author's, guarantee `title`. `showLastModified`\n // is off \u2014 the assembled tree is rebuilt every run, so git-mtime-derived\n // dates would say \"today\" on every page.\n const outData: Record<string, unknown> = { ...frontMatter.data, title };\n\n const blobBase = repoUrl.replace(/\\/$/, \"\").replace(/\\/(blob|tree)$/, \"\");\n const sourceNote = `\\n\\n---\\n\\n<sub>Source: [\\`${page.source}\\`](${blobBase}/blob/main/${page.source}) \u2014 edit that file, not this page.</sub>\\n`;\n\n const outFile = path.join(outDir, page.filePath);\n mkdirSync(path.dirname(outFile), { recursive: true });\n writeFileSync(\n outFile,\n joinFrontMatter(outData, rewritten.body.trimEnd() + sourceNote),\n );\n }\n\n const navigation = buildNavigation(pages);\n\n // Fail-closed: no assembled output path may contain a reserved segment. The\n // walk already skips reserved directories, so a violation here means the\n // exclusion itself broke \u2014 exactly what the gate exists to catch.\n const reservedViolations = pages\n .map((p) => p.filePath)\n .filter((filePath) => hasReservedSegment(filePath));\n\n const publishManifest: PublishManifest = {\n version: 1,\n count: pages.length,\n sources: pages.map((p) => p.source).sort(),\n };\n\n return {\n outDir,\n pages,\n navigation,\n brokenLinks,\n externalLinks,\n publishManifest,\n reservedViolations,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Navigation\n// ---------------------------------------------------------------------------\n\ninterface NavDir {\n label: string;\n routePath: string; // section-relative route of the directory itself\n pages: AssembledPage[];\n dirs: Map<string, NavDir>;\n}\n\nfunction titleizeDir(name: string): string {\n return titleizeStem(name);\n}\n\n/**\n * Build the Zudoku navigation array from the assembled pages.\n *\n * Shape: one root category (\"Documentation\", clicking it lands on the home\n * page) whose items are one non-collapsible category per doc root \u2014 the\n * sidebar's section headers \u2014 each holding the section's tree: pages as doc\n * items, directories as nested categories. A directory with an index page\n * becomes a clickable category (its link); the section's own index page\n * becomes the section category's link. Order is front-matter `order:` first,\n * then filename \u2014 never declared anywhere but the files themselves.\n */\nexport function buildNavigation(pages: AssembledPage[]): unknown[] {\n const sections = new Map<\n string,\n { title: string; order: number; slug: string; pages: AssembledPage[] }\n >();\n for (const page of pages) {\n const key = page.sectionSlug;\n if (!sections.has(key)) {\n sections.set(key, {\n title: page.sectionTitle,\n order: page.sectionOrder,\n slug: page.sectionSlug,\n pages: [],\n });\n }\n sections.get(key)!.pages.push(page);\n }\n\n const sortedSections = [...sections.values()].sort(\n (a, b) => a.order - b.order || a.title.localeCompare(b.title),\n );\n\n const sortPages = (list: AssembledPage[]): AssembledPage[] =>\n [...list].sort(\n (a, b) =>\n (a.order ?? Number.MAX_SAFE_INTEGER) -\n (b.order ?? Number.MAX_SAFE_INTEGER) ||\n a.filePath.localeCompare(b.filePath),\n );\n\n // A nav doc reference (item or category link \u2014 same shape in both places).\n // A `path` is a CUSTOM path in Zudoku: when it equals the file-derived\n // route, the build moves the file's entry onto itself and deletes it\n // (resolveCustomNavigationPaths compares `path === file` without the\n // leading slash). The assembler already names files so the file route IS\n // the desired route \u2014 so `path` is only emitted for the one genuinely\n // custom mapping: the home page (file \"index\" \u2192 \"/\").\n const docRef = (page: AssembledPage): unknown => {\n const file = page.filePath.replace(/\\.md$/, \"\");\n return page.route === `/${file}`\n ? file\n : { type: \"doc\", file, path: page.route };\n };\n\n const items: unknown[] = [];\n for (const section of sortedSections) {\n const indexPage = section.pages.find(\n (p) =>\n p.route === `/${section.slug}` ||\n (section.slug === \"\" && p.route === \"/\"),\n );\n const rest = section.pages.filter((p) => p !== indexPage);\n\n // Group remaining pages by their section-relative directory.\n const rootPages: AssembledPage[] = [];\n const dirs = new Map<string, NavDir>();\n for (const page of rest) {\n const rel = page.route.replace(/^\\//, \"\");\n const sectionPrefix = section.slug ? `${section.slug}/` : \"\";\n const relParts = (\n sectionPrefix && rel.startsWith(sectionPrefix)\n ? rel.slice(sectionPrefix.length)\n : rel\n )\n .split(\"/\")\n .filter(Boolean);\n\n if (relParts.length <= 1) {\n rootPages.push(page);\n continue;\n }\n const dirKey = relParts.slice(0, -1).join(\"/\");\n if (!dirs.has(dirKey)) {\n dirs.set(dirKey, {\n label: titleizeDir(relParts[relParts.length - 2]!),\n routePath: relParts.slice(0, -1).join(\"/\"),\n pages: [],\n dirs: new Map(),\n });\n }\n dirs.get(dirKey)!.pages.push(page);\n }\n\n const byRoute = new Map(section.pages.map((p) => [p.route, p]));\n const childItems: unknown[] = sortPages(rootPages).map(docRef);\n\n for (const dir of [...dirs.values()].sort((a, b) =>\n a.routePath.localeCompare(b.routePath),\n )) {\n const dirRoute =\n `/${[section.slug, dir.routePath].filter(Boolean).join(\"/\")}`.replace(\n /\\/$/,\n \"\",\n ) || \"/\";\n const dirIndex = byRoute.get(dirRoute);\n const grandchildren = sortPages(\n dir.pages.filter((p) => p !== dirIndex),\n ).map(docRef);\n if (grandchildren.length === 0 && dirIndex) {\n childItems.push(docRef(dirIndex));\n continue;\n }\n childItems.push({\n type: \"category\",\n label: dir.label,\n ...(dirIndex ? { link: docRef(dirIndex) } : {}),\n items: grandchildren,\n });\n }\n\n items.push({\n type: \"category\",\n label: section.title,\n collapsible: false,\n ...(indexPage ? { link: docRef(indexPage) } : {}),\n items: childItems,\n });\n }\n\n return [\n {\n type: \"category\",\n label: \"Documentation\",\n link: { type: \"doc\", file: \"index\", path: \"/\" },\n items,\n },\n ];\n}\n\n// ---------------------------------------------------------------------------\n// Generated config + manifests\n// ---------------------------------------------------------------------------\n\n/**\n * Render the generated `zudoku.config.ts`. It is regenerated on every\n * assemble and gitignored \u2014 the navigation manifest is derived state, and\n * committed derived state is how the old manifest rotted.\n */\nexport function renderZudokuConfig(args: {\n navigation: unknown[];\n title: string;\n description: string;\n baseline?: string | undefined;\n commit?: string | undefined;\n}): string {\n const versionLine = args.baseline\n ? `Documents @mesh-tech/* ${args.baseline} \u00B7 built from ${args.commit ?? \"unknown\"}`\n : `Local build \u00B7 ${args.commit ?? \"unknown\"}`;\n\n const config = {\n metadata: {\n title: args.title,\n description: args.description,\n },\n site: {\n title: args.title,\n logoUrl: \"/\",\n footer: {\n copyright: `${versionLine} \u00B7 /version.json`,\n },\n },\n theme: \"THEME_IMPORT\",\n navigation: args.navigation,\n docs: {\n files: [\"/content/**/*.{md,mdx}\"],\n defaultOptions: {\n toc: true,\n showLastModified: false,\n },\n },\n redirects: [],\n // Search is Zudoku's built-in Pagefind index \u2014 no config needed.\n };\n\n const json = JSON.stringify(config, null, 2).replace(\n `\"THEME_IMPORT\"`,\n \"portalTheme\",\n );\n\n return `/**\n * GENERATED by \\`mesh docs portal\\` \u2014 do not edit.\n *\n * The navigation array is derived from the repo's docs.json roots and the\n * markdown tree beneath them. To change what the site publishes, change the\n * tree; to change section labels or order, change the root's docs.json.\n * Regenerate: pnpm exec mesh docs portal --assemble-only\n */\nimport type { ZudokuConfig } from \"zudoku\";\nimport { portalTheme } from \"./theme.js\";\n\nconst config: ZudokuConfig = ${json};\n\nexport default config;\n`;\n}\n\n/** version.json \u2014 the version-parity contract the parity monitor asserts. */\nexport function renderVersionJson(args: {\n baseline?: string | undefined;\n commit: string;\n builtAt: string;\n}): string {\n return `${JSON.stringify(\n {\n meshBaseline: args.baseline ?? null,\n commit: args.commit,\n builtAt: args.builtAt,\n },\n null,\n 2,\n )}\\n`;\n}\n\n/** Best-effort short commit of the repo being assembled. */\nexport function currentCommit(repoRoot: string): string {\n try {\n return execFileSync(\"git\", [\"rev-parse\", \"--short\", \"HEAD\"], {\n cwd: repoRoot,\n encoding: \"utf-8\",\n }).trim();\n } catch {\n return \"unknown\";\n }\n}\n\n/** The fixed lockstep group's version, read from app-kit's package.json. */\nexport function currentBaseline(repoRoot: string): string | undefined {\n try {\n const pkg = JSON.parse(\n readFileSync(path.join(repoRoot, \"libs/app-kit/package.json\"), \"utf-8\"),\n ) as { version?: string };\n return pkg.version;\n } catch {\n return undefined;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Publish-set diff (the PR job-summary surface)\n// ---------------------------------------------------------------------------\n\nexport interface PublishSetDiff {\n added: string[];\n removed: string[];\n}\n\n/**\n * Compute the publish set of another git ref WITHOUT checking it out \u2014 the\n * docs.json files and tree listing are read via `git show`/`git ls-tree`, and\n * the same discovery rules (reserved segments, README exclusion, include[])\n * are applied to that listing. Lets a PR diff its publish set against its\n * merge base in a CI job that has no second worktree and no installed deps\n * for the base.\n *\n * APPROXIMATION, base side only: this reimplementation skips schema\n * validation (an invalid docs.json publishes nothing in real discovery but\n * is walked here), nested-root rejection, and route-collision detection, so\n * it can OVER-report the base's publish set (a spurious \"removed\" row in the\n * summary) \u2014 never under-report the head's. The head side is always real\n * discovery; the gate's assertions never read this function.\n */\nexport function publishSetAtRef(repoRoot: string, ref: string): string[] {\n const git = (gitArgs: string[]): string =>\n execFileSync(\"git\", gitArgs, {\n cwd: repoRoot,\n encoding: \"utf-8\",\n maxBuffer: 64 * 1024 * 1024,\n });\n\n const allFiles = git([\"ls-tree\", \"-r\", \"--name-only\", ref])\n .split(\"\\n\")\n .filter(Boolean);\n const docsJsonPaths = allFiles.filter(\n (file) => file === \"docs.json\" || file.endsWith(\"/docs.json\"),\n );\n\n const published = new Set<string>();\n for (const docsJsonPath of docsJsonPaths) {\n const rootDir =\n docsJsonPath === \"docs.json\"\n ? \"\"\n : docsJsonPath.slice(0, -\"/docs.json\".length);\n if (rootDir && hasReservedSegment(rootDir)) continue;\n\n let config: { include?: string[] };\n try {\n config = JSON.parse(git([\"show\", `${ref}:${docsJsonPath}`])) as {\n include?: string[];\n };\n } catch {\n continue;\n }\n\n const prefix = rootDir ? `${rootDir}/` : \"\";\n for (const file of allFiles) {\n if (!file.startsWith(prefix) || !file.toLowerCase().endsWith(\".md\"))\n continue;\n const rel = file.slice(prefix.length);\n if (hasReservedSegment(rel)) continue;\n if (path.posix.basename(file).toLowerCase() === \"readme.md\") continue;\n published.add(file);\n }\n\n for (const include of config.include ?? []) {\n const normalized = include.replace(/\\\\/g, \"/\").replace(/^\\.\\//, \"\");\n if (hasReservedSegment(normalized)) continue;\n if (allFiles.includes(normalized)) published.add(normalized);\n }\n }\n\n return [...published].sort();\n}\n\nexport function diffPublishSets(\n base: string[],\n head: string[],\n): PublishSetDiff {\n const baseSet = new Set(base);\n const headSet = new Set(head);\n return {\n added: head.filter((source) => !baseSet.has(source)),\n removed: base.filter((source) => !headSet.has(source)),\n };\n}\n\n/** Render the publish-set diff as a GitHub job-summary markdown block. */\nexport function renderPublishSetSummary(\n manifest: PublishManifest,\n diff: PublishSetDiff | null,\n): string {\n const lines: string[] = [\n `## Docs portal publish set`,\n ``,\n `**${manifest.count} pages publish** from this tree.`,\n ``,\n ];\n if (diff && (diff.added.length > 0 || diff.removed.length > 0)) {\n lines.push(`### Changes vs the merge base`, ``);\n for (const source of diff.added) lines.push(`- \u2795 \\`${source}\\``);\n for (const source of diff.removed) lines.push(`- \u2796 \\`${source}\\``);\n lines.push(\n ``,\n `Growing the public surface is a deliberate act \u2014 a reviewer should see this list.`,\n );\n } else if (diff) {\n lines.push(`No change vs the merge base.`);\n }\n lines.push(``, `<details><summary>Full publish set</summary>`, ``);\n for (const source of manifest.sources) lines.push(`- \\`${source}\\``);\n lines.push(``, `</details>`);\n return `${lines.join(\"\\n\")}\\n`;\n}\n", "/**\n * Generate the `mesh` CLI reference from the commander tree.\n *\n * This is the load-bearing half of \"self-documenting\": the reference is not a\n * hand-maintained table that drifts from the code, it is a projection of the\n * same `Command` objects the CLI parses. Add a flag and the docs grow it; the\n * `--check` mode in `mesh docs` fails CI when the two diverge.\n *\n * Pure by construction \u2014 `extractCliReference` and `renderCliReferenceMarkdown`\n * do no I/O, so they are directly unit-testable.\n */\n\nimport os from \"node:os\";\nimport type { Command, Option } from \"commander\";\n\nexport interface CliOptionRef {\n /** Option flags exactly as declared, e.g. `-p, --port <n>`. */\n flags: string;\n description: string;\n /** Rendered default, if the option declares one. */\n defaultValue?: string;\n required: boolean;\n /** Enumerated allowed values, when the option declares `.choices()`. */\n choices?: string[];\n}\n\nexport interface CliCommandRef {\n /** Full invocation path, e.g. `mesh hub dev`. */\n path: string;\n /** Leaf name only, e.g. `dev`. */\n name: string;\n aliases: string[];\n description: string;\n /** Positional argument usage, e.g. `<context> [names...]`. */\n args: string;\n options: CliOptionRef[];\n /** Slug used for the anchor/id of this command's section. */\n slug: string;\n /** Nesting depth below the root program (top-level commands are 1). */\n depth: number;\n subcommands: CliCommandRef[];\n}\n\nexport interface CliReference {\n name: string;\n description: string;\n options: CliOptionRef[];\n commands: CliCommandRef[];\n}\n\n/** Commander's internals we read but which aren't on the public typings. */\ninterface CommandInternals {\n _name?: string;\n _aliases?: string[];\n _description?: string;\n _hidden?: boolean;\n commands?: Command[];\n options?: Option[];\n registeredArguments?: unknown[];\n _args?: unknown[];\n}\n\ninterface OptionInternals {\n flags?: string;\n description?: string;\n defaultValue?: unknown;\n required?: boolean;\n mandatory?: boolean;\n argChoices?: string[];\n hidden?: boolean;\n}\n\n/** Machine-specific paths that must never reach a committed artifact. */\nexport interface MachinePaths {\n homeDir: string;\n tmpDir: string;\n}\n\nfunction currentMachinePaths(): MachinePaths {\n return { homeDir: os.homedir(), tmpDir: os.tmpdir() };\n}\n\n/**\n * Collapse machine-specific absolute paths to the symbols a reader recognizes.\n *\n * Some option defaults are computed at registration time from the environment \u2014\n * `mesh install-shim --dir` defaults to `path.join(os.homedir(), \".local/bin\")`.\n * Rendered literally, the generated reference embeds whoever ran the generator\n * (`/Users/dmb/.local/bin` vs `/home/runner/.local/bin`), which makes the\n * artifact machine-dependent and the `--check` gate pass only on one laptop \u2014\n * exactly how this was caught, by CI failing a locally-green gate.\n *\n * Substituting `~` fixes determinism and is also what the reader wants to see.\n * Longest prefix first, since tmpdir can live under home on macOS.\n */\nexport function normalizeMachinePaths(value: string, paths: MachinePaths): string {\n const candidates: Array<{ prefix: string; symbol: string }> = [\n { prefix: paths.tmpDir, symbol: \"$TMPDIR\" },\n { prefix: paths.homeDir, symbol: \"~\" },\n ];\n\n const substitutions = candidates\n .filter((candidate) => candidate.prefix && candidate.prefix !== \"/\")\n .sort((a, b) => b.prefix.length - a.prefix.length);\n\n for (const { prefix, symbol } of substitutions) {\n if (value === prefix) return symbol;\n if (value.startsWith(`${prefix}/`)) return symbol + value.slice(prefix.length);\n }\n return value;\n}\n\n/**\n * Render a default value the way a reader would type it, not the way\n * `JSON.stringify` would: bare for strings so `docs/docs.config.json` doesn't\n * arrive wrapped in quotes, JSON for everything structured.\n *\n * `paths` is injectable so the normalization above is testable without\n * depending on the machine running the test.\n */\nexport function formatDefault(\n value: unknown,\n paths: MachinePaths = currentMachinePaths(),\n): string | undefined {\n if (value === undefined || value === null) return undefined;\n if (typeof value === \"string\") return normalizeMachinePaths(value, paths);\n if (typeof value === \"boolean\" || typeof value === \"number\") return String(value);\n return normalizeMachinePaths(JSON.stringify(value), paths);\n}\n\n/** Slugify a command path into a stable anchor: `mesh hub dev` \u2192 `mesh-hub-dev`. */\nexport function slugifyCommandPath(path: string): string {\n return path\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n}\n\nfunction extractOptions(command: Command): CliOptionRef[] {\n const options = (command as unknown as CommandInternals).options ?? [];\n return options\n .map((option) => option as unknown as OptionInternals)\n .filter((option) => !option.hidden)\n .map((option) => {\n const ref: CliOptionRef = {\n flags: option.flags ?? \"\",\n description: option.description ?? \"\",\n required: Boolean(option.mandatory ?? option.required ?? false),\n };\n const rendered = formatDefault(option.defaultValue);\n if (rendered !== undefined) ref.defaultValue = rendered;\n if (option.argChoices?.length) ref.choices = [...option.argChoices];\n return ref;\n });\n}\n\n/**\n * Positional-argument usage for a command.\n *\n * `Command.usage()` returns the whole `[options] <arg>` string; we want only\n * the positional part, since options are documented in their own table.\n */\nfunction extractArgs(command: Command): string {\n const internals = command as unknown as CommandInternals;\n const declared = internals.registeredArguments ?? internals._args ?? [];\n if (!Array.isArray(declared) || declared.length === 0) return \"\";\n\n return declared\n .map((argument) => {\n const arg = argument as { name?: () => string; required?: boolean; variadic?: boolean };\n const name = typeof arg.name === \"function\" ? arg.name() : \"arg\";\n const spread = arg.variadic ? \"...\" : \"\";\n return arg.required ? `<${name}${spread}>` : `[${name}${spread}]`;\n })\n .join(\" \");\n}\n\n/**\n * Commands the reference must not publish.\n *\n * Two kinds. Commander auto-registers a `help` subcommand on every group, which\n * documents commander rather than Mesh. And commands declared\n * `{ hidden: true }` are internal re-entry points the CLI spawns for itself\n * (`mesh dev __token-server`, `mesh vpn tunnel __run`) \u2014 `hidden` is already\n * this repo's signal for \"keep out of `--help`\", and the docs honor the same\n * signal rather than inventing a second one.\n */\nfunction isUndocumented(command: Command): boolean {\n const internals = command as unknown as CommandInternals;\n return internals._name === \"help\" || internals._hidden === true;\n}\n\nfunction extractCommand(command: Command, parentPath: string, depth: number): CliCommandRef {\n const internals = command as unknown as CommandInternals;\n const name = internals._name ?? \"\";\n const path = parentPath ? `${parentPath} ${name}` : name;\n\n return {\n path,\n name,\n aliases: [...(internals._aliases ?? [])],\n description: internals._description ?? \"\",\n args: extractArgs(command),\n options: extractOptions(command),\n slug: slugifyCommandPath(path),\n depth,\n subcommands: (internals.commands ?? [])\n .filter((child) => !isUndocumented(child))\n .map((child) => extractCommand(child, path, depth + 1)),\n };\n}\n\n/**\n * Project a commander program into a serializable reference tree.\n *\n * The root program's `--version` option is excluded: its value is the CLI\n * version, which would make the generated output differ on every release and\n * turn the `--check` gate into noise.\n */\nexport function extractCliReference(program: Command): CliReference {\n const internals = program as unknown as CommandInternals;\n const rootName = internals._name ?? \"mesh\";\n\n return {\n name: rootName,\n description: internals._description ?? \"\",\n options: extractOptions(program).filter(\n (option) => !/(^|\\s)(-V|--version)(\\s|,|$)/.test(option.flags),\n ),\n commands: (internals.commands ?? [])\n .filter((child) => !isUndocumented(child))\n .map((child) => extractCommand(child, rootName, 1)),\n };\n}\n\n/** Depth-first walk over every command in the tree, parents before children. */\nexport function flattenCommands(reference: CliReference): CliCommandRef[] {\n const flat: CliCommandRef[] = [];\n const visit = (command: CliCommandRef): void => {\n flat.push(command);\n command.subcommands.forEach(visit);\n };\n reference.commands.forEach(visit);\n return flat;\n}\n\n/**\n * Escape the characters that would break a markdown table cell.\n *\n * Backslash first, then pipe \u2014 the reverse order is subtly wrong. A description\n * containing a literal `\\|` would have its pipe escaped to `\\\\|`, which markdown\n * reads as \"escaped backslash, then a live cell delimiter\", splitting the row.\n * Escaping the backslash first makes it `\\\\\\|`: one literal backslash, one\n * escaped pipe.\n */\nfunction cell(text: string): string {\n return text\n .replace(/\\\\/g, \"\\\\\\\\\")\n .replace(/\\|/g, \"\\\\|\")\n .replace(/\\r?\\n/g, \" \")\n .trim();\n}\n\nfunction renderOptionsTable(options: CliOptionRef[]): string[] {\n if (options.length === 0) return [];\n\n const lines = [\"| Option | Description | Default |\", \"| --- | --- | --- |\"];\n for (const option of options) {\n const notes: string[] = [];\n if (option.required) notes.push(\"**required**\");\n if (option.choices?.length) notes.push(`one of: ${option.choices.join(\", \")}`);\n const description = [cell(option.description), ...notes].filter(Boolean).join(\" \u2014 \");\n const defaultValue = option.defaultValue === undefined ? \"\" : `\\`${cell(option.defaultValue)}\\``;\n lines.push(`| \\`${cell(option.flags)}\\` | ${description} | ${defaultValue} |`);\n }\n lines.push(\"\");\n return lines;\n}\n\nfunction renderCommand(command: CliCommandRef): string[] {\n // Cap heading depth at h4 \u2014 deeper nesting produces headings no navigation\n // renders, and Mesh's tree is at most `mesh <group> <cmd> <sub>`.\n const heading = \"#\".repeat(Math.min(command.depth + 1, 4));\n const usage = [command.path, command.options.length > 0 ? \"[options]\" : \"\", command.args]\n .filter(Boolean)\n .join(\" \");\n\n const lines = [`${heading} \\`${command.path}\\``, \"\"];\n if (command.description) lines.push(command.description, \"\");\n if (command.aliases.length > 0) {\n lines.push(`Alias: ${command.aliases.map((alias) => `\\`${alias}\\``).join(\", \")}`, \"\");\n }\n lines.push(\"```bash\", usage, \"```\", \"\");\n lines.push(...renderOptionsTable(command.options));\n command.subcommands.forEach((child) => lines.push(...renderCommand(child)));\n return lines;\n}\n\n/**\n * Render the reference as markdown.\n *\n * The output carries a generated-file banner naming the command that rebuilds\n * it, because the failure mode for generated docs is someone hand-editing the\n * artifact and losing the change on the next build.\n */\nexport function renderCliReferenceMarkdown(reference: CliReference): string {\n const lines = [\n \"<!--\",\n \" GENERATED FILE \u2014 do not edit by hand.\",\n \" Source: the commander tree in libs/mesh-cli/src/program.ts\",\n \" Rebuild: pnpm exec mesh docs cli-reference\",\n \"-->\",\n \"\",\n \"# `mesh` CLI reference\",\n \"\",\n reference.description,\n \"\",\n \"Every command below is generated from the CLI's own command tree, so this\",\n \"page cannot drift from the binary you have installed. Run any command with\",\n \"`--help` for the same information at the terminal.\",\n \"\",\n ];\n\n lines.push(...renderOptionsTable(reference.options));\n\n lines.push(\"## Commands\", \"\");\n for (const command of reference.commands) {\n const summary = cell(command.description) || \"\u2014\";\n lines.push(`- [\\`${command.path}\\`](#${command.slug}) \u2014 ${summary}`);\n }\n lines.push(\"\");\n\n reference.commands.forEach((command) => lines.push(...renderCommand(command)));\n\n // Collapse the blank-line runs that per-section rendering leaves behind.\n return `${lines.join(\"\\n\").replace(/\\n{3,}/g, \"\\n\\n\").trimEnd()}\\n`;\n}\n", "/**\n * `mesh docs portal` \u2014 assemble the developer portal from the repo's\n * docs.json-discovered markdown and hand it to the renderer (Zudoku) to build\n * or serve.\n *\n * Modes:\n *\n * mesh docs portal assemble \u2192 `zudoku build` \u2192 apps/docs/dist\n * mesh docs portal --serve assemble \u2192 `zudoku dev` (local preview)\n * mesh docs portal --assemble-only assemble and stop (content/, config,\n * manifests) \u2014 what CI runs before `build`\n * mesh docs portal --check the CI gate: assemble to a scratch dir and\n * fail on any of the four assertions below\n *\n * The four --check assertions, any of which exits non-zero:\n * 1. a docs.json fails schema validation (or any other discovery error)\n * 2. an assembled output path contains a reserved segment (fail-closed \u2014\n * internal material must never be publishable)\n * 3. an internal link resolves to nothing\n * 4. the committed CLI reference is stale (the command tree drifted)\n *\n * Assembly always writes `publish-manifest.json` \u2014 every source path that\n * made it into the site \u2014 which CI uploads as an artifact; on PRs\n * `--diff-base <ref>` also prints the added/removed published paths into the\n * GitHub job summary.\n */\n\nimport { spawn } from \"node:child_process\";\nimport {\n appendFileSync,\n existsSync,\n mkdirSync,\n mkdtempSync,\n readFileSync,\n writeFileSync,\n} from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport path from \"node:path\";\n\nimport { logError, logInfo, logSuccess, logWarn } from \"../utils/log.js\";\nimport {\n assemblePortal,\n currentBaseline,\n currentCommit,\n diffPublishSets,\n publishSetAtRef,\n renderPublishSetSummary,\n renderVersionJson,\n renderZudokuConfig,\n} from \"./assemble.js\";\nimport type { AssembleResult, PublishManifest } from \"./assemble.js\";\nimport { discoverDocRoots } from \"./discover.js\";\n\n/** The Zudoku app package directory, relative to the repo root. */\nexport const DOCS_APP_DIR = \"apps/docs\";\nconst CONTENT_DIR = \"content\";\nconst GENERATED_CONFIG = \"zudoku.config.ts\";\nconst PUBLISH_MANIFEST = \"publish-manifest.json\";\nconst VERSION_JSON_DIR = \"public\";\nconst VERSION_JSON = \"version.json\";\n\nconst SITE_TITLE = \"Mesh Developer Portal\";\nconst SITE_DESCRIPTION =\n \"Build and run financial-services apps on Mesh Platform with the mesh developer CLI.\";\n\nexport interface PortalRunResult {\n assembled: AssembleResult;\n errors: string[];\n}\n\n/**\n * Run discovery + assembly. Shared by every mode; the scratch-dir variant is\n * what --check uses so the gate never depends on (or dirties) apps/docs.\n */\nexport function runAssemble(args: {\n repoRoot: string;\n outDir: string;\n configOut?: string;\n writeFiles?: boolean;\n}): PortalRunResult {\n const discovery = discoverDocRoots(args.repoRoot);\n const assembled = assemblePortal({\n repoRoot: args.repoRoot,\n discovery,\n outDir: args.outDir,\n meshBaseline: currentBaseline(args.repoRoot),\n commit: currentCommit(args.repoRoot),\n });\n\n const errors = [...discovery.errors];\n\n if (args.writeFiles !== false) {\n // The manifest lands BESIDE the content dir for a real assemble\n // (apps/docs/publish-manifest.json \u2014 gitignored derived state) and INSIDE\n // the scratch dir for a --check run, so concurrent checks never share a\n // file and nothing is written loose to the tmpdir root.\n const manifestPath = args.outDir.includes(tmpdir())\n ? path.join(args.outDir, PUBLISH_MANIFEST)\n : path.join(args.outDir, \"..\", PUBLISH_MANIFEST);\n writeFileSync(\n manifestPath,\n `${JSON.stringify(assembled.publishManifest, null, 2)}\\n`,\n );\n\n if (args.configOut) {\n writeFileSync(\n args.configOut,\n renderZudokuConfig({\n navigation: assembled.navigation,\n title: SITE_TITLE,\n description: SITE_DESCRIPTION,\n baseline: currentBaseline(args.repoRoot),\n commit: currentCommit(args.repoRoot),\n }),\n );\n\n const versionDir = path.join(\n path.dirname(args.configOut),\n VERSION_JSON_DIR,\n );\n mkdirSync(versionDir, { recursive: true });\n writeFileSync(\n path.join(versionDir, VERSION_JSON),\n renderVersionJson({\n baseline: currentBaseline(args.repoRoot),\n commit: currentCommit(args.repoRoot),\n builtAt: new Date().toISOString(),\n }),\n );\n }\n }\n\n return { assembled, errors };\n}\n\n/** Print the assembly report: counts, external-link note, broken-link list. */\nexport function reportAssembly(result: PortalRunResult): void {\n const { assembled } = result;\n logSuccess(\n `Assembled ${assembled.pages.length} pages from ${new Set(assembled.pages.map((p) => p.sectionTitle)).size} sections \u2192 ${assembled.outDir}`,\n );\n\n if (assembled.externalLinks.length > 0) {\n const unique = new Set(\n assembled.externalLinks.map((issue) => `${issue.page} \u2192 ${issue.href}`),\n );\n logInfo(\n `${unique.size} link${unique.size === 1 ? \"\" : \"s\"} point at repo files outside the portal and were rewritten to blob links`,\n );\n }\n\n if (assembled.brokenLinks.length > 0) {\n logWarn(`${assembled.brokenLinks.length} link(s) resolve to nothing:`);\n for (const issue of assembled.brokenLinks) {\n logWarn(` ${issue.page}: ${issue.href}`);\n }\n }\n}\n\n/**\n * The --check gate. Returns the failure list (empty = pass). Also writes the\n * job-summary publish-set diff when --diff-base names a ref and\n * GITHUB_STEP_SUMMARY is writable.\n */\nexport async function checkPortal(args: {\n repoRoot: string;\n diffBase?: string | undefined;\n printManifest?: boolean;\n /** Stable path to write publish-manifest.json to (CI uploads it as an artifact). */\n manifestOut?: string | undefined;\n checkCliReference: () => Promise<string | null>;\n}): Promise<string[]> {\n const scratch = mkdtempSync(path.join(tmpdir(), \"mesh-docs-check-\"));\n const result = runAssemble({ repoRoot: args.repoRoot, outDir: scratch });\n\n const failures: string[] = [...result.errors];\n\n for (const violation of result.assembled.reservedViolations) {\n failures.push(\n `assembled output path contains a reserved segment: ${violation}`,\n );\n }\n\n for (const issue of result.assembled.brokenLinks) {\n failures.push(`broken link on ${issue.page}: ${issue.href}`);\n }\n\n const cliReferenceError = await args.checkCliReference();\n if (cliReferenceError) failures.push(cliReferenceError);\n\n reportAssembly(result);\n\n if (args.printManifest) {\n process.stdout.write(\n `${JSON.stringify(result.assembled.publishManifest, null, 2)}\\n`,\n );\n }\n\n if (args.manifestOut) {\n mkdirSync(path.dirname(args.manifestOut), { recursive: true });\n writeFileSync(\n args.manifestOut,\n `${JSON.stringify(result.assembled.publishManifest, null, 2)}\\n`,\n );\n }\n\n if (args.diffBase) {\n writePublishSetSummary(\n args.repoRoot,\n args.diffBase,\n result.assembled.publishManifest,\n );\n }\n\n return failures;\n}\n\n/** Diff the publish set against a git ref; print + append to the GH job summary. */\nfunction writePublishSetSummary(\n repoRoot: string,\n diffBase: string,\n manifest: PublishManifest,\n): void {\n let diff = null;\n try {\n const base = publishSetAtRef(repoRoot, diffBase);\n diff = diffPublishSets(base, manifest.sources);\n } catch (error) {\n logWarn(\n `could not compute the publish-set diff against ${diffBase}: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n\n const summary = renderPublishSetSummary(manifest, diff);\n process.stdout.write(`\\n${summary}`);\n\n const summaryPath = process.env.GITHUB_STEP_SUMMARY;\n if (summaryPath) {\n try {\n appendFileSync(summaryPath, summary);\n } catch {\n logWarn(`GITHUB_STEP_SUMMARY is set but not writable (${summaryPath})`);\n }\n }\n}\n\n/** Spawn the renderer. Returns its exit code. */\nfunction runZudoku(args: {\n appDir: string;\n mode: \"build\" | \"dev\";\n port?: number;\n}): Promise<number> {\n const cliArgs =\n args.mode === \"dev\"\n ? [\"dev\", \"--port\", String(args.port ?? 3000)]\n : [\"build\"];\n logInfo(`Running \\`zudoku ${cliArgs.join(\" \")}\\` in ${args.appDir}`);\n return new Promise((resolve, reject) => {\n const child = spawn(\"pnpm\", [\"exec\", \"zudoku\", ...cliArgs], {\n cwd: args.appDir,\n stdio: \"inherit\",\n env: process.env,\n });\n child.on(\"error\", reject);\n child.on(\"close\", (code) => resolve(code ?? 1));\n });\n}\n\nexport interface PortalCommandOptions {\n out?: string | undefined;\n assembleOnly?: boolean;\n serve?: boolean;\n port?: string;\n check?: boolean;\n printManifest?: boolean;\n diffBase?: string | undefined;\n manifestOut?: string | undefined;\n}\n\n/**\n * The command body. Kept free of commander types so the test suite can drive\n * it directly; `commands/docs.ts` is a thin flag adapter.\n */\nexport async function runPortalCommand(\n opts: PortalCommandOptions,\n deps: {\n repoRoot: string;\n checkCliReference: () => Promise<string | null>;\n },\n): Promise<void> {\n const { repoRoot } = deps;\n\n if (opts.check) {\n const failures = await checkPortal({\n repoRoot,\n diffBase: opts.diffBase,\n printManifest: opts.printManifest ?? false,\n manifestOut: opts.manifestOut,\n checkCliReference: deps.checkCliReference,\n });\n if (failures.length > 0) {\n for (const failure of failures) logError(failure);\n throw new Error(\n `docs portal check failed with ${failures.length} problem(s)`,\n );\n }\n logSuccess(\"Docs portal check passed\");\n return;\n }\n\n const appDir = path.join(repoRoot, DOCS_APP_DIR);\n const outDir = opts.out\n ? path.resolve(repoRoot, opts.out)\n : path.join(appDir, CONTENT_DIR);\n\n const result = runAssemble({\n repoRoot,\n outDir,\n configOut: path.join(appDir, GENERATED_CONFIG),\n });\n reportAssembly(result);\n\n if (result.errors.length > 0) {\n for (const error of result.errors) logError(error);\n throw new Error(\n `docs portal assembly failed with ${result.errors.length} problem(s)`,\n );\n }\n\n if (opts.assembleOnly || opts.out) {\n logInfo(\n `Assembled content at ${path.relative(repoRoot, outDir)} \u2014 build with: pnpm --filter @mesh-tech/docs build`,\n );\n return;\n }\n\n const mode = opts.serve ? \"dev\" : \"build\";\n let port: number | undefined;\n if (opts.serve && opts.port) {\n port = Number.parseInt(opts.port, 10);\n if (!Number.isInteger(port) || port < 0 || port > 65535) {\n throw new Error(`Invalid --port: ${opts.port}`);\n }\n }\n\n const code = await runZudoku({\n appDir,\n mode,\n ...(port !== undefined ? { port } : {}),\n });\n if (code !== 0) throw new Error(`zudoku ${mode} exited with code ${code}`);\n if (mode === \"build\") {\n logSuccess(\n `Portal built \u2192 ${path.join(path.relative(repoRoot, appDir), \"dist\")}`,\n );\n }\n}\n\n/** Re-exported so commands/docs.ts can wire the CLI-reference staleness check. */\nexport async function cliReferenceStaleness(\n repoRoot: string,\n): Promise<string | null> {\n const [\n { createProgram },\n { extractCliReference, renderCliReferenceMarkdown },\n ] = await Promise.all([\n import(\"../program.js\"),\n import(\"./cli-reference.js\"),\n ]);\n const outPath = path.join(repoRoot, \"docs/portal/generated/cli-reference.md\");\n const markdown = renderCliReferenceMarkdown(\n extractCliReference(createProgram()),\n );\n const existing = existsSync(outPath) ? readFileSync(outPath, \"utf-8\") : null;\n if (existing === markdown) return null;\n return `${\n existing === null ? \"CLI reference is missing\" : \"CLI reference is stale\"\n }: docs/portal/generated/cli-reference.md \u2014 the commander tree changed; regenerate and commit with \\`pnpm exec mesh docs cli-reference\\``;\n}\n", "/**\n * CLI provenance for `mesh --version` (MESH-2479).\n *\n * A stale shim / stale global install is invisible when --version prints only\n * the package version \u2014 two different checkouts (or a source tree vs a\n * published dist) can share \"0.5.1\". This resolves WHERE the running CLI\n * came from (TypeScript source vs published dist) plus the commit/build date,\n * so \"am I running the code I think I am?\" is answerable from one command.\n *\n * Source layout: bin/mesh.ts runs under tsx from the repo \u2014 commit/date come\n * from git at call time. Dist layout: the published package ships\n * dist/build-info.json written by scripts/build-for-publish.ts.\n */\n\nimport { execFileSync } from \"child_process\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport { fileURLToPath } from \"url\";\n\nexport interface CliRuntimeInfo {\n version: string;\n mode: \"source\" | \"dist\";\n commit?: string;\n builtAt?: string;\n}\n\n/** Pure: a module path under a `dist/` segment is the published build. */\nexport function detectRuntimeMode(modulePath: string): \"source\" | \"dist\" {\n return modulePath.split(/[\\\\/]/).includes(\"dist\") ? \"dist\" : \"source\";\n}\n\n/** Pure: one-line version string with provenance, e.g.\n * `0.5.1 (source @ abc1234 2026-07-30)` or\n * `0.5.1 (published build 2026-07-28, commit abc1234)`. */\nexport function formatVersionLine(info: CliRuntimeInfo): string {\n if (info.mode === \"source\") {\n const at = [info.commit, info.builtAt].filter(Boolean).join(\" \");\n return `${info.version} (source${at ? ` @ ${at}` : \"\"})`;\n }\n const built = info.builtAt ? ` ${info.builtAt.slice(0, 10)}` : \"\";\n const commit = info.commit ? `, commit ${info.commit}` : \"\";\n const detail = built || commit ? `${built}${commit}` : \" \u2014 build metadata unavailable\";\n return `${info.version} (published build${detail})`;\n}\n\n/** Walk up from `startDir` to the @mesh-tech/mesh-cli package root. */\nfunction findCliPackageRoot(startDir: string): string | null {\n let dir = startDir;\n for (let i = 0; i < 8; i++) {\n try {\n const pkg = JSON.parse(fs.readFileSync(path.join(dir, \"package.json\"), \"utf-8\"));\n if (pkg.name === \"@mesh-tech/mesh-cli\") return dir;\n } catch {\n // keep walking\n }\n const parent = path.dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return null;\n}\n\n/** Resolve the running CLI's version + provenance. Never throws.\n * `vcs: false` skips the git spawns in source mode (version + mode only) \u2014\n * commit/date cost two synchronous `git` runs, too slow to pay on every\n * invocation when nothing will print them. */\nexport function resolveCliRuntime(opts?: { vcs?: boolean }): CliRuntimeInfo {\n const vcs = opts?.vcs ?? true;\n const here = path.dirname(fileURLToPath(import.meta.url));\n const mode = detectRuntimeMode(here);\n const root = findCliPackageRoot(here);\n\n let version = \"0.0.0\";\n if (root) {\n try {\n version = JSON.parse(fs.readFileSync(path.join(root, \"package.json\"), \"utf-8\")).version ?? version;\n } catch {\n // fall through with the placeholder\n }\n }\n\n const info: CliRuntimeInfo = { version, mode };\n if (!root) return info;\n\n if (mode === \"dist\") {\n try {\n const meta = JSON.parse(\n fs.readFileSync(path.join(root, \"dist\", \"build-info.json\"), \"utf-8\"),\n ) as { commit?: string; builtAt?: string };\n info.commit = meta.commit;\n info.builtAt = meta.builtAt;\n } catch {\n // pre-MESH-2479 publishes have no build-info.json\n }\n return info;\n }\n\n if (!vcs) return info;\n\n try {\n const git = (args: string[]) =>\n execFileSync(\"git\", args, {\n cwd: root,\n encoding: \"utf-8\",\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n }).trim();\n info.commit = git([\"rev-parse\", \"--short\", \"HEAD\"]);\n info.builtAt = git([\"log\", \"-1\", \"--format=%cs\"]);\n } catch {\n // not a git checkout (e.g. exported source) \u2014 version + mode still print\n }\n return info;\n}\n", "/**\n * Serve a BUILT docs site (the Zudoku `dist/`) over loopback HTTP.\n *\n * This is deliberately not the deleted portal-serve.ts: that one served a\n * bespoke renderer's output with a custom search-index API. This one serves\n * a prerendered static tree and nothing else \u2014 try the exact path, then\n * `<path>.html` (Zudoku's prerendered routes), then `<path>/index.html`,\n * then the SPA fallback. No search endpoint: Pagefind runs client-side\n * against the shipped index files.\n */\n\nimport { createServer } from \"node:http\";\nimport { readFile } from \"node:fs/promises\";\nimport { extname, join, normalize, sep } from \"node:path\";\n\nconst CONTENT_TYPES: Record<string, string> = {\n \".html\": \"text/html; charset=utf-8\",\n \".js\": \"text/javascript; charset=utf-8\",\n \".mjs\": \"text/javascript; charset=utf-8\",\n \".css\": \"text/css; charset=utf-8\",\n \".json\": \"application/json; charset=utf-8\",\n \".map\": \"application/json; charset=utf-8\",\n \".svg\": \"image/svg+xml\",\n \".png\": \"image/png\",\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".gif\": \"image/gif\",\n \".ico\": \"image/x-icon\",\n \".woff\": \"font/woff\",\n \".woff2\": \"font/woff2\",\n \".txt\": \"text/plain; charset=utf-8\",\n \".md\": \"text/markdown; charset=utf-8\",\n \".webmanifest\": \"application/manifest+json\",\n};\n\nexport interface DocsServer {\n url: string;\n port: number;\n close: () => Promise<void>;\n}\n\n/**\n * Start the server. `port: 0` picks a free one (what tests use).\n *\n * Path safety: the URL path is normalized and rejected outright if it escapes\n * the root \u2014 this serves a local preview to the machine's own user, but a\n * `..` escape is a hole with no excuse to exist.\n */\nexport async function serveDocsSite(args: { root: string; port: number }): Promise<DocsServer> {\n const root = normalize(args.root);\n // Containment, not prefix-match: the prefix test alone admits SIBLINGS\n // whose names extend the root's basename (`<parent>/dist-secret/x` starts\n // with `<parent>/dist`). The vector that reaches it is an encoded slash \u2014\n // WHATWG URL parsing strips dot-segments, then decodeURIComponent turns\n // `..%2f` back into `../`. (Review on #3612.)\n const rootPrefix = root.endsWith(sep) ? root : root + sep;\n\n const server = createServer((req, res) => {\n void (async () => {\n const url = new URL(req.url ?? \"/\", \"http://localhost\");\n const pathname = decodeURIComponent(url.pathname);\n\n if (pathname === \"/healthz\") {\n res.writeHead(200, { \"content-type\": \"text/plain\" }).end(\"ok\");\n return;\n }\n\n const candidates = [\n pathname,\n `${pathname}.html`,\n `${pathname.replace(/\\/$/, \"\")}/index.html`,\n ];\n if (pathname !== \"/\") candidates.push(\"/index.html\"); // SPA fallback\n\n for (const candidate of candidates) {\n const filePath = normalize(join(root, candidate));\n // `continue`, not `break`: one malformed candidate must not change\n // the response for the rest (the SPA fallback lives inside the root).\n if (filePath !== root && !filePath.startsWith(rootPrefix)) continue; // outside the root \u2014 never serve\n try {\n const body = await readFile(filePath);\n const type = CONTENT_TYPES[extname(filePath)] ?? \"application/octet-stream\";\n // Prerendered HTML can be stale the moment a newer build exists;\n // hashed assets are immutable.\n const cache = candidate.includes(\"/assets/\") ? \"public, max-age=31536000, immutable\" : \"no-cache\";\n res.writeHead(200, { \"content-type\": type, \"cache-control\": cache });\n res.end(body);\n return;\n } catch {\n // try the next candidate\n }\n }\n\n res.writeHead(404, { \"content-type\": \"text/plain\" }).end(\"not found\");\n })().catch(() => {\n res.writeHead(500).end(\"internal error\");\n });\n });\n\n await new Promise<void>((resolve, reject) => {\n server.once(\"error\", reject);\n server.listen(args.port, \"127.0.0.1\", () => resolve());\n });\n\n const address = server.address();\n const port = typeof address === \"object\" && address ? address.port : args.port;\n\n return {\n url: `http://127.0.0.1:${port}`,\n port,\n close: () =>\n new Promise((resolve, reject) => {\n server.close((error) => (error ? reject(error) : resolve()));\n }),\n };\n}\n", "/**\n * The docs-as-registry-artifact client.\n *\n * The release job publishes the built portal as `@mesh-tech/docs` in the\n * fixed lockstep group, so the docs version IS the @mesh-tech/* baseline\n * version it describes. The audience is exactly \"people who can install the\n * packages\": the CodeArtifact registry is Zitadel-role-gated (see\n * `mesh registry login`), so no public hosting is required for the docs to\n * reach precisely the authorized set.\n *\n * This module reads the user's existing `~/.npmrc` CodeArtifact token (the\n * one `mesh registry login` writes), lists published docs versions, and\n * fetches + caches a version's tarball. It never talks to AWS directly.\n */\n\nimport { execFileSync } from \"node:child_process\";\nimport { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport path from \"node:path\";\n\nimport { homeNpmrcPath, parseNpmrcRegistryAuth } from \"../utils/auth-preflight.js\";\n\nexport const DOCS_PACKAGE = \"@mesh-tech/docs\";\n\nexport interface DocsRegistryAuth {\n endpoint: string;\n token: string;\n}\n\n/** The CodeArtifact token + endpoint from `mesh registry login`'s ~/.npmrc line. */\nexport function readDocsRegistryAuth(npmrcPath: string = homeNpmrcPath()): DocsRegistryAuth | null {\n if (!existsSync(npmrcPath)) return null;\n return parseNpmrcRegistryAuth(readFileSync(npmrcPath, \"utf-8\"));\n}\n\n/** The packument URL for a package (`@scope/name` \u2192 `@scope%2fname` path encoding). */\nfunction packumentUrl(endpoint: string, pkg: string): string {\n return `${endpoint.replace(/\\/+$/, \"\")}/${pkg.replace(/\\//g, \"%2f\")}`;\n}\n\nasync function registryFetch(\n auth: DocsRegistryAuth,\n url: string,\n fetchImpl: typeof fetch,\n): Promise<Response> {\n return fetchImpl(url, {\n headers: {\n authorization: `Bearer ${auth.token}`,\n accept: \"application/json\",\n },\n });\n}\n\n/** x.y.z numeric compare (release versions carry no prerelease suffixes). */\nexport function compareVersions(a: string, b: string): number {\n const parse = (v: string): number[] => {\n const parts = v.split(\".\").map((n) => Number.parseInt(n, 10) || 0);\n while (parts.length < 3) parts.push(0);\n return parts;\n };\n const pa = parse(a);\n const pb = parse(b);\n for (let i = 0; i < 3; i++) {\n if (pa[i] !== pb[i]) return pa[i]! - pb[i]!;\n }\n return 0;\n}\n\nexport interface DocsVersionList {\n versions: string[];\n latest: string | undefined;\n}\n\n/**\n * Every published docs version, oldest \u2192 newest, plus the registry's\n * `latest` dist-tag. Throws with the login remediation when the registry\n * rejects the token \u2014 an expired token is the common case (12h TTL).\n */\nexport async function listDocsVersions(\n auth: DocsRegistryAuth,\n fetchImpl: typeof fetch = fetch,\n): Promise<DocsVersionList> {\n const response = await registryFetch(auth, packumentUrl(auth.endpoint, DOCS_PACKAGE), fetchImpl).catch((error) => {\n throw new Error(\n `could not reach the package registry: ${error instanceof Error ? error.message : String(error)}`,\n );\n });\n\n if (response.status === 401 || response.status === 403) {\n throw new Error(\n `registry auth rejected the token (${response.status}). Refresh it: mesh registry login`,\n );\n }\n if (response.status === 404) {\n throw new Error(\n `${DOCS_PACKAGE} is not published yet \u2014 no release has shipped the docs artifact. In a mesh-platform checkout, use \\`mesh docs start\\` against the working tree instead.`,\n );\n }\n if (!response.ok) {\n throw new Error(`registry returned ${response.status} for ${DOCS_PACKAGE}`);\n }\n\n const packument = (await response.json()) as {\n versions?: Record<string, { dist?: { tarball?: string } }>;\n \"dist-tags\"?: Record<string, string>;\n };\n const versions = Object.keys(packument.versions ?? {}).sort(compareVersions);\n return { versions, latest: packument[\"dist-tags\"]?.latest };\n}\n\n/** Where fetched docs versions live: `~/.cache/mesh/docs/<version>/`. */\nexport function docsCacheRoot(): string {\n const base = process.env.XDG_CACHE_HOME ?? path.join(homeDir(), \".cache\");\n return path.join(base, \"mesh\", \"docs\");\n}\n\nfunction homeDir(): string {\n return process.env.HOME ?? tmpdir();\n}\n\n/**\n * Fetch and extract a docs version into the cache; returns the directory\n * containing the site's `dist/`. Cache hit = the directory already has a\n * `dist/index.html`. Partial downloads extract to a temp sibling and rename,\n * so an interrupted fetch never leaves a half-written \"good\" cache entry.\n */\nexport async function fetchDocsArtifact(\n auth: DocsRegistryAuth,\n version: string,\n cacheRoot: string = docsCacheRoot(),\n fetchImpl: typeof fetch = fetch,\n): Promise<string> {\n const targetDir = path.join(cacheRoot, version);\n if (existsSync(path.join(targetDir, \"dist\", \"index.html\"))) return targetDir;\n\n const listResponse = await registryFetch(auth, packumentUrl(auth.endpoint, DOCS_PACKAGE), fetchImpl);\n if (!listResponse.ok) {\n throw new Error(`registry returned ${listResponse.status} for ${DOCS_PACKAGE}`);\n }\n const packument = (await listResponse.json()) as {\n versions?: Record<string, { dist?: { tarball?: string } }>;\n };\n const tarball = packument.versions?.[version]?.dist?.tarball;\n if (!tarball) {\n throw new Error(\n `${DOCS_PACKAGE}@${version} is not in the registry. Run \\`mesh docs list\\` to see published versions.`,\n );\n }\n\n // Only ever send the registry credential to the registry's own origin: the\n // tarball URL comes out of a response BODY, and a bearer token must not\n // follow it to an arbitrary host. Real CodeArtifact tarball URLs are\n // same-origin; anything else is a malformed (or hostile) packument.\n if (new URL(tarball).origin !== new URL(auth.endpoint).origin) {\n throw new Error(\n `${DOCS_PACKAGE}@${version} points its tarball at ${new URL(tarball).origin}, not the registry (${new URL(auth.endpoint).origin}) \u2014 refusing to send the registry token off-origin`,\n );\n }\n\n const tgzResponse = await registryFetch(auth, tarball, fetchImpl);\n if (!tgzResponse.ok) {\n throw new Error(`downloading ${DOCS_PACKAGE}@${version} failed: ${tgzResponse.status}`);\n }\n\n mkdirSync(cacheRoot, { recursive: true });\n const tgzPath = path.join(cacheRoot, `.${version}.tgz`);\n writeFileSync(tgzPath, Buffer.from(await tgzResponse.arrayBuffer()));\n\n const staging = path.join(cacheRoot, `.staging-${version}`);\n rmSync(staging, { recursive: true, force: true });\n mkdirSync(staging, { recursive: true });\n try {\n // npm tarballs wrap everything in `package/` \u2014 strip one component.\n execFileSync(\"tar\", [\"-xzf\", tgzPath, \"-C\", staging, \"--strip-components\", \"1\"], {\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n } finally {\n rmSync(tgzPath, { force: true });\n }\n\n if (!existsSync(path.join(staging, \"dist\", \"index.html\"))) {\n rmSync(staging, { recursive: true, force: true });\n throw new Error(`${DOCS_PACKAGE}@${version} unpacked without a dist/index.html \u2014 the artifact is malformed`);\n }\n\n rmSync(targetDir, { recursive: true, force: true });\n renameSync(staging, targetDir);\n return targetDir;\n}\n", "/**\n * `mesh docs start` / `mesh docs list` / `mesh docs stop` \u2014 the docs as a\n * local, role-gated server (MESH-1803 follow-up).\n *\n * Two content modes, chosen automatically:\n *\n * - **Repo mode** \u2014 inside a checkout that has doc roots (mesh-platform):\n * assemble the working tree, build, and serve the static output. This is\n * the contributor path; the docs are exactly what is on disk.\n * - **Registry mode** \u2014 anywhere else (a tenant repo, a global install):\n * fetch the published `@mesh-tech/docs` artifact \u2014 versioned with the\n * @mesh-tech/* baseline \u2014 from the role-gated registry and serve it.\n * `-v <version>` pins; default is the registry's `latest` dist-tag.\n *\n * Two run modes: by default the server runs DETACHED in a tmux session with\n * the constant name `mesh-docs` \u2014 the handle that keeps a backgrounded server\n * from getting lost \u2014 and the command prints the URL once it answers.\n * `--foreground` (or a non-TTY, i.e. an agent/CI) serves in the foreground.\n * `--dev` (repo mode) runs the Zudoku dev server and is foreground-only: it\n * is an authoring tool \u2014 you are supposed to watch it.\n *\n * The registry mode is the distribution point: the people who can read the\n * docs are exactly the people who can install the packages, and no public\n * hosting is required.\n */\n\nimport { execFileSync } from \"node:child_process\";\nimport { appendFileSync, existsSync, writeFileSync } from \"node:fs\";\nimport path from \"node:path\";\n\nimport { logError, logInfo, logSuccess } from \"../utils/log.js\";\nimport { resolveCliRuntime } from \"../utils/build-info.js\";\nimport { discoverDocRoots } from \"./discover.js\";\nimport { runAssemble, reportAssembly, DOCS_APP_DIR } from \"./portal.js\";\nimport { serveDocsSite } from \"./serve.js\";\nimport {\n DOCS_PACKAGE,\n fetchDocsArtifact,\n listDocsVersions,\n readDocsRegistryAuth,\n} from \"./registry-docs.js\";\n\n/** The one tmux session name \u2014 the constant handle for the detached server. */\nexport const DOCS_TMUX_SESSION = \"mesh-docs\";\n\nfunction registryAuthOrThrow(): ReturnType<typeof readDocsRegistryAuth> {\n const auth = readDocsRegistryAuth();\n if (!auth) {\n throw new Error(\n \"no CodeArtifact token in ~/.npmrc \u2014 run `mesh registry login` first \" +\n \"(the docs artifact is role-gated the same way the packages are).\",\n );\n }\n return auth;\n}\n\n/** `mesh docs list` \u2014 published docs versions, newest first. */\nexport async function runDocsList(): Promise<void> {\n const auth = registryAuthOrThrow();\n const { versions, latest } = await listDocsVersions(auth!);\n\n if (versions.length === 0) {\n logInfo(`No ${DOCS_PACKAGE} versions published yet.`);\n return;\n }\n\n logInfo(`Published docs versions (docs version == @mesh-tech/* baseline):`);\n for (const version of [...versions].reverse()) {\n const marker = version === latest ? \" \u2190 latest\" : \"\";\n process.stdout.write(` ${version}${marker}\\n`);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Detached (tmux) machinery\n// ---------------------------------------------------------------------------\n\n/** The install command to show when tmux is missing, per platform. */\nexport function tmuxInstallHint(platform: string = process.platform): string {\n if (platform === \"darwin\") return \"brew install tmux\";\n if (platform === \"linux\") return \"sudo apt-get install tmux # or your distro's package manager\";\n return \"install tmux via your package manager\";\n}\n\n/** True when tmux is runnable. */\nexport function tmuxAvailable(): boolean {\n try {\n execFileSync(\"tmux\", [\"-V\"], { stdio: [\"pipe\", \"pipe\", \"pipe\"] });\n return true;\n } catch {\n return false;\n }\n}\n\n/** The detached/foreground decision, as one pure predicate. */\nexport function shouldDetach(args: { foreground: boolean; dev: boolean; isTTY: boolean }): boolean {\n return !args.foreground && !args.dev && args.isTTY;\n}\n\n/** True when the detached session currently exists. */\nexport function docsSessionExists(): boolean {\n try {\n execFileSync(\"tmux\", [\"has-session\", \"-t\", DOCS_TMUX_SESSION], { stdio: [\"pipe\", \"pipe\", \"pipe\"] });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * The argv the tmux session runs: a hidden foreground serve of the prepared\n * directory. Source checkouts re-enter through `pnpm exec mesh` at the repo\n * root (the shim-free canonical form); a published install re-enters through\n * the `mesh` bin on PATH.\n */\nexport function tmuxServeArgs(args: {\n mode: \"source\" | \"dist\";\n repoRoot: string;\n serveRoot: string;\n port: number;\n}): { command: string[]; cwd: string } {\n const serveArgs = [\"docs\", \"serve-static\", \"--root\", args.serveRoot, \"--port\", String(args.port)];\n if (args.mode === \"dist\") {\n return { command: [\"mesh\", ...serveArgs], cwd: args.repoRoot };\n }\n return { command: [\"pnpm\", \"exec\", \"mesh\", ...serveArgs], cwd: args.repoRoot };\n}\n\n/** (Re)start the detached docs session and wait for it to answer. */\nexport async function startDetached(args: {\n mode: \"source\" | \"dist\";\n repoRoot: string;\n serveRoot: string;\n port: number;\n label: string;\n}): Promise<void> {\n if (!tmuxAvailable()) {\n throw new Error(\n `tmux is not installed \u2014 the detached docs server runs in a tmux session named \"${DOCS_TMUX_SESSION}\".\\n` +\n `Install it with: ${tmuxInstallHint()}\\n` +\n `Or run in the foreground instead: mesh docs start --foreground`,\n );\n }\n\n // Restart semantics: the session name is the constant handle, so a second\n // `docs start` replaces the first rather than orphaning it. Say so when it\n // happens \u2014 a developer serving `-v 1.11.3` who starts the working tree\n // should not lose the first server silently.\n if (docsSessionExists()) {\n logInfo(`Replacing the docs server already running in tmux session \"${DOCS_TMUX_SESSION}\".`);\n try {\n execFileSync(\"tmux\", [\"kill-session\", \"-t\", DOCS_TMUX_SESSION], { stdio: [\"pipe\", \"pipe\", \"pipe\"] });\n } catch {\n // raced with its own shutdown \u2014 harmless\n }\n }\n\n const { command, cwd } = tmuxServeArgs(args);\n // Pass the argv ARRAY: tmux execs a multi-argument command directly, with no\n // shell. A single joined string would go through `sh -c`, and a `$()` or\n // backtick in a path (which mesh-ops worktree names can legitimately carry)\n // would be evaluated. Verified empirically on tmux 3.6a.\n execFileSync(\n \"tmux\",\n [\"new-session\", \"-d\", \"-s\", DOCS_TMUX_SESSION, \"-c\", cwd, \"--\", ...command],\n { stdio: [\"pipe\", \"pipe\", \"pipe\"] },\n );\n\n // Wait for the server to answer before printing the URL \u2014 \"one click\" only\n // works if the link is live when it appears.\n const deadline = Date.now() + 60_000;\n const url = `http://127.0.0.1:${args.port}`;\n let lastError = \"\";\n while (Date.now() < deadline) {\n try {\n const response = await fetch(`${url}/healthz`);\n if (response.ok) {\n printReady(url, args.label);\n return;\n }\n lastError = `HTTP ${response.status}`;\n } catch (error) {\n lastError = error instanceof Error ? error.message : String(error);\n }\n await new Promise((resolve) => setTimeout(resolve, 500));\n }\n\n throw new Error(\n `the docs server did not answer at ${url} within 60s (${lastError || \"no response\"}).\\n` +\n `Read its log with: tmux attach -t ${DOCS_TMUX_SESSION} (detach: Ctrl-B then D)`,\n );\n}\n\nfunction printReady(url: string, label: string): void {\n logSuccess(`Mesh docs (${label}) are live:`);\n // Bare on its own line \u2014 one click from any terminal.\n process.stdout.write(`\\n ${url}\\n\\n`);\n logInfo(`Running detached in the tmux session \"${DOCS_TMUX_SESSION}\".`);\n logInfo(` attach: tmux attach -t ${DOCS_TMUX_SESSION}`);\n logInfo(` stop: mesh docs stop`);\n}\n\n/** `mesh docs stop` \u2014 kill the detached session if it exists. */\nexport function runDocsStop(): void {\n try {\n execFileSync(\"tmux\", [\"kill-session\", \"-t\", DOCS_TMUX_SESSION], { stdio: [\"pipe\", \"pipe\", \"pipe\"] });\n logSuccess(`Stopped the docs server (tmux session \"${DOCS_TMUX_SESSION}\").`);\n } catch {\n logInfo(`No docs server is running (no tmux session named \"${DOCS_TMUX_SESSION}\").`);\n }\n}\n\n/** The hidden `mesh docs serve-static` the tmux session re-enters through. */\nexport async function runDocsServeStatic(args: { root: string; port: string }): Promise<void> {\n const requestedPort = Number.parseInt(args.port, 10);\n if (!Number.isInteger(requestedPort) || requestedPort < 0 || requestedPort > 65535) {\n throw new Error(`Invalid --port: ${args.port}`);\n }\n if (!args.root || !existsSync(path.join(args.root, \"index.html\"))) {\n throw new Error(\n `--root ${args.root || \"(empty)\"} does not hold a built site (no index.html). ` +\n `This command exists so the detached tmux session can re-enter; you probably want \\`mesh docs start\\`.`,\n );\n }\n const server = await serveDocsSite({ root: args.root, port: requestedPort });\n logSuccess(`Mesh docs serving at ${server.url} (from ${args.root})`);\n await new Promise<void>((resolve) => {\n const stop = (): void => void server.close().finally(() => resolve());\n process.once(\"SIGINT\", stop);\n process.once(\"SIGTERM\", stop);\n });\n}\n\n// ---------------------------------------------------------------------------\n// mesh docs start\n// ---------------------------------------------------------------------------\n\n/** `mesh docs start` \u2014 serve the docs locally, detached by default. */\nexport async function runDocsStart(args: {\n repoRoot: string;\n version?: string | undefined;\n port: string;\n dev: boolean;\n foreground: boolean;\n}): Promise<void> {\n const requestedPort = Number.parseInt(args.port, 10);\n if (!Number.isInteger(requestedPort) || requestedPort < 0 || requestedPort > 65535) {\n throw new Error(`Invalid --port: ${args.port}`);\n }\n\n // Compute the run mode BEFORE any prepare work (assemble+build is the\n // expensive part; refuse bad combinations up front).\n const detached = shouldDetach({\n foreground: args.foreground,\n dev: args.dev,\n isTTY: process.stdout.isTTY === true,\n });\n if (detached && requestedPort === 0) {\n // A detached server that picks its own port cannot report the choice back:\n // the parent would poll 127.0.0.1:0 for a minute and \"fail\" while a\n // perfectly good server runs on a port nobody knows.\n throw new Error(\n \"--port 0 (pick a free port) needs a foreground server, because the detached session \" +\n \"cannot report the port it chose back to this process. Use `mesh docs start --foreground --port 0`, \" +\n \"or pass an explicit port to run detached.\",\n );\n }\n\n const localRoots = discoverDocRoots(args.repoRoot);\n const repoHasDocs = localRoots.roots.length > 0;\n const registryMode = args.version !== undefined || !repoHasDocs;\n\n let serveRoot: string;\n let label: string;\n\n if (registryMode) {\n const auth = registryAuthOrThrow()!;\n const version =\n args.version === undefined || args.version === \"latest\"\n ? (await listDocsVersions(auth)).latest\n : args.version;\n if (!version) {\n throw new Error(`the registry has no ${DOCS_PACKAGE} versions tagged latest`);\n }\n logInfo(`Fetching ${DOCS_PACKAGE}@${version} from the registry\u2026`);\n const artifactDir = await fetchDocsArtifact(auth, version);\n serveRoot = path.join(artifactDir, \"dist\");\n label = `@mesh-tech/* ${version} (published artifact)`;\n } else {\n if (localRoots.errors.length > 0) {\n for (const error of localRoots.errors) logError(error);\n throw new Error(`docs discovery failed with ${localRoots.errors.length} problem(s)`);\n }\n\n const appDir = path.join(args.repoRoot, DOCS_APP_DIR);\n\n if (args.dev) {\n // HMR mode for docs authoring: assemble, then hand the tree to the\n // Zudoku dev server. Foreground-only by design \u2014 an authoring tool is\n // watched, not detached.\n const result = runAssemble({\n repoRoot: args.repoRoot,\n outDir: path.join(appDir, \"content\"),\n configOut: path.join(appDir, \"zudoku.config.ts\"),\n });\n reportAssembly(result);\n const { spawn } = await import(\"node:child_process\");\n const child = spawn(\"pnpm\", [\"exec\", \"zudoku\", \"dev\", \"--port\", String(requestedPort)], {\n cwd: appDir,\n stdio: \"inherit\",\n env: process.env,\n });\n await new Promise<void>((resolve) => {\n child.on(\"close\", () => resolve());\n process.once(\"SIGINT\", () => child.kill(\"SIGINT\"));\n process.once(\"SIGTERM\", () => child.kill(\"SIGTERM\"));\n });\n return;\n }\n\n // Detached mode keeps the waiting display to two lines; the build's noise\n // lands in a log file instead of the terminal.\n const buildLog = path.join(args.repoRoot, DOCS_APP_DIR, \"build.log\");\n logInfo(`Preparing the docs from this checkout (assemble + build \u2014 log: ${path.relative(args.repoRoot, buildLog)})\u2026`);\n\n const result = runAssemble({\n repoRoot: args.repoRoot,\n outDir: path.join(appDir, \"content\"),\n configOut: path.join(appDir, \"zudoku.config.ts\"),\n });\n reportAssembly(result);\n\n const { spawn } = await import(\"node:child_process\");\n writeFileSync(buildLog, \"\");\n const code = await new Promise<number>((resolve) => {\n const child = spawn(\"pnpm\", [\"exec\", \"zudoku\", \"build\"], {\n cwd: appDir,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n env: process.env,\n });\n child.stdout?.on(\"data\", (chunk) => appendFileSync(buildLog, chunk));\n child.stderr?.on(\"data\", (chunk) => appendFileSync(buildLog, chunk));\n child.on(\"error\", () => resolve(1));\n child.on(\"close\", (exitCode) => resolve(exitCode ?? 1));\n });\n if (code !== 0) throw new Error(`zudoku build exited with code ${code} \u2014 see ${buildLog}`);\n\n serveRoot = path.join(appDir, \"dist\");\n label = \"this checkout\";\n }\n\n if (detached) {\n const runtime = resolveCliRuntime({ vcs: false });\n await startDetached({\n mode: runtime.mode,\n repoRoot: args.repoRoot,\n serveRoot,\n port: requestedPort,\n label,\n });\n return;\n }\n\n const server = await serveDocsSite({ root: serveRoot, port: requestedPort });\n logSuccess(`Mesh docs (${label}) serving at ${server.url}`);\n logInfo(\"Press Ctrl-C to stop\");\n\n await new Promise<void>((resolve) => {\n const stop = (): void => {\n void server.close().finally(() => resolve());\n };\n process.once(\"SIGINT\", stop);\n process.once(\"SIGTERM\", stop);\n });\n}\n", "import { Command } from \"commander\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport { createRequire } from \"module\";\nimport { pathToFileURL } from \"url\";\nimport { logError, logInfo, logSuccess } from \"../utils/log.js\";\nimport { cliReferenceStaleness, runPortalCommand } from \"../docs/portal.js\";\nimport { findRepoRoot } from \"../utils/workflow-fingerprint.js\";\n\ninterface DocsBuildConfig {\n openapi?: OpenApiTask[];\n validate?: string[];\n}\n\ntype OpenApiTask = OpenApiFileTask | OpenApiSymxchangeTask;\n\ninterface OpenApiFileTask {\n kind: \"file\";\n input: string;\n output?: string;\n}\n\ninterface OpenApiSymxchangeTask {\n kind: \"symxchange\";\n output: string;\n enabled?: string[];\n title?: string;\n version?: string;\n description?: string;\n basePath?: string;\n servers?: Array<{ url: string; description?: string }>;\n}\n\nfunction findProjectRoot(start: string = process.cwd()): string {\n let dir = start;\n while (true) {\n if (fs.existsSync(path.join(dir, \"package.json\"))) return dir;\n const parent = path.dirname(dir);\n if (parent === dir) return start;\n dir = parent;\n }\n}\n\nfunction resolvePath(projectRoot: string, candidate: string): string {\n return path.isAbsolute(candidate) ? candidate : path.join(projectRoot, candidate);\n}\n\nfunction ensureParentDir(filePath: string): void {\n fs.mkdirSync(path.dirname(filePath), { recursive: true });\n}\n\nfunction readConfig(configPath: string): DocsBuildConfig {\n if (!fs.existsSync(configPath)) {\n throw new Error(`Docs config not found: ${configPath}`);\n }\n\n const raw = fs.readFileSync(configPath, \"utf-8\");\n const parsed = JSON.parse(raw) as DocsBuildConfig;\n\n if (parsed.openapi && !Array.isArray(parsed.openapi)) {\n throw new Error(`Invalid docs config: 'openapi' must be an array`);\n }\n\n return parsed;\n}\n\nfunction validateOpenApiSpec(specPath: string): void {\n const content = fs.readFileSync(specPath, \"utf-8\");\n const parsed = JSON.parse(content) as Record<string, unknown>;\n\n if (typeof parsed.openapi !== \"string\") {\n throw new Error(`Invalid OpenAPI spec (${specPath}): missing 'openapi'`);\n }\n\n if (!parsed.info || typeof parsed.info !== \"object\") {\n throw new Error(`Invalid OpenAPI spec (${specPath}): missing 'info' object`);\n }\n\n if (!parsed.paths || typeof parsed.paths !== \"object\") {\n throw new Error(`Invalid OpenAPI spec (${specPath}): missing 'paths' object`);\n }\n}\n\nasync function loadSymxchangeGenerator(projectRoot: string): Promise<{\n generateSymxchangeOpenApi: (options?: Record<string, unknown>) => Promise<Record<string, unknown>>;\n}> {\n const requireFromProject = createRequire(path.join(projectRoot, \"package.json\"));\n const entryPath = requireFromProject.resolve(\"@mesh-tech/jh-symitar-api\");\n const mod = await import(pathToFileURL(entryPath).href) as Record<string, unknown>;\n\n const fn = mod.generateSymxchangeOpenApi;\n if (typeof fn !== \"function\") {\n throw new Error(\"@mesh-tech/jh-symitar-api does not export generateSymxchangeOpenApi()\");\n }\n\n return {\n generateSymxchangeOpenApi: fn as (options?: Record<string, unknown>) => Promise<Record<string, unknown>>,\n };\n}\n\nasync function buildDocs(configPathArg?: string): Promise<void> {\n const cwd = process.cwd();\n const configPath = path.isAbsolute(configPathArg ?? \"\")\n ? (configPathArg as string)\n : path.resolve(cwd, configPathArg ?? \"docs/docs.config.json\");\n\n const projectRoot = findProjectRoot(path.dirname(configPath));\n const config = readConfig(configPath);\n\n logInfo(`Using docs config: ${configPath}`);\n\n const generatedSpecs = new Set<string>();\n\n for (const task of config.openapi ?? []) {\n if (task.kind === \"file\") {\n const inputPath = resolvePath(projectRoot, task.input);\n const outputPath = resolvePath(projectRoot, task.output ?? task.input);\n\n if (!fs.existsSync(inputPath)) {\n throw new Error(`OpenAPI source file not found: ${inputPath}`);\n }\n\n if (inputPath !== outputPath) {\n ensureParentDir(outputPath);\n fs.copyFileSync(inputPath, outputPath);\n logSuccess(`Copied OpenAPI spec \u2192 ${path.relative(projectRoot, outputPath)}`);\n } else {\n logInfo(`Using OpenAPI spec: ${path.relative(projectRoot, inputPath)}`);\n }\n\n validateOpenApiSpec(outputPath);\n generatedSpecs.add(outputPath);\n continue;\n }\n\n if (task.kind === \"symxchange\") {\n const outputPath = resolvePath(projectRoot, task.output);\n const { generateSymxchangeOpenApi } = await loadSymxchangeGenerator(projectRoot);\n\n const spec = await generateSymxchangeOpenApi({\n enabled: task.enabled,\n title: task.title,\n version: task.version,\n description: task.description,\n basePath: task.basePath,\n servers: task.servers,\n });\n\n ensureParentDir(outputPath);\n fs.writeFileSync(outputPath, JSON.stringify(spec, null, 2));\n validateOpenApiSpec(outputPath);\n generatedSpecs.add(outputPath);\n logSuccess(`Generated SymXchange OpenAPI \u2192 ${path.relative(projectRoot, outputPath)}`);\n continue;\n }\n\n const exhaustive: never = task;\n throw new Error(`Unsupported OpenAPI task kind: ${(exhaustive as any).kind}`);\n }\n\n for (const relPath of config.validate ?? []) {\n const abs = resolvePath(projectRoot, relPath);\n if (!fs.existsSync(abs)) {\n throw new Error(`OpenAPI spec to validate not found: ${abs}`);\n }\n validateOpenApiSpec(abs);\n generatedSpecs.add(abs);\n logSuccess(`Validated OpenAPI spec: ${path.relative(projectRoot, abs)}`);\n }\n\n if (generatedSpecs.size === 0) {\n logInfo(\"No docs tasks configured (nothing to do)\");\n return;\n }\n\n logSuccess(`Docs build complete (${generatedSpecs.size} OpenAPI file${generatedSpecs.size === 1 ? \"\" : \"s\"})`);\n}\n\n/** Default location of the committed, reviewable CLI reference. */\nconst CLI_REFERENCE_PATH = \"docs/portal/generated/cli-reference.md\";\n\n/**\n * Render the CLI reference markdown.\n *\n * `../program.js` is imported dynamically because it imports this module \u2014\n * a static import would close the cycle. It also keeps the whole command tree\n * out of the module graph for every other `mesh` invocation.\n */\nasync function renderCliReference(): Promise<string> {\n const [{ createProgram }, { extractCliReference, renderCliReferenceMarkdown }] = await Promise.all([\n import(\"../program.js\"),\n import(\"../docs/cli-reference.js\"),\n ]);\n return renderCliReferenceMarkdown(extractCliReference(createProgram()));\n}\n\n/** Wrap an action so any thrown error becomes a one-line failure + exit 1. */\nfunction guarded(action: () => Promise<void>): () => Promise<void> {\n return async () => {\n try {\n await action();\n } catch (error) {\n logError(error instanceof Error ? error.message : String(error));\n process.exitCode = 1;\n }\n };\n}\n\nasync function runCliReference(opts: { out: string; check: boolean }): Promise<void> {\n const repoRoot = findRepoRoot(process.cwd());\n const outPath = resolvePath(repoRoot, opts.out);\n const markdown = await renderCliReference();\n\n if (opts.check) {\n const existing = fs.existsSync(outPath) ? fs.readFileSync(outPath, \"utf-8\") : null;\n if (existing === markdown) {\n logSuccess(`CLI reference is up to date (${path.relative(repoRoot, outPath)})`);\n return;\n }\n throw new Error(\n `${\n existing === null ? \"CLI reference is missing\" : \"CLI reference is stale\"\n }: ${path.relative(repoRoot, outPath)}\\n` +\n ` The commander tree changed. Regenerate and commit:\\n` +\n ` pnpm exec mesh docs cli-reference`,\n );\n }\n\n ensureParentDir(outPath);\n fs.writeFileSync(outPath, markdown);\n logSuccess(`CLI reference \u2192 ${path.relative(repoRoot, outPath)}`);\n}\n\nasync function runPortal(opts: {\n out?: string;\n assembleOnly: boolean;\n serve: boolean;\n port: string;\n check: boolean;\n printManifest: boolean;\n diffBase?: string;\n manifestOut?: string;\n}): Promise<void> {\n const repoRoot = findRepoRoot(process.cwd());\n await runPortalCommand(\n {\n out: opts.out,\n assembleOnly: opts.assembleOnly,\n serve: opts.serve,\n port: opts.port,\n check: opts.check,\n printManifest: opts.printManifest,\n diffBase: opts.diffBase,\n manifestOut: opts.manifestOut,\n },\n { repoRoot, checkCliReference: () => cliReferenceStaleness(repoRoot) },\n );\n}\n\nexport function registerDocsCommand(program: Command): void {\n const docs = program\n .command(\"docs\")\n .description(\"Mesh documentation \u2014 the developer portal, the CLI reference, and app API docs\");\n\n docs\n .command(\"build\")\n .description(\"Generate app docs artifacts (OpenAPI specs, composed specs)\")\n .option(\"-c, --config <path>\", \"Path to docs config file\", \"docs/docs.config.json\")\n .action(async (opts: { config: string }) => {\n try {\n await buildDocs(opts.config);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n logError(message);\n process.exitCode = 1;\n }\n });\n\n docs\n .command(\"cli-reference\")\n .description(\"Regenerate the `mesh` CLI reference markdown from the command tree\")\n .option(\"-o, --out <path>\", \"output markdown path\", CLI_REFERENCE_PATH)\n .option(\"--check\", \"verify only (CI): exit 1 when the committed reference is stale\", false)\n .action((opts: { out: string; check: boolean }) => guarded(() => runCliReference(opts))());\n\n docs\n .command(\"portal\")\n .description(\n \"Assemble the Mesh developer portal from docs.json-discovered repo docs, then build/serve it with Zudoku\",\n )\n .option(\"-o, --out <dir>\", \"assemble into this content directory and stop (implies --assemble-only)\")\n .option(\"--assemble-only\", \"write the content tree + generated zudoku.config.ts, then stop\", false)\n .option(\"--serve\", \"run `zudoku dev` against the assembled content (local preview)\", false)\n .option(\"-p, --port <port>\", \"port for --serve\", \"3000\")\n .option(\"--check\", \"CI gate: schema, reserved names, links, and CLI-reference staleness \u2014 no build\", false)\n .option(\"--print-manifest\", \"print the publish manifest (every published source path) to stdout\", false)\n .option(\"--diff-base <ref>\", \"also diff the publish set against a git ref (PR job summary)\")\n .option(\"--manifest-out <path>\", \"with --check: also write publish-manifest.json to this path\")\n .action(\n (opts: {\n out?: string;\n assembleOnly: boolean;\n serve: boolean;\n port: string;\n check: boolean;\n printManifest: boolean;\n diffBase?: string;\n manifestOut?: string;\n }) => guarded(() => runPortal(opts))(),\n );\n\n docs\n .command(\"start\")\n .description(\n \"Serve the Mesh docs locally \u2014 detached in a tmux session by default; the working tree in a mesh-platform checkout, or the published @mesh-tech/docs artifact (role-gated registry) anywhere else\",\n )\n .option(\"-v, --version <version>\", \"docs version to serve (== the @mesh-tech/* baseline it describes); default: latest\", undefined)\n .option(\"-p, --port <port>\", \"port to serve on (0 picks a free one)\", \"4400\")\n .option(\"--dev\", \"in a checkout: run the Zudoku dev server (HMR) in the foreground, for authoring\", false)\n .option(\"--foreground\", \"serve in the foreground (the agent/CI path; automatic when not a TTY)\", false)\n .action((opts: { version?: string; port: string; dev: boolean; foreground: boolean }) =>\n guarded(async () => {\n const { runDocsStart } = await import(\"../docs/start.js\");\n await runDocsStart({\n repoRoot: findRepoRoot(process.cwd()),\n version: opts.version,\n port: opts.port,\n dev: opts.dev,\n foreground: opts.foreground,\n });\n })(),\n );\n\n docs\n .command(\"stop\")\n .description(`Stop the detached docs server (the tmux session \"${\"mesh-docs\"}\")`)\n .action(() =>\n guarded(async () => {\n const { runDocsStop } = await import(\"../docs/start.js\");\n runDocsStop();\n })(),\n );\n\n // Hidden: the tmux session re-enters through this. Not in the reference \u2014\n // cli-reference excludes hidden commands by design.\n docs\n .command(\"serve-static\", { hidden: true })\n .option(\"--root <dir>\", \"built site root\", \"\")\n .option(\"--port <port>\", \"port\", \"4400\")\n .action((opts: { root: string; port: string }) =>\n guarded(async () => {\n const { runDocsServeStatic } = await import(\"../docs/start.js\");\n await runDocsServeStatic(opts);\n })(),\n );\n\n docs\n .command(\"list\")\n .description(\"List the published docs versions (each is an @mesh-tech/* baseline)\")\n .action(() =>\n guarded(async () => {\n const { runDocsList } = await import(\"../docs/start.js\");\n await runDocsList();\n })(),\n );\n}\n", "/**\n * mesh hub dev \u2014 one-command local Hub over a running dev-local stack (MESH-2275).\n *\n * Launches the CURRENT-CODE Hub (apps/hub api + ui from a mesh-platform\n * checkout) pointed at an existing `mesh dev` session's stack, auto-assembling\n * the env that used to be hand-set (the FUB-demo runbook \u00A76 recipe):\n *\n * HUB_TENANT / HUB_SCOPE_ENV / HUB_SCOPE_TENANTS from the session's platform context\n * TEMPORAL_ADDRESS from the session's tunnel (VPN or SSM)\n * AWS_* from the session's scratch credential_process profile\n * DEV_USER_* / DEV_USER_TOKEN_URL from the session's injected dev identity +\n * per-session token-server (MESH-2039)\n *\n * The `mesh dev` session already resolved all of these \u2014 its tmux session\n * environment and state file (`$TMPDIR/mesh-dev-sessions/<name>.json`) are the\n * source of truth; this command only reads them and never mutates the app\n * session.\n *\n * Scoped-tenant enumeration is validated up front: HUB_SCOPE_ENV without a\n * non-empty HUB_SCOPE_TENANTS makes the Hub API silently return zero\n * registrations (apps/hub/api/src/lib/ssm/reader.ts), so that combination is\n * a loud error here, never an empty Hub.\n */\n\nimport { execFileSync } from \"node:child_process\";\nimport * as fs from \"node:fs\";\nimport * as net from \"node:net\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\n\nimport chalk from \"chalk\";\nimport { Command } from \"commander\";\n\nimport { buildLaunchCommand, waitForPort, writeEnvFile } from \"../dev-launch.js\";\nimport { tunnelClientAddress, type SessionState } from \"../dev.js\";\nimport { MeshCliError } from \"../../utils/errors.js\";\nimport { DEFAULT_HUB_PORT } from \"../local/stack.js\";\nimport { logInfo, logSuccess, logWarn } from \"../../utils/log.js\";\nimport { findAppRoot } from \"../../utils/pulumi.js\";\n\n/** tmux session the Hub runs in \u2014 fixed, one local Hub at a time. */\nexport const HUB_SESSION = \"mesh-hub-dev\";\n\n// Same default as the containerized Hub (local/stack.ts DEFAULT_HUB_PORT),\n// but a SEPARATE override variable: MESH_HUB_PORT moves the containerized\n// Hub's published port, MESH_HUB_DEV_PORT moves this dev-server Hub. The two\n// are built to run side by side \u2014 one shared variable would make \"move the\n// containerized Hub off 9000\" also move the dev server onto the same port.\nexport const DEFAULT_HUB_UI_PORT = Number(DEFAULT_HUB_PORT);\nexport const DEFAULT_HUB_API_PORT = 3002;\n\n// \u2500\u2500 dev-session discovery \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface DiscoveredSession {\n name: string;\n state: SessionState;\n}\n\nexport function devSessionsDir(): string {\n return path.join(os.tmpdir(), \"mesh-dev-sessions\");\n}\n\n/** All persisted `mesh dev` session states (unparseable files skipped). */\nexport function listDevSessions(dir = devSessionsDir()): DiscoveredSession[] {\n if (!fs.existsSync(dir)) return [];\n const sessions: DiscoveredSession[] = [];\n for (const entry of fs.readdirSync(dir)) {\n if (!entry.endsWith(\".json\")) continue;\n try {\n const state = JSON.parse(\n fs.readFileSync(path.join(dir, entry), \"utf-8\"),\n ) as SessionState;\n if (state && typeof state === \"object\" && state.devOutput) {\n sessions.push({ name: entry.slice(0, -\".json\".length), state });\n }\n } catch {\n // stale/corrupt state file \u2014 not a candidate\n }\n }\n return sessions;\n}\n\n/**\n * Pick the dev session to point the Hub at.\n *\n * 1. --session <name> wins (error if its state file is missing).\n * 2. The session whose appRoot equals the cwd's app root (both sides come\n * from findAppRoot, so exact equality is the right comparison).\n * 3. A sole running session.\n *\n * Ambiguity (multiple sessions, none matching cwd) is an error listing the\n * candidates \u2014 never a silent guess.\n */\nexport function pickDevSession(\n sessions: DiscoveredSession[],\n opts: { session?: string; cwdAppRoot?: string | null },\n): DiscoveredSession {\n if (opts.session) {\n const match = sessions.find((s) => s.name === opts.session);\n if (!match) {\n throw new MeshCliError(\n `No dev session state found for '${opts.session}'. Known sessions: ${\n sessions.map((s) => s.name).join(\", \") || \"(none)\"\n }`,\n { remediation: { command: \"mesh dev # from the app repo, to start the stack session\" } },\n );\n }\n return match;\n }\n if (sessions.length === 0) {\n throw new MeshCliError(\n \"No running `mesh dev` session found \u2014 the Hub needs a dev-local stack to observe.\",\n { remediation: { command: \"mesh dev # from your app repo, then re-run mesh hub dev\" } },\n );\n }\n if (opts.cwdAppRoot) {\n const root = path.resolve(opts.cwdAppRoot);\n const match = sessions.find((s) => path.resolve(s.state.appRoot) === root);\n if (match) return match;\n }\n if (sessions.length === 1) return sessions[0]!;\n throw new MeshCliError(\n `Multiple dev sessions found and none matches this directory: ${sessions\n .map((s) => `${s.name} (${s.state.appRoot})`)\n .join(\", \")}`,\n { remediation: { command: \"mesh hub dev --session <name>\" } },\n );\n}\n\n// \u2500\u2500 tmux session env \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Parse `tmux show-environment` output (`KEY=value` lines; `-KEY` = unset). */\nexport function parseTmuxEnv(output: string): Record<string, string> {\n const env: Record<string, string> = {};\n for (const line of output.split(\"\\n\")) {\n if (!line || line.startsWith(\"-\")) continue;\n const eq = line.indexOf(\"=\");\n if (eq <= 0) continue;\n env[line.slice(0, eq)] = line.slice(eq + 1);\n }\n return env;\n}\n\nfunction readTmuxSessionEnv(sessionName: string): Record<string, string> {\n try {\n const out = execFileSync(\"tmux\", [\"show-environment\", \"-t\", sessionName], {\n encoding: \"utf-8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n });\n return parseTmuxEnv(out);\n } catch {\n return {};\n }\n}\n\nfunction tmuxSessionExists(sessionName: string): boolean {\n try {\n execFileSync(\"tmux\", [\"has-session\", \"-t\", sessionName], { stdio: \"ignore\" });\n return true;\n } catch {\n return false;\n }\n}\n\n// \u2500\u2500 env assembly \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Vars carried over verbatim from the dev session's tmux environment. */\nconst FORWARD_PREFIXES = [\"AWS_\", \"DEV_USER_\"] as const;\n\nexport function forwardedSessionVars(sessionEnv: Record<string, string>): Record<string, string> {\n const out: Record<string, string> = {};\n for (const [key, value] of Object.entries(sessionEnv)) {\n if (FORWARD_PREFIXES.some((p) => key.startsWith(p))) out[key] = value;\n }\n return out;\n}\n\nexport interface HubDevEnvOptions {\n /** Comma-separated tenant override (--tenants). */\n tenants?: string;\n uiPort: number;\n apiPort: number;\n}\n\nexport interface AssembledHubEnv {\n apiEnv: Record<string, string>;\n uiEnv: Record<string, string>;\n /** Human-readable scope summary for the launch banner. */\n scope: { hubTenant: string; scopeEnv: string; scopeTenants: string[] };\n temporalAddress: string;\n warnings: string[];\n /** Informational \u2014 things the command is handling itself, not user problems. */\n notes: string[];\n}\n\n/**\n * Assemble the Hub api/ui env from a discovered dev session. Throws loudly on\n * the combinations that today produce a silently-empty Hub.\n */\nexport function assembleHubEnv(\n session: DiscoveredSession,\n sessionEnv: Record<string, string>,\n opts: HubDevEnvOptions,\n): AssembledHubEnv {\n const warnings: string[] = [];\n const notes: string[] = [];\n const platform = session.state.devOutput.platform;\n if (!platform) {\n throw new MeshCliError(\n `Dev session '${session.name}' has no platform context in its state file \u2014 cannot derive the Hub scope.`,\n { remediation: { command: \"mesh dev --kill && mesh dev # relaunch to refresh session state\" } },\n );\n }\n if (platform.tenant === \"local\") {\n throw new MeshCliError(\n \"This session runs on the full-local platform (`mesh start`) \u2014 use its containerized Hub instead of `mesh hub dev`.\",\n { remediation: { command: \"mesh start --with-hub # MESH_HUB_PORT=<port> publishes it off 9000\" } },\n );\n }\n\n const hubTenant = platform.name ?? \"mesh\";\n const scopeEnv = platform.env;\n const scopeTenants = (opts.tenants ?? platform.tenant)\n .split(\",\")\n .map((t) => t.trim())\n .filter(Boolean);\n if (scopeTenants.length === 0) {\n // The Hub API's scoped SSM reader returns [] with no error when\n // HUB_SCOPE_ENV is set and HUB_SCOPE_TENANTS is empty \u2014 every page renders\n // blank with nothing in the logs. Refuse to launch into that state.\n throw new MeshCliError(\n \"Tenant scope resolved EMPTY (HUB_SCOPE_ENV set, no HUB_SCOPE_TENANTS) \u2014 the Hub would launch but show zero tenants everywhere.\",\n { remediation: { command: \"mesh hub dev --tenants <tenant>[,<tenant>\u2026]\" } },\n );\n }\n\n const forwarded = forwardedSessionVars(sessionEnv);\n if (!Object.keys(forwarded).some((k) => k.startsWith(\"AWS_\"))) {\n warnings.push(\n \"No AWS_* vars found in the dev session env \u2014 the Hub API will fall back to ambient credentials (SSM reads may 403).\",\n );\n }\n if (!forwarded.DEV_USER_ID_TOKEN && !forwarded.DEV_USER_ACCESS_TOKEN) {\n warnings.push(\n \"No DEV_USER_* identity in the dev session env \u2014 the Hub will show an unauthenticated state. Run `mesh login mesh.\" +\n `${scopeEnv}\\` and relaunch \\`mesh dev\\`.`,\n );\n }\n if (!forwarded.DEV_USER_TOKEN_URL) {\n // Not a warning: the launch path starts a dedicated token-server for this\n // case, so telling the user to restart `mesh dev` would contradict the\n // `\u2714 Dev-user token-server: \u2026` line printed moments later.\n notes.push(\n \"Dev session predates the per-session token-server (MESH-2039) \u2014 starting a dedicated one so tokens stay fresh past ~1h.\",\n );\n }\n\n const temporalAddress =\n sessionEnv.TEMPORAL_ADDRESS ??\n (session.state.devOutput.tunnels[\"temporal\"]\n ? tunnelClientAddress(session.state.devOutput.tunnels[\"temporal\"]!)\n : undefined);\n if (!temporalAddress) {\n throw new MeshCliError(\n `Dev session '${session.name}' exposes no Temporal tunnel \u2014 the Hub can't reach the stack's Temporal.`,\n { remediation: { command: \"mesh dev # relaunch; the session records tunnels.temporal in its state\" } },\n );\n }\n\n const apiEnv: Record<string, string> = {\n ...forwarded,\n PORT: String(opts.apiPort),\n TEMPORAL_ADDRESS: temporalAddress,\n HUB_TENANT: hubTenant,\n HUB_SCOPE_ENV: scopeEnv,\n HUB_SCOPE_TENANTS: scopeTenants.join(\",\"),\n };\n\n const uiEnv: Record<string, string> = {\n ...forwarded,\n PORT: String(opts.uiPort),\n API_URL: `http://localhost:${opts.apiPort}`,\n HUB_TENANT: hubTenant,\n // UI namespace parsing + session defaults land on the scoped tenant.\n DEFAULT_ORG: scopeTenants[0]!,\n DEFAULT_ENV: scopeEnv,\n };\n\n return { apiEnv, uiEnv, scope: { hubTenant, scopeEnv, scopeTenants }, temporalAddress, warnings, notes };\n}\n\n// \u2500\u2500 platform checkout resolution \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Does `dir` look like a mesh-platform checkout root (has the Hub app)? */\nfunction isPlatformRoot(dir: string): boolean {\n return (\n fs.existsSync(path.join(dir, \"apps\", \"hub\", \"api\", \"package.json\")) &&\n fs.existsSync(path.join(dir, \"apps\", \"hub\", \"ui\", \"package.json\"))\n );\n}\n\n/**\n * Locate the mesh-platform checkout the Hub runs from:\n * --platform-dir \u2192 $MESH_PLATFORM_DIR \u2192 walk up from cwd (monorepo case).\n *\n * An invalid `--platform-dir` is fatal (the user named it explicitly), but a\n * stale `MESH_PLATFORM_DIR` left over in the shell only warns and falls through\n * to the cwd walk-up \u2014 otherwise it would hard-fail runs made from inside a\n * perfectly good checkout.\n */\nexport function resolvePlatformDir(\n explicit: string | undefined,\n cwd: string,\n env: Record<string, string | undefined> = process.env,\n): string {\n if (explicit) {\n const resolved = path.resolve(explicit);\n if (isPlatformRoot(resolved)) return resolved;\n throw new MeshCliError(\n `'${resolved}' is not a mesh-platform checkout (apps/hub/{api,ui} not found).`,\n { remediation: { command: \"mesh hub dev --platform-dir <path-to-mesh-platform>\" } },\n );\n }\n if (env.MESH_PLATFORM_DIR) {\n const resolved = path.resolve(env.MESH_PLATFORM_DIR);\n if (isPlatformRoot(resolved)) return resolved;\n logWarn(\n `MESH_PLATFORM_DIR='${resolved}' is not a mesh-platform checkout (apps/hub/{api,ui} not found) \u2014 ignoring it.`,\n );\n }\n let dir = path.resolve(cwd);\n for (;;) {\n if (isPlatformRoot(dir)) return dir;\n const parent = path.dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n throw new MeshCliError(\n \"Can't find a mesh-platform checkout (the Hub's source). Run from inside one, or point at one explicitly.\",\n {\n remediation: {\n command: \"mesh hub dev --platform-dir <path-to-mesh-platform> # or export MESH_PLATFORM_DIR\",\n },\n },\n );\n}\n\n// \u2500\u2500 token server \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nasync function findFreePort(): Promise<number> {\n return new Promise((resolve, reject) => {\n const server = net.createServer();\n server.listen(0, \"127.0.0.1\", () => {\n const address = server.address();\n server.close(() =>\n typeof address === \"object\" && address ? resolve(address.port) : reject(new Error(\"no port\")),\n );\n });\n server.on(\"error\", reject);\n });\n}\n\nfunction isPortListening(port: number): Promise<boolean> {\n return new Promise((resolve) => {\n const socket = net.connect({ host: \"127.0.0.1\", port, timeout: 400 });\n const done = (ok: boolean) => {\n socket.removeAllListeners();\n socket.destroy();\n resolve(ok);\n };\n socket.once(\"connect\", () => done(true));\n socket.once(\"timeout\", () => done(false));\n socket.once(\"error\", () => done(false));\n });\n}\n\n// \u2500\u2500 env file dir \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction hubEnvDir(): string {\n return path.join(os.tmpdir(), \"mesh-dev-sessions\", HUB_SESSION);\n}\n\n// \u2500\u2500 port parsing \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Parse a port option, naming its source in the error. Without this a typo'd\n * `--port` (or a stale non-numeric `MESH_HUB_DEV_PORT` left in the shell) becomes\n * `NaN`, lands in the env file as `PORT=NaN`, and reaches `net.connect` \u2014 which\n * throws a raw `ERR_SOCKET_BAD_PORT` instead of an actionable CLI error.\n */\nexport function parsePort(raw: string | undefined, fallback: number, source: string): number {\n if (raw === undefined) return fallback;\n const n = Number(raw);\n if (!Number.isInteger(n) || n < 1 || n > 65535) {\n throw new MeshCliError(`Invalid port '${raw}' from ${source} \u2014 expected an integer 1\u201365535.`, {\n remediation: { command: `mesh hub dev ${source.startsWith(\"--\") ? source : \"--port\"} <1-65535>` },\n });\n }\n return n;\n}\n\n// \u2500\u2500 redaction for --print-env \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst SENSITIVE_RE = /TOKEN|SECRET|KEY|PASSWORD/i;\n\nexport function redactEnv(env: Record<string, string>): Record<string, string> {\n const out: Record<string, string> = {};\n for (const [key, value] of Object.entries(env)) {\n // URLs named *_TOKEN_URL etc. are locators, not credentials.\n const sensitive = SENSITIVE_RE.test(key) && !key.endsWith(\"_URL\") && !key.endsWith(\"_FILE\");\n out[key] = sensitive ? `<redacted ${value.length} chars>` : value;\n }\n return out;\n}\n\n// \u2500\u2500 command \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\ninterface HubDevOptions {\n session?: string;\n tenants?: string;\n port?: string;\n apiPort?: string;\n platformDir?: string;\n printEnv?: boolean;\n kill?: boolean;\n}\n\nasync function hubDevAction(opts: HubDevOptions): Promise<void> {\n if (opts.kill) {\n if (tmuxSessionExists(HUB_SESSION)) {\n execFileSync(\"tmux\", [\"kill-session\", \"-t\", HUB_SESSION], { stdio: \"ignore\" });\n fs.rmSync(hubEnvDir(), { recursive: true, force: true });\n logSuccess(`Killed Hub session '${HUB_SESSION}'.`);\n } else {\n logInfo(`No '${HUB_SESSION}' tmux session running.`);\n }\n return;\n }\n\n const uiPort = opts.port\n ? parsePort(opts.port, DEFAULT_HUB_UI_PORT, \"--port\")\n : parsePort(process.env.MESH_HUB_DEV_PORT, DEFAULT_HUB_UI_PORT, \"MESH_HUB_DEV_PORT\");\n const apiPort = parsePort(opts.apiPort, DEFAULT_HUB_API_PORT, \"--api-port\");\n\n // 1. The Hub's source.\n const platformDir = resolvePlatformDir(opts.platformDir, process.cwd());\n\n // 2. The dev-local stack session to observe.\n const cwdAppRoot = findAppRoot(process.cwd());\n const session = pickDevSession(listDevSessions(), { session: opts.session, cwdAppRoot });\n if (!tmuxSessionExists(session.name)) {\n throw new MeshCliError(\n `Dev session '${session.name}' has a state file but no live tmux session \u2014 its tunnels and token-server are gone.`,\n { remediation: { command: `mesh dev # from ${session.state.appRoot}` } },\n );\n }\n const sessionEnv = readTmuxSessionEnv(session.name);\n\n // 3. Assemble the env (loud failures instead of a silently-empty Hub).\n const assembled = assembleHubEnv(session, sessionEnv, { tenants: opts.tenants, uiPort, apiPort });\n\n if (opts.printEnv) {\n console.log(chalk.bold(\"\\nhub-api env:\"));\n for (const [k, v] of Object.entries(redactEnv(assembled.apiEnv))) console.log(` ${k}=${v}`);\n console.log(chalk.bold(\"\\nhub-ui env:\"));\n for (const [k, v] of Object.entries(redactEnv(assembled.uiEnv))) console.log(` ${k}=${v}`);\n return;\n }\n\n if (tmuxSessionExists(HUB_SESSION)) {\n throw new MeshCliError(`A '${HUB_SESSION}' tmux session is already running.`, {\n remediation: { command: \"mesh hub dev --kill # then re-run mesh hub dev\" },\n });\n }\n\n // Pre-flight the ports. Without this, a port already owned by ANOTHER Hub\n // (the containerized `mesh start` one is fixed at :9000, or a plain\n // `mesh dev` from apps/hub holds :3002) makes the post-launch waitForPort\n // succeed against that other process: vite has no strictPort in its config\n // so the UI silently falls forward to the next free port, and we would then\n // print \"Hub \u2192 http://localhost:9000\" pointing at someone else's Hub \u2014 the\n // exact silently-wrong-Hub failure this command exists to remove.\n for (const [label, port, flag] of [\n [\"API\", apiPort, \"--api-port\"],\n [\"UI\", uiPort, \"--port\"],\n ] as const) {\n if (await isPortListening(port)) {\n throw new MeshCliError(\n `Hub ${label} port ${port} is already in use \u2014 another process (a \\`mesh start\\` Hub, or another \\`mesh hub dev\\`) is listening there.`,\n { remediation: { command: `mesh hub dev ${flag} <free-port> # or free :${port} first` } },\n );\n }\n }\n\n logInfo(`Dev session : ${session.name} (${session.state.appRoot})`);\n logInfo(`Hub source : ${platformDir}`);\n logInfo(\n `Scope : HUB_TENANT=${assembled.scope.hubTenant} HUB_SCOPE_ENV=${assembled.scope.scopeEnv} HUB_SCOPE_TENANTS=${assembled.scope.scopeTenants.join(\",\")}`,\n );\n logInfo(`Temporal : ${assembled.temporalAddress}`);\n for (const note of assembled.notes) logInfo(note);\n for (const warning of assembled.warnings) logWarn(warning);\n\n const apiDir = path.join(platformDir, \"apps\", \"hub\", \"api\");\n const uiDir = path.join(platformDir, \"apps\", \"hub\", \"ui\");\n\n execFileSync(\"tmux\", [\"new-session\", \"-d\", \"-s\", HUB_SESSION, \"-n\", \"api\", \"-c\", apiDir]);\n\n // Fresh dev tokens: reuse the app session's token-server when it has one;\n // otherwise run our own (MESH-2039 pattern) so the Hub survives past the\n // ~1h Zitadel horizon either way.\n if (!assembled.apiEnv.DEV_USER_TOKEN_URL && assembled.apiEnv.DEV_USER_ID_TOKEN) {\n const platform = session.state.devOutput.platform!;\n const credContext = `mesh.${platform.env}`;\n const tokenPort = await findFreePort();\n const tokenUrl = `http://127.0.0.1:${tokenPort}`;\n execFileSync(\"tmux\", [\"new-window\", \"-t\", HUB_SESSION, \"-n\", \"token-server\", \"-c\", platformDir]);\n execFileSync(\"tmux\", [\"set-option\", \"-t\", `${HUB_SESSION}:token-server`, \"remain-on-exit\", \"on\"], {\n stdio: \"ignore\",\n });\n execFileSync(\"tmux\", [\n \"send-keys\",\n \"-t\",\n `${HUB_SESSION}:token-server`,\n `npx mesh dev __token-server ${tokenPort} ${credContext}`,\n \"Enter\",\n ]);\n for (let i = 0; i < 15 && !(await isPortListening(tokenPort)); i++) {\n await new Promise((r) => setTimeout(r, 200));\n }\n assembled.apiEnv.DEV_USER_TOKEN_URL = tokenUrl;\n assembled.uiEnv.DEV_USER_TOKEN_URL = tokenUrl;\n logSuccess(`Dev-user token-server: ${tokenUrl} (context ${credContext})`);\n }\n\n const launch = (window: string, dir: string, env: Record<string, string>, cmd: string, createWindow: boolean) => {\n const envFile = path.join(hubEnvDir(), `${window}.env.sh`);\n writeEnvFile(envFile, env);\n if (createWindow) {\n execFileSync(\"tmux\", [\"new-window\", \"-t\", HUB_SESSION, \"-n\", window, \"-c\", dir]);\n }\n execFileSync(\"tmux\", [\"set-option\", \"-t\", `${HUB_SESSION}:${window}`, \"remain-on-exit\", \"on\"], {\n stdio: \"ignore\",\n });\n execFileSync(\"tmux\", [\"send-keys\", \"-t\", `${HUB_SESSION}:${window}`, buildLaunchCommand(envFile, dir, cmd), \"Enter\"]);\n };\n\n launch(\"api\", apiDir, assembled.apiEnv, \"pnpm dev\", false);\n // --strictPort: the Hub UI's vite config sets `port` but NOT `strictPort`, so\n // vite would silently fall forward to the next free port and we'd advertise a\n // URL serving something else. Fail instead \u2014 the pre-flight above already\n // rejects a taken port, this closes the race. (`host: true` is already in\n // apps/hub/ui/vite.config.ts, so the tailnet binding needs no flag here.)\n launch(\"ui\", uiDir, assembled.uiEnv, `pnpm dev -- --port ${uiPort} --strictPort`, true);\n\n logInfo(\"Waiting for the Hub to come up\u2026\");\n const apiUp = await waitForPort(\"127.0.0.1\", apiPort, 90_000);\n const uiUp = apiUp && (await waitForPort(\"127.0.0.1\", uiPort, 90_000));\n if (!apiUp || !uiUp) {\n throw new MeshCliError(\n `Hub ${apiUp ? \"UI\" : \"API\"} did not start listening (api :${apiPort}, ui :${uiPort}).`,\n { remediation: { command: `tmux attach -t ${HUB_SESSION} # inspect the ${apiUp ? \"ui\" : \"api\"} window` } },\n );\n }\n\n console.log(\"\");\n logSuccess(`Mesh Hub (dev-local scope ${assembled.scope.scopeTenants.join(\",\")} @ ${assembled.scope.scopeEnv})`);\n console.log(` ${chalk.bold.cyan(`http://localhost:${uiPort}`)} (also reachable on your tailnet)`);\n console.log(` api http://localhost:${apiPort}`);\n console.log(` logs tmux attach -t ${HUB_SESSION}`);\n console.log(` stop mesh hub dev --kill`);\n}\n\nexport function registerHubCommands(program: Command): void {\n const hub = program.command(\"hub\").description(\"Local Hub over dev-local stacks\");\n hub\n .command(\"dev\")\n .description(\n \"Launch the current-code Hub (api + ui) against a running `mesh dev` session \u2014 env auto-assembled, zero hand-set vars\",\n )\n .option(\"--session <name>\", \"dev session to observe (default: auto-detect from cwd)\")\n .option(\"--tenants <list>\", \"comma-separated HUB_SCOPE_TENANTS override (default: the session's tenant)\")\n .option(\"--port <port>\", `Hub UI host port (default: $MESH_HUB_DEV_PORT or ${DEFAULT_HUB_UI_PORT})`)\n .option(\"--api-port <port>\", `Hub API port (default: ${DEFAULT_HUB_API_PORT})`)\n .option(\"--platform-dir <dir>\", \"mesh-platform checkout to run the Hub from (default: $MESH_PLATFORM_DIR or walk up from cwd)\")\n .option(\"--print-env\", \"print the assembled env (secrets redacted) and exit without launching\")\n .option(\"--kill\", \"tear down the running Hub session\")\n .action(hubDevAction);\n}\n", "/**\n * mesh init app-tenant \u2014 the doctor for a tenant apps repo (design \u00A73.1,\n * AC A1\u2013A3).\n *\n * Runs a read-only check pipeline; every failure names the exact `mesh`\n * command that fixes it (never a person \u2014 A2). Re-running IS the doctor\n * (A3): exit 0 iff everything passes. `--json` is the agent surface (A5);\n * `--fix` applies the developer-scope fixes directly (registry token\n * refresh, skills sync) and leaves operator actions as remediations.\n *\n * Checks (API-first; local platform = the same Hub API on localhost):\n * 1. CLI auth \u2014 cached `mesh login` credentials for the context\n * 2. Registry access \u2014 the CodeArtifact token in ~/.npmrc is accepted by the\n * registry (a live probe, not a substring match \u2014 an\n * expired token used to report `pass`); local: skipped\n * 2b. Public npm not hijacked \u2014 no unscoped `registry=<codeartifact>` in\n * ~/.npmrc making CodeArtifact the DEFAULT registry\n * 3. Platform tenant \u2014 Hub API /tenants (the platform registry)\n * 4. App tenant \u2014 tenant present in the Hub registry\n * 5. Deployer role \u2014 mesh:deployerRole config present (cloud contexts)\n * 6. Repo shape \u2014 pnpm workspace + apps layout create-app expects\n * 7. Skills wired \u2014 `mesh skills sync --check`\n */\n\nimport { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport { logInfo } from \"../utils/log.js\";\nimport { MeshCliError, emitJsonPayload } from \"../utils/errors.js\";\nimport {\n findUnscopedCodeArtifactRegistry,\n homeNpmrcPath,\n probeRegistryToken,\n} from \"../utils/auth-preflight.js\";\nimport { readCredentials } from \"./login.js\";\nimport { resolveTargetRoot, syncSkills } from \"./skills.js\";\nimport { detectLocalTenant } from \"./local/dev-local.js\";\nimport { LOGIN_CONTEXT } from \"./local/seed-zitadel.js\";\n\ntype CheckStatus = \"pass\" | \"warn\" | \"fail\";\n\ninterface CheckResult {\n name: string;\n status: CheckStatus;\n detail: string;\n /** The exact command that remediates (A2: commands, never people). */\n fix?: string;\n}\n\nconst LOCAL_HUB_API = \"http://localhost:4568\";\n\nfunction isLocalContext(context: string): boolean {\n return context === LOGIN_CONTEXT;\n}\n\nasync function probeHubTenants(hubUrl: string, accessToken: string | null): Promise<\n { ok: true; tenants: Array<{ name: string }> } | { ok: false; reason: string }\n> {\n try {\n const response = await fetch(`${hubUrl}/tenants`, {\n headers: accessToken ? { Authorization: `Bearer ${accessToken}` } : {},\n signal: AbortSignal.timeout(5000),\n });\n if (response.status === 401) return { ok: false, reason: \"unauthenticated against the Hub API\" };\n if (!response.ok) return { ok: false, reason: `Hub API returned ${response.status}` };\n return { ok: true, tenants: (await response.json()) as Array<{ name: string }> };\n } catch {\n return { ok: false, reason: `Hub API unreachable at ${hubUrl}` };\n }\n}\n\nfunction readHomeNpmrc(): string {\n try {\n return fs.readFileSync(homeNpmrcPath(), \"utf-8\");\n } catch {\n return \"\";\n }\n}\n\n/**\n * The remediation string the doctor prints for a registry fault. It must render\n * the command `--fix` actually executes: `runRegistryLogin` is called with the\n * doctor's own `--profile` (or none), so advertising a hardcoded\n * `--profile mesh-dev` would be a command the doctor never runs.\n */\nexport function registryFixCommand(profile?: string, context?: string): string {\n // Context first: `--fix` calls runRegistryLogin(ctx, \u2026), and a context-less\n // `mesh registry login` skips the broker entirely \u2014 so advertising the bare\n // form sends someone with no AWS account to a command that cannot work.\n const base = context ? `mesh registry login ${context}` : \"mesh registry login\";\n return profile ? `${base} --profile ${profile}` : base;\n}\n\n/**\n * The two registry checks, exported for tests.\n *\n * 1. **Registry access** \u2014 does the token in ~/.npmrc actually work? The old\n * check was `content.includes(\"codeartifact\")`, which reports `pass` for a\n * token that expired two days ago. `probeRegistryToken` asks the registry.\n * 2. **Public npm not hijacked** \u2014 is there an *unscoped* `registry=` line\n * pointing at CodeArtifact? A bare `aws codeartifact login` (no\n * `--namespace @mesh-tech`) writes one, which routes every public package\n * through CodeArtifact and makes the whole of npm 401 at the 12h token\n * expiry. `mesh registry login` now removes it, so it is the fix for both.\n */\nexport async function registryChecks(args: {\n context: string;\n fix: boolean;\n /** AWS SSO profile to log in with \u2014 threaded from `mesh init app-tenant --profile`. */\n profile?: string;\n /** Test seam \u2014 defaults to the real network probe against ~/.npmrc. */\n probe?: typeof probeRegistryToken;\n /** Test seam \u2014 defaults to `runRegistryLogin`. */\n login?: (context: string) => Promise<void>;\n}): Promise<CheckResult[]> {\n const { context, fix, profile } = args;\n const probe = args.probe ?? probeRegistryToken;\n const login =\n args.login ??\n (async (ctx: string) => {\n const { runRegistryLogin } = await import(\"./registry.js\");\n await runRegistryLogin(ctx, profile ? { profile } : {});\n });\n\n // The command we ADVERTISE must be the command `--fix` RUNS \u2014 otherwise the\n // doctor tells you to pass a profile it then silently drops.\n const REGISTRY_FIX = registryFixCommand(profile, context);\n\n let tokenState = await probe({ npmrcPath: homeNpmrcPath() });\n let hijack = findUnscopedCodeArtifactRegistry(readHomeNpmrc());\n let repaired = false;\n let loginError: string | null = null;\n\n // One login repairs both: it refreshes the token AND strips the unscoped line.\n if (fix && (tokenState.state === \"expired\" || tokenState.state === \"missing\" || hijack)) {\n try {\n await login(context);\n repaired = true;\n tokenState = await probe({ npmrcPath: homeNpmrcPath() });\n hijack = findUnscopedCodeArtifactRegistry(readHomeNpmrc());\n } catch (err) {\n loginError = err instanceof Error ? err.message : String(err);\n }\n }\n\n const suffix = repaired ? \" (--fix)\" : \"\";\n const checks: CheckResult[] = [];\n\n if (loginError) {\n checks.push({\n name: \"Registry access\",\n status: \"fail\",\n detail: `token refresh failed: ${loginError}`,\n fix: REGISTRY_FIX,\n });\n } else if (tokenState.state === \"fresh\") {\n checks.push({\n name: \"Registry access\",\n status: \"pass\",\n detail: `CodeArtifact token in ~/.npmrc is accepted by the registry${suffix}`,\n });\n } else if (tokenState.state === \"unreachable\") {\n // A network fault is not an auth fault \u2014 don't send someone to `aws sso login`.\n checks.push({\n name: \"Registry access\",\n status: \"warn\",\n detail: `could not reach the registry to verify the token (${tokenState.detail ?? \"unknown error\"})`,\n fix: REGISTRY_FIX,\n });\n } else {\n checks.push({\n name: \"Registry access\",\n status: \"fail\",\n detail:\n tokenState.state === \"expired\"\n ? `the CodeArtifact token in ~/.npmrc is expired (${tokenState.detail ?? \"rejected by the registry\"})`\n : \"no CodeArtifact token in ~/.npmrc\",\n fix: REGISTRY_FIX,\n });\n }\n\n checks.push(\n hijack\n ? {\n name: \"Public npm not hijacked\",\n status: \"fail\",\n detail:\n `~/.npmrc makes CodeArtifact the DEFAULT registry (${hijack.trim()}) \u2014 every public ` +\n \"package resolves through it and 401s when the 12h token expires\",\n fix: REGISTRY_FIX,\n }\n : {\n name: \"Public npm not hijacked\",\n status: \"pass\",\n detail: `no unscoped CodeArtifact registry= in ~/.npmrc${repaired ? \" (--fix removed it)\" : \"\"}`,\n },\n );\n\n return checks;\n}\n\nasync function runChecks(args: {\n root: string;\n tenant: string;\n context: string;\n hubUrl: string;\n fix: boolean;\n profile?: string;\n}): Promise<CheckResult[]> {\n const { root, tenant, context, hubUrl, fix, profile } = args;\n const checks: CheckResult[] = [];\n const local = isLocalContext(context);\n\n // 1. CLI auth\n const creds = readCredentials(context);\n const expired = creds ? new Date(creds.expiresAt).getTime() < Date.now() : true;\n checks.push(\n creds && !expired\n ? { name: \"CLI auth\", status: \"pass\", detail: `logged in (${context}${creds.email ? `, ${creds.email}` : \"\"})` }\n : {\n name: \"CLI auth\",\n status: \"fail\",\n detail: creds ? `credentials for '${context}' are expired` : `no credentials for context '${context}'`,\n fix: `mesh login ${context}`,\n },\n );\n const accessToken = creds && !expired ? creds.accessToken : null;\n\n // 2 + 2b. Registry access (CodeArtifact) \u2014 the local platform has no registry\n if (local) {\n checks.push({ name: \"Registry access\", status: \"pass\", detail: \"local context \u2014 no registry required\" });\n checks.push({ name: \"Public npm not hijacked\", status: \"pass\", detail: \"local context \u2014 no registry required\" });\n } else {\n checks.push(...(await registryChecks({ context, fix, profile })));\n }\n\n // 3 + 4. Platform tenant + app tenant via the Hub API (the registry)\n const hub = await probeHubTenants(hubUrl, accessToken);\n if (!hub.ok) {\n const fixCmd = local ? \"mesh start\" : `mesh login ${context}`;\n checks.push({ name: \"Platform reachable\", status: \"fail\", detail: hub.reason, fix: fixCmd });\n checks.push({\n name: `App tenant '${tenant}'`,\n status: \"warn\",\n detail: \"not verifiable while the platform registry is unreachable\",\n fix: fixCmd,\n });\n } else {\n checks.push({\n name: \"Platform reachable\",\n status: \"pass\",\n detail: `Hub API at ${hubUrl} (${hub.tenants.length} tenant(s) registered)`,\n });\n const registered = hub.tenants.some((t) => t.name === tenant);\n checks.push(\n registered\n ? { name: `App tenant '${tenant}'`, status: \"pass\", detail: \"registered in the platform registry\" }\n : {\n name: `App tenant '${tenant}'`,\n status: local ? \"warn\" : \"fail\",\n detail: local\n ? \"not registered yet \u2014 auto-created on the first `mesh dev` run of an app in this repo\"\n : \"not registered \u2014 register it on the platform stack and deploy\",\n fix: local ? \"mesh dev\" : `mesh tenant add ${tenant} # in the platform repo, then: mesh deploy up`,\n },\n );\n }\n\n // 5. Deployer role (cloud contexts only \u2014 local has no IAM)\n if (local) {\n checks.push({ name: \"Deployer role\", status: \"pass\", detail: \"local context \u2014 no deployer role required\" });\n } else {\n const stackFiles = fs.existsSync(root)\n ? fs.readdirSync(root).filter((f) => /^Pulumi\\..*\\.yaml$/.test(f))\n : [];\n const hasRole = stackFiles.some((f) =>\n /mesh:deployerRole/.test(fs.readFileSync(path.join(root, f), \"utf-8\")),\n );\n checks.push(\n hasRole\n ? { name: \"Deployer role\", status: \"pass\", detail: \"mesh:deployerRole configured in stack config\" }\n : {\n name: \"Deployer role\",\n status: \"warn\",\n detail: \"no mesh:deployerRole in Pulumi.*.yaml \u2014 `mesh deploy` will not be able to assume a role\",\n fix: \"mesh create-app # scaffolds stack config with the deployer role\",\n },\n );\n }\n\n // 6. Repo shape (what create-app/mesh dev expect)\n const shapeProblems: string[] = [];\n if (!fs.existsSync(path.join(root, \"package.json\"))) shapeProblems.push(\"package.json\");\n const hasWorkspace =\n fs.existsSync(path.join(root, \"pnpm-workspace.yaml\")) ||\n fs.existsSync(path.join(root, \"pnpm-lock.yaml\"));\n if (!hasWorkspace) shapeProblems.push(\"pnpm-workspace.yaml\");\n checks.push(\n shapeProblems.length === 0\n ? { name: \"Repo shape\", status: \"pass\", detail: \"pnpm workspace layout present\" }\n : {\n name: \"Repo shape\",\n status: \"warn\",\n detail: `missing: ${shapeProblems.join(\", \")}`,\n fix: \"mesh create-app # scaffold an app (workspace files included)\",\n },\n );\n\n // 7. Skills wired\n const skillsOk = fix ? syncSkills(root) : syncSkills(root, { check: true });\n checks.push(\n skillsOk\n ? { name: \"Agent skills\", status: \"pass\", detail: \"base skills + Intent discovery in sync\" }\n : {\n name: \"Agent skills\",\n status: fix ? \"pass\" : \"fail\",\n detail: fix ? \"synced (--fix)\" : \"missing or stale\",\n fix: \"mesh skills sync\",\n },\n );\n\n return checks;\n}\n\nexport function registerInitCommands(program: Command): void {\n const init = program.command(\"init\").description(\"Initialize / diagnose a repo against the Mesh platform\");\n\n init\n .command(\"platform <tenant>\")\n .description(\n \"Scaffold a tenant PLATFORM repo (core + platform Pulumi layers on @mesh-tech/infra-components) that deploys with `mesh deploy` unmodified \u2014 the proven mesh-sandbox shape, annotated.\",\n )\n .option(\"--env <env>\", \"environment the first stack targets\", \"dev\")\n .option(\"--region <region>\", \"AWS region\", \"us-east-2\")\n .option(\"--domain <domain>\", \"base public domain (ingress zone becomes {env}.{domain})\", \"example.com\")\n .option(\"--profile <profile>\", \"AWS profile the stack config references\", \"default\")\n .option(\"--state-bucket <bucket>\", \"Pulumi state S3 bucket (created by an operator)\", undefined)\n .option(\"--dir <path>\", \"target directory (default: ./{tenant}-mesh-platform)\")\n .action(async (tenant: string, opts: { env: string; region: string; domain: string; profile: string; stateBucket?: string; dir?: string }) => {\n if (!/^[a-z][a-z0-9-]*$/.test(tenant)) {\n throw new MeshCliError(`Invalid tenant name '${tenant}' (lowercase alphanumeric + dashes).`);\n }\n const targetDir = path.resolve(opts.dir ?? `${tenant}-mesh-platform`);\n if (fs.existsSync(targetDir) && fs.readdirSync(targetDir).length > 0) {\n throw new MeshCliError(`Target directory is not empty: ${targetDir}`, {\n remediation: { command: `mesh init platform ${tenant} --dir <empty-dir>` },\n });\n }\n const { copyTemplate } = await import(\"./create-app.js\");\n const { findPackageRoot } = await import(\"./local/stack.js\");\n const templateDir = path.join(findPackageRoot(), \"templates\", \"platform-repo\");\n const context = {\n tenant,\n env: opts.env,\n region: opts.region,\n domain: opts.domain,\n profile: opts.profile,\n stateBucket: opts.stateBucket ?? `${tenant}-mesh-platform-pulumi-state`,\n };\n fs.mkdirSync(targetDir, { recursive: true });\n copyTemplate(templateDir, targetDir, context);\n syncSkills(targetDir);\n logInfo(`Platform repo scaffolded at ${targetDir}`);\n console.log(\"\");\n console.log(\"Next steps:\");\n console.log(` cd ${path.relative(process.cwd(), targetDir) || \".\"}`);\n console.log(` mesh login ${tenant}.${opts.env} # or an operator context with access`);\n console.log(\" pnpm install\");\n console.log(\" cd core && mesh deploy up\");\n console.log(\" cd ../platform && mesh deploy up\");\n console.log(\"\");\n logInfo(`Review the annotated stack configs (Pulumi.${tenant}-${opts.env}.yaml) before the first deploy.`);\n });\n\n init\n .command(\"app-tenant\")\n .description(\n \"Check (and with --fix, repair) everything an app-tenant repo needs: auth, registry, tenant registration, repo shape, agent skills. Re-run any time \u2014 it is the doctor.\",\n )\n .option(\"--tenant <name>\", \"app tenant (default: mesh:tenant from Pulumi config, else 'local')\")\n .option(\"--context <ctx>\", \"login context to check against (default: 'local' when the local platform is targeted)\", LOGIN_CONTEXT)\n .option(\"--hub-url <url>\", \"platform Hub API base URL\", LOCAL_HUB_API)\n .option(\"--fix\", \"apply developer-scope fixes (registry token, skills sync)\", false)\n .option(\"--profile <profile>\", \"AWS SSO profile --fix logs into CodeArtifact with (e.g. mesh-dev)\")\n .option(\"--json\", \"machine-readable output\", false)\n .action(async (opts: { tenant?: string; context: string; hubUrl: string; fix: boolean; profile?: string; json: boolean }) => {\n const root = resolveTargetRoot();\n const tenant = opts.tenant ?? detectLocalTenant(root);\n if (!opts.json) {\n logInfo(`Checking app-tenant repo ${root} (tenant '${tenant}', context '${opts.context}')\u2026`);\n }\n // Under --json, stdout is the machine surface (A5): route the check\n // helpers' human chatter (syncSkills / registry login logInfo etc.) to\n // stderr so stdout stays pure parseable JSON.\n const origLog = console.log;\n if (opts.json) console.log = (...a: unknown[]) => console.error(...a);\n let checks: Awaited<ReturnType<typeof runChecks>>;\n try {\n checks = await runChecks({\n root,\n tenant,\n context: opts.context,\n hubUrl: opts.hubUrl.replace(/\\/+$/, \"\"),\n fix: opts.fix,\n profile: opts.profile,\n });\n } finally {\n console.log = origLog;\n }\n // Warns are advisory (expected on a fresh repo pre-`mesh dev`): only\n // hard failures gate the exit code (A3). `ok` mirrors that contract.\n const ok = !checks.some((c) => c.status === \"fail\");\n\n if (opts.json) {\n emitJsonPayload({ ok, root, tenant, context: opts.context, checks });\n } else {\n console.log(\"\");\n for (const check of checks) {\n const icon =\n check.status === \"pass\" ? chalk.green(\"\u2714\") : check.status === \"warn\" ? chalk.yellow(\"\u25B2\") : chalk.red(\"\u2718\");\n console.log(` ${icon} ${check.name.padEnd(24)} ${check.detail}`);\n if (check.fix && check.status !== \"pass\") {\n console.log(` ${chalk.dim(\"\u2192 run:\")} ${chalk.cyan(check.fix)}`);\n }\n }\n console.log(\"\");\n }\n\n if (!ok) {\n throw new MeshCliError(\"app-tenant checks failed \u2014 apply the fixes above and re-run.\", {\n remediation: { command: \"mesh init app-tenant --fix\" },\n });\n }\n });\n}\n", "import { execFileSync } from \"child_process\";\nimport { Command } from \"commander\";\nimport * as fs from \"fs\";\nimport * as os from \"os\";\nimport * as path from \"path\";\nimport { logError, logInfo, logSuccess, logWarn } from \"../utils/log.js\";\n\n/**\n * `mesh install-shim` \u2014 make bare `mesh` work on the PATH without a build.\n *\n * People and agents reach for `mesh dev`, not `pnpm exec mesh dev`. Getting a\n * bare `mesh` onto the PATH inherently needs one PATH entry \u2014 but it can be a\n * build-free, cwd-aware resolver: a tiny shell script that, on each run, walks\n * up from the current directory to the nearest workspace `node_modules/.bin/mesh`\n * and execs it. That `.bin/mesh` is the `bin/mesh.mjs` launcher, which runs the\n * CLI from TypeScript source \u2014 so bare `mesh` always runs the LOCAL source of\n * whatever worktree/app you are in, with no build and nothing global to keep in\n * sync (MESH-2261). Run this once; it survives worktree switches and pulls.\n */\n\n/** The cwd-aware resolver written to the PATH. Pure so it can be unit-tested. */\nexport function shimScript(): string {\n return `#!/bin/sh\n# mesh \u2014 canonical launcher shim (installed by \\`mesh install-shim\\`, MESH-2261).\n# Walks up from the current directory to the nearest workspace mesh CLI and runs\n# it. That resolves to bin/mesh.mjs, which runs the CLI from TypeScript source \u2014\n# so this always runs the LOCAL source of whatever worktree/app you are in, with\n# no build step. Nothing here is version-pinned; do not edit by hand.\ndir=$(pwd)\nwhile [ \"$dir\" != \"/\" ]; do\n if [ -x \"$dir/node_modules/.bin/mesh\" ]; then\n exec \"$dir/node_modules/.bin/mesh\" \"$@\"\n fi\n dir=$(dirname \"$dir\")\ndone\necho \"mesh: not inside a Mesh workspace (no node_modules/.bin/mesh found).\" >&2\necho \" cd into your app/repo (after 'pnpm install'), or run 'pnpm exec mesh'.\" >&2\nexit 1\n`;\n}\n\n/** Default install target: ~/.local/bin (conventional per-user PATH dir). */\nexport function defaultShimDir(): string {\n return path.join(os.homedir(), \".local\", \"bin\");\n}\n\n/** True if `dir` is a component of the PATH env string. */\nexport function dirOnPath(dir: string, pathEnv: string | undefined): boolean {\n if (!pathEnv) return false;\n return pathEnv.split(path.delimiter).some((p) => p === dir);\n}\n\nexport function registerInstallShimCommand(program: Command): void {\n program\n .command(\"install-shim\")\n .description(\"Install a build-free `mesh` shim on your PATH so bare `mesh` runs the local source\")\n .option(\"--dir <dir>\", \"Directory to install into (must be on your PATH)\", defaultShimDir())\n .option(\"-f, --force\", \"Overwrite an existing file at the target path\", false)\n .action((opts: { dir: string; force: boolean }) => {\n const dir = path.resolve(opts.dir);\n const target = path.join(dir, \"mesh\");\n\n if (fs.existsSync(target) && !opts.force) {\n logWarn(`A file already exists at ${target}.`);\n logInfo(\"Re-run with --force to overwrite it, or pass --dir <other-path-on-PATH>.\");\n return;\n }\n\n try {\n fs.mkdirSync(dir, { recursive: true });\n fs.writeFileSync(target, shimScript(), { mode: 0o755 });\n fs.chmodSync(target, 0o755);\n } catch (err) {\n logError(`Could not write the shim to ${target}: ${(err as Error).message}`);\n process.exitCode = 1;\n return;\n }\n\n logSuccess(`Installed mesh shim \u2192 ${target}`);\n if (!dirOnPath(dir, process.env.PATH)) {\n logWarn(`${dir} is not on your PATH.`);\n logInfo(`Add it, e.g.: echo 'export PATH=\"${dir}:$PATH\"' >> ~/.zshrc && source ~/.zshrc`);\n } else {\n logInfo(\"Bare `mesh <cmd>` now runs the local source of whatever workspace you're in.\");\n }\n\n // Post-install self-test: run the freshly installed shim and record a full\n // diagnostic (env + stdout/stderr + exit) to a file, so a failure is\n // debuggable without copy-pasting terminal output.\n const diagPath = path.join(os.tmpdir(), \"mesh-shim-selftest.log\");\n let stdout = \"\";\n let stderr = \"\";\n let status = 0;\n let ok = true;\n try {\n stdout = execFileSync(target, [\"--help\"], {\n cwd: process.cwd(),\n encoding: \"utf8\",\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n } catch (err) {\n ok = false;\n const e = err as { status?: unknown; stdout?: unknown; stderr?: unknown; message?: unknown };\n status = typeof e.status === \"number\" ? e.status : 1;\n stdout = e.stdout?.toString?.() ?? \"\";\n stderr = e.stderr?.toString?.() ?? String(e.message ?? err);\n }\n const diag = [\n `mesh install-shim self-test \u2014 ${new Date().toISOString()}`,\n `cwd: ${process.cwd()}`,\n `shim: ${target}`,\n `node: ${process.execPath} (${process.version})`,\n `PATH: ${process.env.PATH ?? \"\"}`,\n `command: mesh --help`,\n `exit: ${status}`,\n `--- stdout (${stdout.length} bytes) ---`,\n stdout,\n `--- stderr (${stderr.length} bytes) ---`,\n stderr,\n \"\",\n ].join(\"\\n\");\n try {\n fs.writeFileSync(diagPath, diag);\n } catch {\n /* diagnostics are best-effort */\n }\n\n if (ok && /Commands:|Usage:/.test(stdout)) {\n logSuccess(`Self-test passed: \\`mesh --help\\` ran cleanly. Diagnostic: ${diagPath}`);\n } else {\n logError(`Self-test FAILED (exit ${status}). Full diagnostic written to:`);\n logError(` ${diagPath}`);\n process.exitCode = 1;\n }\n });\n}\n", "/**\n * Local Hub image builder (`mesh start --with-hub`) \u2014 the interim path\n * until the hub pipeline publishes pullable container images (design \u00A711).\n *\n * Resolves the published @mesh-tech/hub tarball with the user's registry\n * auth (mesh registry login), extracts it, and docker-builds two images\n * from the prebuilt dists it ships (api/dist \u2192 mesh-local-hub-api,\n * ui/build \u2192 mesh-local-hub-ui). The CodeArtifact token enters the build\n * as a BuildKit secret and never lands in a layer. Idempotent: images are\n * keyed by the package version and rebuilt only when missing.\n */\n\nimport { execFile, execFileSync } from \"child_process\";\nimport * as fs from \"fs\";\nimport * as os from \"os\";\nimport * as path from \"path\";\nimport { promisify } from \"util\";\nimport { logInfo, logSuccess, logWarn, startHeartbeat } from \"../../utils/log.js\";\nimport { MeshCliError } from \"../../utils/errors.js\";\nimport { isNpmAuthError, REGISTRY_LOGIN_FIX, type RegistryTokenState } from \"../../utils/auth-preflight.js\";\nimport { findPackageRoot } from \"./stack.js\";\n\nconst execFileAsync = promisify(execFile);\n\nconst HUB_PACKAGE = \"@mesh-tech/hub\";\nexport const HUB_IMAGES = [\"mesh-local-hub-api\", \"mesh-local-hub-ui\"] as const;\n/** Bump when stack/hub/Dockerfile.* change \u2014 forces a rebuild of images\n * already cached for the same published hub version. */\nconst LOCAL_IMAGE_REV = \"r2\";\n\nfunction cacheDir(): string {\n const dir = path.join(os.homedir(), \".cache\", \"mesh\", \"hub-local\");\n fs.mkdirSync(dir, { recursive: true });\n return dir;\n}\n\nfunction npmrcPath(): string {\n const p = path.join(os.homedir(), \".npmrc\");\n if (!fs.existsSync(p) || !fs.readFileSync(p, \"utf-8\").includes(\"codeartifact\")) {\n throw new MeshCliError(\n \"The local Hub builds from the published @mesh-tech/hub tarball, which needs registry auth.\",\n { remediation: { command: REGISTRY_LOGIN_FIX } },\n );\n }\n return p;\n}\n\nfunction imageExists(tag: string): boolean {\n try {\n execFileSync(\"docker\", [\"image\", \"inspect\", tag], { stdio: [\"ignore\", \"pipe\", \"pipe\"] });\n return true;\n } catch {\n return false;\n }\n}\n\n/** Tag referenced by docker-compose.hub.yml \u2014 bump alongside Dockerfile.auth. */\nconst HUB_AUTH_IMAGE = \"mesh-local-hub-auth:v7.7.1-r1\";\n\n/**\n * Build the Hub's oauth2-proxy image (hosted sidecar + loopback issuer\n * forward). Public base images only \u2014 no registry auth involved.\n */\nexport function ensureHubAuthImage(): void {\n if (imageExists(HUB_AUTH_IMAGE)) return;\n logInfo(`Building ${HUB_AUTH_IMAGE} (Hub auth proxy)\u2026`);\n const hubStackDir = path.join(findPackageRoot(), \"stack\", \"hub\");\n execFileSync(\n \"docker\",\n [\"build\", \"-f\", path.join(hubStackDir, \"Dockerfile.auth\"), \"-t\", HUB_AUTH_IMAGE, hubStackDir],\n { stdio: [\"ignore\", \"inherit\", \"inherit\"], env: { ...process.env, DOCKER_BUILDKIT: \"1\" } },\n );\n logSuccess(`Built ${HUB_AUTH_IMAGE}`);\n}\n\n/** Registry auth present? (Needed only to BUILD hub images, not to run them.) */\nexport function hasRegistryAuth(): boolean {\n const p = path.join(os.homedir(), \".npmrc\");\n return fs.existsSync(p) && fs.readFileSync(p, \"utf-8\").includes(\"codeartifact\");\n}\n\n/**\n * Newest hub version whose images already exist locally \u2014 lets `mesh start`\n * include the Hub by default with no network and no registry auth. Returns\n * undefined when no built images are present.\n */\nexport function localHubVersion(): string | undefined {\n const versions = HUB_IMAGES.map((name) => {\n try {\n const out = execFileSync(\"docker\", [\"images\", name, \"--format\", \"{{.Tag}}\"], {\n encoding: \"utf-8\",\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n return out.split(\"\\n\").map((t) => t.trim()).filter((t) => t && t !== \"<none>\");\n } catch {\n return [] as string[];\n }\n });\n const shared = versions[0]!.filter(\n (v) => v.endsWith(`-${LOCAL_IMAGE_REV}`) && versions.every((list) => list.includes(v)),\n );\n if (shared.length === 0) return undefined;\n // Highest semver wins (numeric-aware compare handles the -rN suffix).\n return shared.sort((a, b) => a.localeCompare(b, undefined, { numeric: true })).at(-1);\n}\n\n/** `npm pack` the published hub tarball into the cache; returns its path +\n * version. Falls back to the newest cached tarball when the registry is\n * unreachable (offline / expired token). Async so the heartbeat can fill\n * silence during the fetch \u2014 a first run's slowest, quietest step. */\nasync function fetchTarball(): Promise<{ tarball: string; version: string }> {\n const dir = cacheDir();\n logInfo(`Resolving ${HUB_PACKAGE} from the registry\u2026`);\n const heartbeat = startHeartbeat(`fetching the ${HUB_PACKAGE} tarball from CodeArtifact`);\n try {\n const { stdout } = await execFileAsync(\n \"npm\",\n [\"pack\", `${HUB_PACKAGE}@latest`, \"--pack-destination\", dir, \"--json\"],\n { encoding: \"utf-8\" },\n );\n const info = JSON.parse(stdout)[0];\n return { tarball: path.join(dir, info.filename), version: info.version };\n } catch (err) {\n const authFailure = isNpmAuthError(err);\n const cached = fs\n .readdirSync(dir)\n .filter((f) => f.startsWith(\"mesh-tech-hub-\") && f.endsWith(\".tgz\"))\n .sort((a, b) => a.localeCompare(b, undefined, { numeric: true }))\n .at(-1);\n if (!cached) {\n // Map npm's E401 (\"try npm login\") to the Mesh fix \u2014 npm login can\n // never mint a CodeArtifact token (MESH-2479).\n if (authFailure) {\n throw new MeshCliError(\n `The registry rejected the ${HUB_PACKAGE} tarball fetch (E401 Unauthorized) \u2014 your CodeArtifact token is expired or invalid. (npm's \"try npm login\" advice does not apply to this registry.)`,\n { remediation: { command: REGISTRY_LOGIN_FIX }, cause: err },\n );\n }\n throw err;\n }\n const version = cached.replace(\"mesh-tech-hub-\", \"\").replace(/\\.tgz$/, \"\");\n if (authFailure) {\n logWarn(\n `Registry rejected the fetch (E401 \u2014 CodeArtifact token expired). Using the cached hub tarball v${version}; refresh with: ${REGISTRY_LOGIN_FIX}`,\n );\n } else {\n logInfo(`Registry unavailable \u2014 using the cached hub tarball v${version}`);\n }\n return { tarball: path.join(dir, cached), version };\n } finally {\n heartbeat.stop();\n }\n}\n\nexport type WithHubPlan =\n | { action: \"refresh\" }\n | { action: \"use-local\"; version: string; warning: string }\n | { action: \"fail\"; message: string; remediation: string };\n\n/**\n * Pure: decide what `mesh start --with-hub` does given the registry probe\n * and any already-built local images. Only a *refresh* needs the registry \u2014\n * already-built images run without it, so an expired/missing token degrades\n * to those (with the fixing command) instead of hard-failing a path that\n * works offline (MESH-2479).\n */\nexport function planWithHubRefresh(\n probeState: RegistryTokenState,\n builtVersion: string | undefined,\n): WithHubPlan {\n if (probeState !== \"expired\" && probeState !== \"missing\") return { action: \"refresh\" };\n if (builtVersion) {\n return {\n action: \"use-local\",\n version: builtVersion,\n warning:\n `CodeArtifact token is ${probeState} \u2014 using the already-built local Hub images (v${builtVersion}). ` +\n `To pick up a newer published Hub: ${REGISTRY_LOGIN_FIX}, then re-run mesh start --with-hub.`,\n };\n }\n return {\n action: \"fail\",\n message:\n probeState === \"expired\"\n ? \"Your CodeArtifact token is expired or rejected \u2014 the Hub build would fail minutes in with E401.\"\n : \"No CodeArtifact registry auth found in ~/.npmrc \u2014 the Hub builds from the published @mesh-tech/hub tarball.\",\n remediation: REGISTRY_LOGIN_FIX,\n };\n}\n\n/**\n * Ensure the two local hub images exist; build them from the tarball when\n * missing. Returns the hub version (used as the compose image tag).\n */\nexport async function ensureHubImages(): Promise<string> {\n const npmrc = npmrcPath();\n const { tarball, version: packageVersion } = await fetchTarball();\n const version = `${packageVersion}-${LOCAL_IMAGE_REV}`;\n const tags = HUB_IMAGES.map((name) => `${name}:${version}`);\n if (tags.every(imageExists)) {\n logInfo(`Local Hub images ready (v${version})`);\n return version;\n }\n\n const context = path.join(cacheDir(), `context-${version}`);\n fs.rmSync(context, { recursive: true, force: true });\n fs.mkdirSync(context, { recursive: true });\n execFileSync(\"tar\", [\"-xzf\", tarball, \"-C\", context, \"--strip-components\", \"1\"], {\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n\n const hubStackDir = path.join(findPackageRoot(), \"stack\", \"hub\");\n for (const [name, dockerfile] of [\n [\"mesh-local-hub-api\", \"Dockerfile.api\"],\n [\"mesh-local-hub-ui\", \"Dockerfile.ui\"],\n ] as const) {\n const tag = `${name}:${version}`;\n if (imageExists(tag)) continue;\n logInfo(`Building ${tag} from the published tarball\u2026`);\n execFileSync(\n \"docker\",\n [\n \"build\",\n \"-f\", path.join(hubStackDir, dockerfile),\n \"-t\", tag,\n \"--secret\", `id=npmrc,src=${npmrc}`,\n context,\n ],\n { stdio: [\"ignore\", \"inherit\", \"inherit\"], env: { ...process.env, DOCKER_BUILDKIT: \"1\" } },\n );\n logSuccess(`Built ${tag}`);\n }\n return version;\n}\n", "/**\n * mesh start / stop / status \u2014 the full-local Mesh platform.\n *\n * mesh start [--no-seed] Bring up the local platform (docker compose) and\n * seed tenant `local` / env `dev` on first boot.\n * mesh stop [--destroy] Stop the stack; --destroy also removes volumes\n * (resets databases and seeds).\n * mesh status [--json] Per-service health, endpoints, and ports.\n *\n * Everything here works with zero AWS credentials, zero VPN, and zero Pulumi\n * state \u2014 Docker is the only prerequisite.\n */\n\nimport { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { logError, logInfo, logSuccess, logWarn } from \"../../utils/log.js\";\nimport { MeshCliError } from \"../../utils/errors.js\";\nimport {\n COMPOSE_PROJECT,\n DEFAULT_HUB_PORT,\n ONE_SHOT_SERVICES,\n STACK_ENDPOINTS,\n compose,\n composeStreamed,\n crashedServices,\n ensureDockerAvailable,\n hubApiRunning,\n hubEndpoints,\n hubOverlayRunning,\n hubOverlayServices,\n hubPort,\n probeEndpoint,\n stackOwnedElsewhere,\n stackServices,\n type ServiceStatus,\n type StackEndpoint,\n} from \"./stack.js\";\nimport { probeRegistryToken, REGISTRY_LOGIN_FIX } from \"../../utils/auth-preflight.js\";\nimport {\n ensureHubAuthImage,\n ensureHubImages,\n hasRegistryAuth,\n localHubVersion,\n planWithHubRefresh,\n} from \"./hub-local.js\";\nimport { reconcileRegistryFromZitadel } from \"./auth-provision.js\";\nimport { LOCAL_AWS_CONFIG, localAwsEnv, seedLocalPlatform, verifyFabric } from \"./seed.js\";\nimport { LOGIN_CONTEXT, readHubAuth, seedZitadel, TEST_USERS } from \"./seed-zitadel.js\";\n\nconst WAIT_TIMEOUT_MS = 180_000;\nconst WAIT_POLL_MS = 3_000;\n\n/** The one crash message, so both wait loops stay on the same remediation. */\nfunction crashError(crashed: ServiceStatus[]): MeshCliError {\n return new MeshCliError(\n `Service(s) exited during startup: ${crashed.map((s) => s.name).join(\", \")}`,\n {\n remediation: {\n command: `docker compose -p ${COMPOSE_PROJECT} logs ${crashed[0]!.name}`,\n },\n },\n );\n}\n\n/** Injectable seams so tests can drive the wait loop without Docker. */\nexport interface WaitForStackIo {\n probe: (endpoint: StackEndpoint) => Promise<boolean>;\n services: () => ServiceStatus[];\n overlayServices: () => ReadonlySet<string>;\n}\n\nexport async function waitForStack(\n io: WaitForStackIo = {\n probe: probeEndpoint,\n services: stackServices,\n overlayServices: hubOverlayServices,\n },\n): Promise<void> {\n const deadline = Date.now() + WAIT_TIMEOUT_MS;\n let pending = STACK_ENDPOINTS.filter((e) => e.probe.kind !== \"none\");\n\n while (true) {\n const results = await Promise.all(pending.map((e) => io.probe(e)));\n const stillDown: StackEndpoint[] = [];\n for (let i = 0; i < pending.length; i++) {\n if (results[i]) {\n logSuccess(`${pending[i]!.label} is up (${pending[i]!.url})`);\n } else {\n stillDown.push(pending[i]!);\n }\n }\n pending = stillDown;\n\n // Surface hard failures on EVERY round, including the one that would end\n // the wait: not every container has a STACK_ENDPOINTS entry, so with all\n // probes answering first try an endpoint-less service (blackbox-exporter,\n // temporal-admin-tools) could exit during startup unseen.\n // The Hub overlay has not been brought up yet (that happens after the\n // seed, below), so its containers are excluded \u2014 an `exited` hub-api\n // here is a leftover from a previous run, not this run's crash.\n const crashed = crashedServices(io.services(), {\n overlayServices: io.overlayServices(),\n overlayStarted: false,\n });\n if (crashed.length > 0) throw crashError(crashed);\n\n if (pending.length === 0) break;\n\n if (Date.now() > deadline) {\n throw new MeshCliError(\n `Timed out waiting for: ${pending.map((e) => e.label).join(\", \")}`,\n { remediation: { command: \"mesh status\" } },\n );\n }\n logInfo(`Waiting for ${pending.map((e) => e.label).join(\", \")} \u2026`);\n await new Promise((resolve) => setTimeout(resolve, WAIT_POLL_MS));\n }\n}\n\nfunction printEndpoints(hubRunning: boolean): void {\n console.log(\"\");\n if (hubRunning) {\n // The Hub is the front door \u2014 the same operations dashboard customers\n // use against the hosted platform. Everything else is plumbing.\n console.log(chalk.bold.cyan(\"\u2605 Mesh Hub \u2014 your operations dashboard (start here)\"));\n console.log(` ${\"Hub UI\".padEnd(34)} ${chalk.bold.cyan(`http://localhost:${hubPort()}`)}`);\n console.log(\n ` ${\"\".padEnd(34)} ${chalk.dim(\"sign in: admin@local.mesh or dev@local.mesh / LocalDev1!\")}`,\n );\n console.log(` ${\"Hub API\".padEnd(34)} ${chalk.cyan(\"http://localhost:4568\")}`);\n console.log(\n ` ${\"\".padEnd(34)} ${chalk.dim(\"tenants, apps, workflows, logs, traces \u2014 local runs self-register here\")}`,\n );\n } else {\n logWarn(\"Hub is not running \u2014 it is the platform's front door. Enable it with:\");\n logInfo(` ${REGISTRY_LOGIN_FIX} (one-time, to build the Hub images \u2014 no AWS account needed)`);\n logInfo(\" mesh start (the Hub joins automatically)\");\n }\n console.log(\"\");\n console.log(chalk.bold(\"Local platform endpoints\"));\n for (const endpoint of STACK_ENDPOINTS) {\n console.log(` ${endpoint.label.padEnd(34)} ${chalk.cyan(endpoint.url)}`);\n if (endpoint.hint) {\n console.log(` ${\"\".padEnd(34)} ${chalk.dim(endpoint.hint)}`);\n }\n }\n console.log(\"\");\n console.log(chalk.bold(\"AWS SDK wiring (local fabric)\"));\n console.log(chalk.dim(\" Point any AWS SDK process at the local registry \u2014 no code changes:\"));\n for (const [key, value] of Object.entries(localAwsEnv())) {\n console.log(` export ${key}=${chalk.cyan(value)}`);\n }\n console.log(\"\");\n console.log(chalk.bold(\"Login\"));\n console.log(` mesh login ${LOGIN_CONTEXT}`);\n console.log(\n ` ${chalk.dim(`test users: ${TEST_USERS.map((u) => u.email).join(\", \")} (password: ${TEST_USERS[0]!.password})`)}`,\n );\n console.log(\"\");\n logInfo(\"Next: `mesh dev` in an apps repo wires services to this stack automatically.\");\n}\n\nexport function registerLocalCommands(program: Command): void {\n program\n .command(\"start\")\n .description(\"Start the full-local Mesh platform (Docker only \u2014 no AWS, no VPN)\")\n .option(\"--no-seed\", \"skip first-boot seeding (tenant registry, artifacts bucket)\")\n .option(\"--no-hub\", \"start without the Hub (API + UI)\")\n .option(\n \"--with-hub\",\n \"force-refresh the Hub to the latest published @mesh-tech/hub (the Hub is included by default when its images exist or registry auth is available)\",\n )\n .option(\n \"--takeover\",\n \"re-own a stack that another checkout started (may recreate shared containers with THIS checkout's config)\",\n false,\n )\n .action(async (opts: { seed: boolean; hub: boolean; withHub?: boolean; takeover: boolean }) => {\n ensureDockerAvailable();\n\n // The stack is machine-wide; a `start` from a checkout whose compose\n // config differs recreates shared containers out from under whatever\n // is running against them (another project's `mesh dev` session, a\n // Hub under development, \u2026). Tenant/app work never needs `start`\n // against an already-running stack \u2014 `mesh dev --local` deploys\n // tenant-scoped only.\n const foreign = stackOwnedElsewhere();\n if (foreign && !opts.takeover) {\n throw new MeshCliError(\n `The local platform is already running, started from a different checkout:\\n ${foreign}\\n` +\n `Re-running start from here may recreate shared containers with this checkout's config and disrupt work using the current stack.`,\n {\n remediation: {\n command:\n \"mesh status # inspect the running stack (apps deploy tenant-scoped via `mesh dev --local`)\\n\" +\n \" mesh start --takeover # intentionally re-own the stack from this checkout\",\n },\n },\n );\n }\n if (foreign && opts.takeover) {\n logWarn(`Taking over the running stack (previously driven from ${foreign}).`);\n }\n\n // The Hub is the platform's front door, so it's part of the default\n // stack: use already-built images when present; build from the\n // published tarball when registry auth allows; otherwise start\n // without it and say exactly how to enable it. --with-hub forces a\n // registry resolve (picks up newly published hub versions).\n let hubVersion: string | undefined;\n if (opts.hub) {\n if (opts.withHub) {\n // Auth preflight (MESH-2479): the tarball fetch + image build run\n // for minutes \u2014 verify the CodeArtifact token BEFORE that work.\n // Only a refresh needs the registry: with already-built images a\n // bad token degrades to them instead of failing an offline path.\n const probe = await probeRegistryToken();\n const plan = planWithHubRefresh(probe.state, localHubVersion());\n if (plan.action === \"fail\") {\n throw new MeshCliError(plan.message, { remediation: { command: plan.remediation } });\n }\n if (plan.action === \"use-local\") {\n logWarn(plan.warning);\n hubVersion = plan.version;\n } else {\n hubVersion = await ensureHubImages();\n }\n } else {\n hubVersion = localHubVersion();\n if (!hubVersion && hasRegistryAuth()) {\n const probe = await probeRegistryToken();\n if (probe.state === \"expired\") {\n // Keep `mesh start`'s Docker-only promise: degrade to a\n // hub-less stack, but say exactly how to get the Hub back.\n logWarn(\n `CodeArtifact token is expired \u2014 starting without the Hub. Fix: ${REGISTRY_LOGIN_FIX}, then: mesh start --with-hub`,\n );\n } else {\n try {\n hubVersion = await ensureHubImages();\n } catch (err) {\n logWarn(\n `Hub image build failed (${err instanceof Error ? err.message : err}) \u2014 starting without the Hub.`,\n );\n }\n }\n }\n }\n }\n\n logInfo(\"Starting the local Mesh platform (docker compose project: mesh-local)\u2026\");\n // Base stack first; the Hub joins AFTER seeding so its oauth2-proxy\n // gets the seeded client credentials and hub-api never caches a\n // pre-seed (empty) registry view.\n await composeStreamed([\"up\", \"-d\"]);\n // Deterministic cache bust for the bind-mounted observability configs:\n // `up -d` only recreates a container whose compose spec changed, and\n // Prometheus re-reads prometheus.yml on restart/SIGHUP only. A CLI\n // upgrade that edits observability/*.yml would otherwise leave a\n // running stack on the OLD scrape config (and blackbox on old modules)\n // \u2014 silently, since a misrouted probe just reports probe_success 0.\n compose([\"restart\", \"prometheus\", \"blackbox-exporter\"], { inherit: true });\n await waitForStack();\n let hubAuth = readHubAuth();\n if (opts.seed) {\n logInfo(\"Seeding local platform (tenant registry, artifacts bucket)\u2026\");\n await seedLocalPlatform();\n logInfo(\"Seeding Zitadel (Platform project, Mesh CLI app, Hub auth, test users)\u2026\");\n const zitadel = await seedZitadel(LOCAL_AWS_CONFIG);\n hubAuth = zitadel.hubAuth;\n // Zitadel is the auth source of truth \u2014 mirror every provisioned\n // app tenant/app into the registry so the Hub shows them even if\n // the app hasn't been run since it was provisioned.\n try {\n const reconciled = await reconcileRegistryFromZitadel();\n if (reconciled.tenants.length > 0) {\n logSuccess(\n `Hub registry reconciled from Zitadel: ${reconciled.tenants.length} app tenant(s) (${reconciled.tenants.join(\", \")}), ${reconciled.apps} app(s)`,\n );\n }\n } catch (err) {\n logWarn(`Registry reconcile skipped: ${err instanceof Error ? err.message : err}`);\n }\n logInfo(\"Verifying the local AWS fabric (8 KB Advanced-tier round-trip)\u2026\");\n await verifyFabric();\n } else {\n logWarn(\"Skipping seed (--no-seed).\");\n }\n if (hubVersion) {\n if (!hubAuth) {\n logWarn(\"Hub auth is not seeded yet (started with --no-seed?) \u2014 Hub sign-in needs one seeded run: mesh start\");\n }\n // The redirect URI for a non-default port is registered during\n // seeding (reconcileHubRedirectUris) \u2014 skipping the seed with a new\n // port reproduces the \"redirect_uri is missing in the client\n // configuration\" login failure.\n if (!opts.seed && hubPort() !== DEFAULT_HUB_PORT) {\n logWarn(\n `--no-seed with MESH_HUB_PORT=${hubPort()}: this port's redirect URI is registered during seeding \u2014 if Hub sign-in fails with \"redirect_uri is missing in the client configuration\", re-run without --no-seed.`,\n );\n }\n ensureHubAuthImage();\n const hubEnv: Record<string, string> = { MESH_HUB_VERSION: hubVersion };\n if (hubAuth) {\n hubEnv.MESH_HUB_OAUTH2_CLIENT_ID = hubAuth.clientId;\n hubEnv.MESH_HUB_OAUTH2_CLIENT_SECRET = hubAuth.clientSecret;\n hubEnv.MESH_HUB_OAUTH2_COOKIE_SECRET = hubAuth.cookieSecret;\n }\n await composeStreamed([\"up\", \"-d\"], { hub: true, env: hubEnv });\n if (opts.seed) {\n // Deterministic cache bust: hub-api holds its tenants view for 5\n // minutes and this run's seed/reconcile may have changed it.\n compose([\"restart\", \"hub-api\"], { hub: true, env: hubEnv });\n }\n // From here the overlay HAS been started, so an exited hub service is\n // a real crash again \u2014 same message, same remediation as the base\n // stack's. (Without this the loop would spin out its 60 attempts and\n // then claim the endpoint was up.)\n const overlayServices = hubOverlayServices();\n for (const endpoint of hubEndpoints()) {\n logInfo(`Waiting for ${endpoint.label}\u2026`);\n let up = await probeEndpoint(endpoint);\n for (let i = 0; i < 60 && !up; i++) {\n const crashed = crashedServices(stackServices(), {\n overlayServices,\n overlayStarted: true,\n });\n if (crashed.length > 0) throw crashError(crashed);\n await new Promise((resolve) => setTimeout(resolve, 2000));\n up = await probeEndpoint(endpoint);\n }\n if (!up) {\n throw new MeshCliError(`Timed out waiting for ${endpoint.label} (${endpoint.url}).`, {\n remediation: {\n command: `docker compose -p ${COMPOSE_PROJECT} logs ${endpoint.service}`,\n },\n });\n }\n logSuccess(`${endpoint.label} is up (${endpoint.url})`);\n }\n }\n logSuccess(\"Local Mesh platform is running.\");\n printEndpoints(!!hubVersion);\n });\n\n program\n .command(\"stop\")\n .description(\"Stop the local Mesh platform\")\n .option(\"--destroy\", \"also remove volumes (resets databases and seeds)\", false)\n .option(\"--force\", \"stop even when the stack was started from a different checkout\", false)\n .action((opts: { destroy: boolean; force: boolean }) => {\n ensureDockerAvailable();\n const foreign = stackOwnedElsewhere();\n if (foreign && !opts.force) {\n throw new MeshCliError(\n `The running local platform was started from a different checkout (${foreign}) \u2014 another project may be using it.`,\n { remediation: { command: \"mesh stop --force # stop it anyway\" } },\n );\n }\n const args = [\"down\"];\n if (opts.destroy) args.push(\"-v\");\n compose(args, { inherit: true, hub: true });\n logSuccess(opts.destroy ? \"Local platform stopped and volumes destroyed.\" : \"Local platform stopped.\");\n });\n\n program\n .command(\"status\")\n .description(\"Show local platform component health, endpoints, and ports\")\n .option(\"--json\", \"machine-readable output\", false)\n .action(async (opts: { json: boolean }) => {\n ensureDockerAvailable();\n const services = stackServices();\n if (services.length === 0) {\n if (opts.json) {\n console.log(JSON.stringify({ running: false, services: [], endpoints: [] }));\n return;\n }\n throw new MeshCliError(\"The local Mesh platform is not running.\", {\n remediation: { command: \"mesh start\" },\n });\n }\n\n // `status` never started anything, so \"is the Hub overlay part of this\n // run?\" can only be read off the containers: at least one overlay\n // service actually running. Everything Hub-related keys off that \u2014 an\n // overlay container left `exited` by a previous run (a Docker restart,\n // a laptop sleep) is \"not started\", not \"crashed\".\n const overlayServices = hubOverlayServices();\n const overlayStarted = hubOverlayRunning(services, overlayServices);\n const notStarted = (s: ServiceStatus) =>\n !overlayStarted && overlayServices.has(s.name) && s.state === \"exited\";\n\n // A *running* hub-api, not merely a hub-api container: a leftover\n // exited one from a previous run would otherwise make status probe Hub\n // endpoints that were never meant to be up and report them down.\n const hasHub = hubApiRunning(services);\n const endpoints = hasHub ? [...STACK_ENDPOINTS, ...hubEndpoints()] : STACK_ENDPOINTS;\n const probes = await Promise.all(\n endpoints.map(async (endpoint) => ({\n service: endpoint.service,\n label: endpoint.label,\n url: endpoint.url,\n up: await probeEndpoint(endpoint),\n })),\n );\n\n // The P0 gate: with the fabric up, the 8 KB Advanced-tier round-trip\n // must pass on every status check, not just at seed time.\n let fabric: { ok: boolean; error?: string } | null = null;\n if (probes.find((p) => p.service === \"ministack\")?.up) {\n try {\n await verifyFabric();\n fabric = { ok: true };\n } catch (err) {\n fabric = { ok: false, error: err instanceof Error ? err.message : String(err) };\n }\n }\n\n if (opts.json) {\n console.log(\n JSON.stringify({\n running: true,\n services,\n endpoints: probes,\n fabric,\n awsEnv: localAwsEnv(),\n }),\n );\n if (fabric && !fabric.ok) process.exitCode = 1;\n return;\n }\n\n console.log(chalk.bold(\"Containers\"));\n for (const service of services) {\n const ok =\n service.state === \"running\" &&\n (service.health === undefined || service.health === \"healthy\");\n const oneShotDone = ONE_SHOT_SERVICES.has(service.name) && service.state === \"exited\";\n const idle = notStarted(service);\n const icon =\n ok || oneShotDone ? chalk.green(\"\u25CF\") : idle ? chalk.dim(\"\u25CB\") : chalk.red(\"\u25CF\");\n const health = service.health ? ` (${service.health})` : \"\";\n const note = idle ? chalk.dim(\" (Hub not started this run)\") : \"\";\n console.log(` ${icon} ${service.name.padEnd(22)} ${service.state}${health}${note}`);\n }\n console.log(\"\");\n console.log(chalk.bold(\"Endpoints\"));\n for (const probe of probes) {\n const icon = probe.up ? chalk.green(\"\u25CF\") : chalk.red(\"\u25CF\");\n console.log(` ${icon} ${probe.label.padEnd(34)} ${chalk.cyan(probe.url)}`);\n }\n if (fabric) {\n const icon = fabric.ok ? chalk.green(\"\u25CF\") : chalk.red(\"\u25CF\");\n const detail = fabric.ok ? \"8 KB Advanced-tier round-trip OK\" : fabric.error;\n console.log(` ${icon} ${\"AWS fabric check\".padEnd(34)} ${chalk.dim(detail ?? \"\")}`);\n }\n\n const down = probes.filter((p) => !p.up);\n const crashed = crashedServices(services, { overlayServices, overlayStarted });\n if (fabric && !fabric.ok) process.exitCode = 1;\n if (down.length > 0 || crashed.length > 0) {\n console.log(\"\");\n logError(\n `${down.length + crashed.length} component(s) unhealthy \u2014 inspect with: docker compose -p mesh-local logs <service>`,\n );\n process.exitCode = 1;\n }\n });\n}\n", "/**\n * mesh secrets exec - Execute command with secrets from AWS Secrets Manager\n *\n * Fetches a JSON secret from Secrets Manager and injects all key-value pairs\n * as environment variables before running the specified command.\n *\n * Usage:\n * mesh secrets exec --secret=<name-or-arn> [--db-host=<host>] -- <command>\n *\n * Options:\n * --db-host=<host> Rewrite DATABASE_URL host (for dev mode tunneling)\n *\n * Example:\n * mesh secrets exec --secret=mesh/encore/dev/rdc/db-credentials --db-host=localhost -- pnpm dev\n */\n\nimport { spawn } from \"child_process\";\nimport {\n SecretsManagerClient,\n GetSecretValueCommand,\n} from \"@aws-sdk/client-secrets-manager\";\n\n// Simple logging helpers\nfunction logInfo(msg: string): void {\n console.log(`\\u001b[36m\u2139\\u001b[0m ${msg}`);\n}\n\nfunction logSuccess(msg: string): void {\n console.log(`\\u001b[32m\u2713\\u001b[0m ${msg}`);\n}\n\nfunction logError(msg: string): void {\n console.error(`\\u001b[31m\u2717\\u001b[0m ${msg}`);\n}\n\ninterface Options {\n secret?: string;\n dbHost?: string;\n}\n\nfunction parseArgs(args: string[]): { options: Options; commandArgs: string[] } {\n const options: Options = {};\n let commandArgs: string[] = [];\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i]!;\n\n if (arg === \"--\") {\n commandArgs = args.slice(i + 1);\n break;\n }\n\n if (arg.startsWith(\"--secret=\")) {\n options.secret = arg.substring(\"--secret=\".length);\n } else if (arg === \"--secret\" && args[i + 1]) {\n options.secret = args[++i];\n } else if (arg.startsWith(\"--db-host=\")) {\n options.dbHost = arg.substring(\"--db-host=\".length);\n } else if (arg === \"--db-host\" && args[i + 1]) {\n options.dbHost = args[++i];\n }\n }\n\n return { options, commandArgs };\n}\n\nasync function fetchSecret(\n client: SecretsManagerClient,\n secretId: string\n): Promise<Record<string, string>> {\n const response = await client.send(\n new GetSecretValueCommand({ SecretId: secretId })\n );\n\n if (!response.SecretString) {\n throw new Error(\"Secret has no string value\");\n }\n\n try {\n return JSON.parse(response.SecretString) as Record<string, string>;\n } catch {\n throw new Error(\"Secret is not valid JSON\");\n }\n}\n\n/**\n * Rewrite the host in a DATABASE_URL\n * Useful for dev mode where we tunnel to the database via localhost\n */\nfunction rewriteDatabaseHost(databaseUrl: string, newHost: string): string {\n try {\n const url = new URL(databaseUrl);\n const originalHost = url.host;\n url.hostname = newHost;\n // Keep the original port if the new host doesn't include one\n if (!newHost.includes(\":\")) {\n url.port = url.port || \"5432\";\n }\n logInfo(`Rewrote DATABASE_URL host: ${originalHost} \u2192 ${url.host}`);\n return url.toString();\n } catch {\n logError(`Failed to parse DATABASE_URL for host rewrite`);\n return databaseUrl;\n }\n}\n\nexport async function execCommand(args: string[]): Promise<void> {\n const { options, commandArgs } = parseArgs(args);\n\n if (!options.secret || commandArgs.length === 0) {\n logError(\"Usage: mesh secrets exec --secret=<name-or-arn> [options] -- <command>\");\n logInfo(\"\");\n logInfo(\"Options:\");\n logInfo(\" --secret=<name-or-arn> Secret name or ARN in Secrets Manager\");\n logInfo(\" --db-host=<host> Rewrite DATABASE_URL host (for dev tunneling)\");\n logInfo(\"\");\n logInfo(\"Examples:\");\n logInfo(\n \" mesh secrets exec --secret=mesh/tenant/stage/app/secret -- pnpm dev\"\n );\n logInfo(\n \" mesh secrets exec --secret=mesh/tenant/stage/app/db --db-host=localhost -- pnpm dev\"\n );\n process.exit(1);\n }\n\n const secretsManager = new SecretsManagerClient({});\n\n logInfo(`Fetching secret: ${options.secret}`);\n\n let secretValues: Record<string, string>;\n try {\n secretValues = await fetchSecret(secretsManager, options.secret);\n } catch (error) {\n logError(`Failed to fetch secret: ${error}`);\n process.exit(1);\n }\n\n const envKeys = Object.keys(secretValues);\n logSuccess(`Loaded ${envKeys.length} environment variable(s) from secret`);\n\n // Rewrite DATABASE_URL host for dev mode tunneling\n if (options.dbHost && secretValues.DATABASE_URL) {\n secretValues.DATABASE_URL = rewriteDatabaseHost(\n secretValues.DATABASE_URL,\n options.dbHost\n );\n }\n\n // Build environment with secret values injected\n const env: NodeJS.ProcessEnv = {\n ...process.env,\n ...secretValues,\n };\n\n const [cmd, ...cmdArgs] = commandArgs;\n logInfo(`Running: ${commandArgs.join(\" \")}`);\n console.log(\"\");\n\n const child = spawn(cmd!, cmdArgs, { stdio: \"inherit\", env });\n\n child.on(\"exit\", (code: number | null) => {\n process.exit(code ?? 0);\n });\n\n child.on(\"error\", (error: Error) => {\n logError(`Failed to start command: ${error.message}`);\n process.exit(1);\n });\n}\n", "/**\n * mesh secrets set \u2014 Set credentials for an external service.\n *\n * Reads the credential field schema from SSM (written by ExternalService),\n * prompts interactively for each field, and writes to Secrets Manager.\n *\n * Supports nested credential schemas: groups render as sections with headers,\n * and the stored JSON mirrors the nested structure exactly.\n *\n * Usage:\n * mesh secrets set external/symitar # single-instance\n * mesh secrets set external/symitar --key=12345 # multi-instance (specific key)\n * mesh secrets set external/symitar --all # include optional fields\n * mesh secrets set external/symitar --non-interactive --json='{\"baseUrl\":\"...\"}'\n *\n * The command detects tenant/stage from Pulumi config in the current directory.\n */\n\nimport {\n SSMClient,\n GetParametersByPathCommand,\n} from \"@aws-sdk/client-ssm\";\nimport {\n SecretsManagerClient,\n GetSecretValueCommand,\n PutSecretValueCommand,\n CreateSecretCommand,\n} from \"@aws-sdk/client-secrets-manager\";\nimport input from \"@inquirer/input\";\nimport password from \"@inquirer/password\";\nimport { detectContext } from \"../../utils/context.js\";\nimport { logInfo, logSuccess, logError } from \"../../utils/log.js\";\nimport { resolveStackOption } from \"../../utils/stack-flag.js\";\nimport { findAppRoot, readStackConfig } from \"../../utils/pulumi.js\";\nimport { resolveAwsCredentials } from \"../../utils/aws-auth.js\";\n\n/**\n * Ensure AWS credentials are available for the SSM/Secrets Manager calls. If the\n * environment has none, assume the stack's `mesh:deployerRole` \u2014 which triggers\n * `mesh login` automatically when there's no active session. No-op when\n * credentials are already present or the stack/role can't be resolved.\n *\n * The stack is the locally-detected stage (from the `Pulumi.<stage>.yaml`\n * filename) \u2014 NOT `pulumi stack --show-name`, which would itself need creds to\n * read the backend (the chicken-and-egg this is meant to avoid).\n */\nasync function ensureAwsCredentialsForStack(stack: string | undefined): Promise<void> {\n if (process.env.AWS_ACCESS_KEY_ID || process.env.AWS_SESSION_TOKEN) return;\n if (!stack) return;\n const appRoot = findAppRoot(process.cwd());\n if (!appRoot) return;\n const roleArn = readStackConfig(appRoot, stack, \"mesh:deployerRole\");\n if (!roleArn) return;\n const resolved = await resolveAwsCredentials(roleArn, appRoot, stack);\n if (resolved) {\n Object.assign(process.env, resolved.env);\n delete process.env.AWS_PROFILE;\n }\n}\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/** Leaf field in the credential schema */\ninterface SchemaField {\n type: \"field\";\n name: string;\n description: string;\n secret: boolean;\n optional: boolean;\n}\n\n/** Group of fields (may nest further) */\ninterface SchemaGroup {\n type: \"group\";\n name: string;\n description: string;\n fields: Record<string, SchemaField | SchemaGroup>;\n}\n\n/** A schema entry is either a leaf field or a nested group */\ntype SchemaEntry = SchemaField | SchemaGroup;\n\ninterface CredentialSchema {\n fields: Record<string, SchemaEntry>;\n keyedBy: string | null;\n}\n\ninterface ExternalServiceMeta {\n name: string;\n type: string;\n description: string;\n secretPrefix: string;\n}\n\n// =============================================================================\n// Schema compatibility\n// =============================================================================\n\n/**\n * Normalize a schema entry from SSM. Handles both:\n * - New format: `{ type: \"field\"|\"group\", ... }`\n * - Legacy format: `{ name, description, secret, optional }` (no type marker)\n */\nfunction normalizeEntry(raw: Record<string, unknown>): SchemaEntry {\n if (raw.type === \"group\" && raw.fields) {\n return {\n type: \"group\",\n name: (raw.name as string) ?? \"\",\n description: (raw.description as string) ?? \"\",\n fields: normalizeFields(raw.fields as Record<string, Record<string, unknown>>),\n };\n }\n\n // Leaf field (explicit type: \"field\" or legacy without type)\n return {\n type: \"field\",\n name: (raw.name as string) ?? \"\",\n description: (raw.description as string) ?? \"\",\n secret: (raw.secret as boolean) ?? false,\n optional: (raw.optional as boolean) ?? false,\n };\n}\n\nfunction normalizeFields(\n raw: Record<string, Record<string, unknown>>,\n): Record<string, SchemaEntry> {\n return Object.fromEntries(\n Object.entries(raw).map(([key, value]) => [key, normalizeEntry(value)]),\n );\n}\n\n// =============================================================================\n// SSM discovery\n// =============================================================================\n\nasync function discoverExternalServices(\n ssmClient: SSMClient,\n tenant: string,\n platformEnv: string,\n): Promise<Map<string, { meta: ExternalServiceMeta; schema?: CredentialSchema }>> {\n const services = new Map<string, { meta: ExternalServiceMeta; schema?: CredentialSchema }>();\n\n const basePath = `/mesh-platform/${tenant}/${platformEnv}`;\n let nextToken: string | undefined;\n\n do {\n const response = await ssmClient.send(\n new GetParametersByPathCommand({\n Path: basePath,\n Recursive: true,\n NextToken: nextToken,\n }),\n );\n\n for (const param of response.Parameters ?? []) {\n if (!param.Name || !param.Value) continue;\n\n // Match: .../external-services/{name}/meta\n const metaMatch = param.Name.match(\n /\\/external-services\\/([^/]+)\\/meta$/,\n );\n if (metaMatch?.[1]) {\n const serviceName = metaMatch[1];\n const meta = JSON.parse(param.Value) as ExternalServiceMeta;\n const existing = services.get(serviceName);\n services.set(serviceName, { ...existing, meta });\n }\n\n // Match: .../external-services/{name}/credentials\n const credMatch = param.Name.match(\n /\\/external-services\\/([^/]+)\\/credentials$/,\n );\n if (credMatch?.[1]) {\n const serviceName = credMatch[1];\n const raw = JSON.parse(param.Value) as {\n fields: Record<string, Record<string, unknown>>;\n keyedBy: string | null;\n };\n const schema: CredentialSchema = {\n fields: normalizeFields(raw.fields),\n keyedBy: raw.keyedBy,\n };\n const existing = services.get(serviceName);\n if (existing) {\n existing.schema = schema;\n } else {\n services.set(serviceName, { meta: {} as ExternalServiceMeta, schema });\n }\n }\n }\n\n nextToken = response.NextToken;\n } while (nextToken);\n\n return services;\n}\n\n// =============================================================================\n// Nested value helpers\n// =============================================================================\n\n// =============================================================================\n// Interactive prompts (recursive)\n// =============================================================================\n\n/**\n * Recursively prompt for all fields in the schema.\n * Groups render as section headers; leaf fields get input prompts.\n */\nasync function promptFields(\n fields: Record<string, SchemaEntry>,\n existing: Record<string, unknown>,\n result: Record<string, unknown>,\n opts: { all: boolean },\n depth: number = 0,\n): Promise<void> {\n for (const [fieldKey, entry] of Object.entries(fields)) {\n if (entry.type === \"group\") {\n // Section header\n const indent = \" \".repeat(depth);\n console.error(\"\");\n console.error(`${indent}\u2500\u2500 ${entry.name} \u2500\u2500`);\n\n // Ensure nested object exists\n const existingGroup = (existing[fieldKey] ?? {}) as Record<string, unknown>;\n const resultGroup: Record<string, unknown> = {};\n\n await promptFields(entry.fields, existingGroup, resultGroup, opts, depth + 1);\n\n result[fieldKey] = resultGroup;\n } else {\n // Leaf field\n if (entry.optional && !opts.all) {\n const existingVal = existing[fieldKey];\n if (existingVal !== undefined && existingVal !== \"\") {\n result[fieldKey] = existingVal;\n }\n continue;\n }\n\n const existingVal = existing[fieldKey] as string | undefined;\n const hasExisting = !!existingVal && existingVal !== \"\";\n\n const message = entry.description\n ? `${entry.name} (${entry.description})`\n : entry.name;\n\n const label = entry.optional ? `${message} [optional]` : message;\n\n let value: string;\n\n if (entry.secret) {\n value = await password({ message: label, mask: \"*\" });\n // Keep existing if user just pressed Enter\n if (!value && hasExisting) {\n value = existingVal!;\n }\n } else {\n value = await input({\n message: label,\n default: hasExisting ? existingVal : undefined,\n });\n }\n\n result[fieldKey] = value || (hasExisting ? existingVal! : \"\");\n }\n }\n}\n\n// =============================================================================\n// Summary display (recursive)\n// =============================================================================\n\nfunction displaySummary(\n fields: Record<string, SchemaEntry>,\n values: Record<string, unknown>,\n depth: number = 0,\n): void {\n const indent = \" \".repeat(depth);\n\n for (const [key, entry] of Object.entries(fields)) {\n if (entry.type === \"group\") {\n console.error(`${indent}${entry.name}:`);\n const group = (values[key] ?? {}) as Record<string, unknown>;\n displaySummary(entry.fields, group, depth + 1);\n } else {\n const val = values[key];\n if (!val) continue;\n const display = entry.secret ? \"********\" : String(val);\n console.error(`${indent}${entry.name}: ${display}`);\n }\n }\n}\n\n// =============================================================================\n// Main command\n// =============================================================================\n\nexport async function setCommand(\n servicePath: string | undefined,\n opts: {\n key?: string;\n all?: boolean;\n json?: string;\n stack?: string;\n stage?: string;\n region?: string;\n },\n): Promise<void> {\n const stackOpt = resolveStackOption(opts);\n const context = detectContext(stackOpt);\n const region = opts.region ?? process.env.AWS_REGION ?? \"us-east-2\";\n\n // Ensure AWS credentials: if none in the environment, assume the stack's\n // deployer role \u2014 which triggers `mesh login` automatically when there's no\n // active session (instead of failing with a credentials error).\n await ensureAwsCredentialsForStack(stackOpt ?? context.stage);\n\n const ssmClient = new SSMClient({ region });\n const smClient = new SecretsManagerClient({ region });\n\n // Discover all external services\n const services = await discoverExternalServices(\n ssmClient,\n context.tenant,\n context.platformEnv,\n );\n\n if (services.size === 0) {\n logError(\n \"No external services found. Deploy an ExternalService first:\\n\" +\n \" new mesh.apps.ExternalService(\\\"symitar\\\", { env, credentials: { ... } })\",\n );\n process.exit(1);\n }\n\n // Parse service name from path (e.g., \"external/symitar\" \u2192 \"symitar\")\n let serviceName: string | undefined;\n if (servicePath) {\n serviceName = servicePath.replace(/^external\\//, \"\");\n }\n\n // If no service specified or not found, list available\n if (!serviceName || !services.has(serviceName)) {\n if (serviceName) {\n logError(`External service \"${serviceName}\" not found.`);\n }\n console.error(\"\\nAvailable external services:\");\n for (const [name, svc] of services) {\n const desc = svc.meta?.description ? ` \u2014 ${svc.meta.description}` : \"\";\n const type = svc.meta?.type ? ` (${svc.meta.type})` : \"\";\n console.error(` ${name}${type}${desc}`);\n }\n console.error(`\\nUsage: mesh secrets set external/<name>`);\n process.exit(serviceName ? 1 : 0);\n }\n\n const svc = services.get(serviceName)!;\n const schema = svc.schema;\n\n if (!schema) {\n logError(`No credential schema found for \"${serviceName}\".`);\n process.exit(1);\n }\n\n // Determine secret path\n const secretPrefix = svc.meta.secretPrefix;\n const secretId = opts.key ? `${secretPrefix}/${opts.key}` : secretPrefix;\n\n if (schema.keyedBy && !opts.key) {\n logError(\n `\"${serviceName}\" is multi-instance (keyed by ${schema.keyedBy}). ` +\n `Specify an instance:\\n mesh secrets set external/${serviceName} --key=<${schema.keyedBy}>`,\n );\n process.exit(1);\n }\n\n // Read existing values (if any)\n let existing: Record<string, unknown> = {};\n try {\n const response = await smClient.send(\n new GetSecretValueCommand({ SecretId: secretId }),\n );\n if (response.SecretString) {\n existing = JSON.parse(response.SecretString);\n }\n } catch (err: any) {\n if (!isResourceNotFound(err)) {\n throw err;\n }\n // Secret doesn't exist yet (multi-instance key) \u2014 will create\n }\n\n // Non-interactive mode: JSON input (deep-merged)\n if (opts.json) {\n let values: Record<string, unknown>;\n try {\n values = JSON.parse(opts.json);\n } catch {\n logError(\"Invalid JSON input. Provide valid JSON, e.g.: --json='{\\\"key\\\": \\\"value\\\"}'\");\n return;\n }\n const merged = deepMerge(existing, values);\n await writeSecret(smClient, secretId, merged, svc.meta);\n await writeConfigMirror(smClient, secretId, schema, merged, svc.meta);\n logSuccess(`Credentials written to ${secretId}`);\n return;\n }\n\n // Interactive mode\n console.error(\"\");\n logInfo(`Setting credentials for: ${svc.meta.description || serviceName}`);\n if (opts.key) {\n logInfo(`Instance: ${opts.key}`);\n }\n logInfo(`Secret: ${secretId}`);\n\n const values: Record<string, unknown> = {};\n await promptFields(schema.fields, existing, values, { all: !!opts.all });\n\n console.error(\"\");\n\n // Merge and write\n const merged = deepMerge(existing, values);\n await writeSecret(smClient, secretId, merged, svc.meta);\n await writeConfigMirror(smClient, secretId, schema, merged, svc.meta);\n\n logSuccess(`Credentials written to ${secretId}`);\n\n // Show summary\n console.error(\"\\nStored fields:\");\n displaySummary(schema.fields, merged);\n console.error(\"\");\n}\n\n// =============================================================================\n// Helpers\n// =============================================================================\n\nfunction isResourceNotFound(err: unknown): boolean {\n const e = err as {\n name?: string;\n __type?: string;\n Code?: string;\n code?: string;\n message?: string;\n };\n\n return (\n e?.name === \"ResourceNotFoundException\" ||\n e?.__type === \"ResourceNotFoundException\" ||\n e?.Code === \"ResourceNotFoundException\" ||\n e?.code === \"ResourceNotFoundException\" ||\n (typeof e?.message === \"string\" && e.message.includes(\"ResourceNotFoundException\"))\n );\n}\n\n/** Deep merge two objects. Source values overwrite target at leaf level. */\nfunction deepMerge(\n target: Record<string, unknown>,\n source: Record<string, unknown>,\n): Record<string, unknown> {\n const result = { ...target };\n for (const [key, value] of Object.entries(source)) {\n if (\n value !== null &&\n typeof value === \"object\" &&\n !Array.isArray(value) &&\n typeof result[key] === \"object\" &&\n result[key] !== null &&\n !Array.isArray(result[key])\n ) {\n result[key] = deepMerge(\n result[key] as Record<string, unknown>,\n value as Record<string, unknown>,\n );\n } else {\n result[key] = value;\n }\n }\n return result;\n}\n\nasync function writeSecret(\n client: SecretsManagerClient,\n secretId: string,\n values: Record<string, unknown>,\n meta: ExternalServiceMeta,\n): Promise<void> {\n const secretString = JSON.stringify(values);\n\n try {\n await client.send(\n new PutSecretValueCommand({\n SecretId: secretId,\n SecretString: secretString,\n }),\n );\n } catch (err: any) {\n if (isResourceNotFound(err)) {\n // Multi-instance: create the per-key secret\n await client.send(\n new CreateSecretCommand({\n Name: secretId,\n Description: `External service credentials for ${meta.name} (instance)`,\n SecretString: secretString,\n Tags: [\n { Key: \"mesh:type\", Value: \"external-service\" },\n { Key: \"mesh:service\", Value: meta.name },\n ],\n }),\n );\n } else {\n throw err;\n }\n }\n}\n\n/**\n * Extract non-secret fields from merged values based on the credential schema.\n * Walks groups recursively, preserving structure.\n */\nfunction extractNonSecretFields(\n fields: Record<string, SchemaEntry>,\n values: Record<string, unknown>,\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [key, entry] of Object.entries(fields)) {\n if (entry.type === \"group\") {\n const groupValues = (values[key] ?? {}) as Record<string, unknown>;\n const filtered = extractNonSecretFields(entry.fields, groupValues);\n if (Object.keys(filtered).length > 0) {\n result[key] = filtered;\n }\n } else if (!entry.secret && values[key] !== undefined) {\n result[key] = values[key];\n }\n }\n return result;\n}\n\nasync function writeConfigMirror(\n client: SecretsManagerClient,\n secretId: string,\n schema: CredentialSchema,\n merged: Record<string, unknown>,\n meta: ExternalServiceMeta,\n): Promise<void> {\n const configId = `${secretId}/.config`;\n const configValues = extractNonSecretFields(schema.fields, merged);\n const secretString = JSON.stringify(configValues);\n try {\n try {\n await client.send(\n new PutSecretValueCommand({\n SecretId: configId,\n SecretString: secretString,\n }),\n );\n } catch (err) {\n if (isResourceNotFound(err)) {\n await client.send(\n new CreateSecretCommand({\n Name: configId,\n Description: `Non-secret credential fields for ${meta.name} (Hub display)`,\n SecretString: secretString,\n Tags: [{ Key: \"mesh:type\", Value: \"external-service-config\" }],\n }),\n );\n } else {\n throw err;\n }\n }\n } catch (err) {\n // Non-fatal: log warning but don't fail the main write\n logInfo(`Warning: failed to write .config mirror to ${configId}: ${err}`);\n }\n}\n", "/**\n * mesh secrets migrate-config \u2014 Backfill .config mirror secrets.\n *\n * For each external service discovered in SSM, reads the main secret from\n * Secrets Manager, extracts non-secret fields using the credential schema,\n * and writes them to {secretPrefix}/.config.\n *\n * Idempotent: skips services where .config already exists (unless --force).\n * Handles multi-instance services by iterating instance keys.\n *\n * Usage:\n * mesh secrets migrate-config # migrate all services\n * mesh secrets migrate-config --force # overwrite existing .config\n * mesh secrets migrate-config --dry-run # show what would be written\n * mesh secrets migrate-config --stage dev # override stage detection\n */\n\nimport {\n SSMClient,\n GetParametersByPathCommand,\n} from \"@aws-sdk/client-ssm\";\nimport {\n SecretsManagerClient,\n GetSecretValueCommand,\n PutSecretValueCommand,\n CreateSecretCommand,\n ListSecretsCommand,\n} from \"@aws-sdk/client-secrets-manager\";\nimport { detectContext } from \"../../utils/context.js\";\nimport { logInfo, logSuccess, logError } from \"../../utils/log.js\";\nimport { resolveStackOption } from \"../../utils/stack-flag.js\";\n\n// =============================================================================\n// Types (mirrored from set.ts \u2014 shared schema types)\n// =============================================================================\n\ninterface SchemaField {\n type: \"field\";\n name: string;\n description: string;\n secret: boolean;\n optional: boolean;\n}\n\ninterface SchemaGroup {\n type: \"group\";\n name: string;\n description: string;\n fields: Record<string, SchemaField | SchemaGroup>;\n}\n\ntype SchemaEntry = SchemaField | SchemaGroup;\n\ninterface CredentialSchema {\n fields: Record<string, SchemaEntry>;\n keyedBy: string | null;\n}\n\ninterface ExternalServiceMeta {\n name: string;\n type: string;\n description: string;\n secretPrefix: string;\n}\n\n// =============================================================================\n// Schema normalization (same as set.ts)\n// =============================================================================\n\nfunction normalizeEntry(raw: Record<string, unknown>): SchemaEntry {\n if (raw.type === \"group\" && raw.fields) {\n return {\n type: \"group\",\n name: (raw.name as string) ?? \"\",\n description: (raw.description as string) ?? \"\",\n fields: normalizeFields(raw.fields as Record<string, Record<string, unknown>>),\n };\n }\n return {\n type: \"field\",\n name: (raw.name as string) ?? \"\",\n description: (raw.description as string) ?? \"\",\n secret: (raw.secret as boolean) ?? false,\n optional: (raw.optional as boolean) ?? false,\n };\n}\n\nfunction normalizeFields(\n raw: Record<string, Record<string, unknown>>,\n): Record<string, SchemaEntry> {\n return Object.fromEntries(\n Object.entries(raw).map(([key, value]) => [key, normalizeEntry(value)]),\n );\n}\n\n// =============================================================================\n// Discovery (same logic as set.ts)\n// =============================================================================\n\nasync function discoverExternalServices(\n ssmClient: SSMClient,\n tenant: string,\n platformEnv: string,\n): Promise<Map<string, { meta: ExternalServiceMeta; schema?: CredentialSchema }>> {\n const services = new Map<string, { meta: ExternalServiceMeta; schema?: CredentialSchema }>();\n const basePath = `/mesh-platform/${tenant}/${platformEnv}`;\n let nextToken: string | undefined;\n\n do {\n const response = await ssmClient.send(\n new GetParametersByPathCommand({\n Path: basePath,\n Recursive: true,\n NextToken: nextToken,\n }),\n );\n\n for (const param of response.Parameters ?? []) {\n if (!param.Name || !param.Value) continue;\n\n const metaMatch = param.Name.match(/\\/external-services\\/([^/]+)\\/meta$/);\n if (metaMatch?.[1]) {\n const serviceName = metaMatch[1];\n const meta = JSON.parse(param.Value) as ExternalServiceMeta;\n const existing = services.get(serviceName);\n services.set(serviceName, { ...existing, meta });\n }\n\n const credMatch = param.Name.match(/\\/external-services\\/([^/]+)\\/credentials$/);\n if (credMatch?.[1]) {\n const serviceName = credMatch[1];\n const raw = JSON.parse(param.Value) as {\n fields: Record<string, Record<string, unknown>>;\n keyedBy: string | null;\n };\n const schema: CredentialSchema = {\n fields: normalizeFields(raw.fields),\n keyedBy: raw.keyedBy,\n };\n const existing = services.get(serviceName);\n if (existing) {\n existing.schema = schema;\n } else {\n services.set(serviceName, { meta: {} as ExternalServiceMeta, schema });\n }\n }\n }\n\n nextToken = response.NextToken;\n } while (nextToken);\n\n return services;\n}\n\n// =============================================================================\n// Non-secret field extraction\n// =============================================================================\n\nfunction extractNonSecretFields(\n fields: Record<string, SchemaEntry>,\n values: Record<string, unknown>,\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [key, entry] of Object.entries(fields)) {\n if (entry.type === \"group\") {\n const groupValues = (values[key] ?? {}) as Record<string, unknown>;\n const filtered = extractNonSecretFields(entry.fields, groupValues);\n if (Object.keys(filtered).length > 0) {\n result[key] = filtered;\n }\n } else if (!entry.secret && values[key] !== undefined) {\n result[key] = values[key];\n }\n }\n return result;\n}\n\n// =============================================================================\n// SM helpers\n// =============================================================================\n\nfunction isResourceNotFound(err: unknown): boolean {\n const e = err as {\n name?: string;\n __type?: string;\n Code?: string;\n code?: string;\n message?: string;\n };\n\n return (\n e?.name === \"ResourceNotFoundException\" ||\n e?.__type === \"ResourceNotFoundException\" ||\n e?.Code === \"ResourceNotFoundException\" ||\n e?.code === \"ResourceNotFoundException\" ||\n (typeof e?.message === \"string\" && e.message.includes(\"ResourceNotFoundException\"))\n );\n}\n\nasync function readSecret(\n client: SecretsManagerClient,\n secretId: string,\n): Promise<Record<string, unknown> | null> {\n try {\n const res = await client.send(new GetSecretValueCommand({ SecretId: secretId }));\n return res.SecretString ? JSON.parse(res.SecretString) : null;\n } catch (err) {\n if (isResourceNotFound(err)) return null;\n throw err;\n }\n}\n\nasync function writeSecret(\n client: SecretsManagerClient,\n secretId: string,\n values: Record<string, unknown>,\n description: string,\n): Promise<void> {\n const secretString = JSON.stringify(values);\n try {\n await client.send(new PutSecretValueCommand({ SecretId: secretId, SecretString: secretString }));\n } catch (err) {\n if (isResourceNotFound(err)) {\n await client.send(new CreateSecretCommand({\n Name: secretId,\n Description: description,\n SecretString: secretString,\n Tags: [{ Key: \"mesh:type\", Value: \"external-service-config\" }],\n }));\n } else {\n throw err;\n }\n }\n}\n\nasync function secretExists(\n client: SecretsManagerClient,\n secretId: string,\n): Promise<boolean> {\n try {\n await client.send(new GetSecretValueCommand({ SecretId: secretId }));\n return true;\n } catch (err) {\n if (isResourceNotFound(err)) return false;\n throw err;\n }\n}\n\nasync function listInstanceKeys(\n client: SecretsManagerClient,\n secretPrefix: string,\n): Promise<string[]> {\n const prefix = `${secretPrefix}/`;\n const keys: string[] = [];\n let nextToken: string | undefined;\n\n do {\n const response = await client.send(\n new ListSecretsCommand({\n Filters: [{ Key: \"name\", Values: [prefix] }],\n NextToken: nextToken,\n }),\n );\n for (const secret of response.SecretList ?? []) {\n if (secret.Name?.startsWith(prefix)) {\n const key = secret.Name.slice(prefix.length);\n if (key && !key.includes(\"/\") && !key.endsWith(\".config\")) {\n keys.push(key);\n }\n }\n }\n nextToken = response.NextToken;\n } while (nextToken);\n\n return keys;\n}\n\n// =============================================================================\n// Migration logic\n// =============================================================================\n\nasync function migrateService(\n smClient: SecretsManagerClient,\n meta: ExternalServiceMeta,\n schema: CredentialSchema,\n opts: { force: boolean; dryRun: boolean },\n): Promise<{ migrated: number; skipped: number; errors: number }> {\n let migrated = 0;\n let skipped = 0;\n let errors = 0;\n\n async function migrateOneSecret(secretId: string, label: string): Promise<void> {\n const configId = `${secretId}/.config`;\n\n try {\n // Check if .config already exists\n if (!opts.force) {\n const exists = await secretExists(smClient, configId);\n if (exists) {\n logInfo(` SKIP ${label} \u2014 .config already exists`);\n skipped++;\n return;\n }\n }\n\n // Read the main secret\n const values = await readSecret(smClient, secretId);\n if (!values) {\n logInfo(` SKIP ${label} \u2014 main secret empty or missing`);\n skipped++;\n return;\n }\n\n // Extract non-secret fields\n const configValues = extractNonSecretFields(schema.fields, values);\n\n if (opts.dryRun) {\n const fieldCount = Object.keys(configValues).length;\n logInfo(` DRY-RUN ${label} \u2192 ${configId} (${fieldCount} non-secret fields)`);\n migrated++;\n return;\n }\n\n const desc = `Non-secret credential fields for ${meta.name} (Hub display)`;\n await writeSecret(smClient, configId, configValues, desc);\n logSuccess(` OK ${label} \u2192 ${configId}`);\n migrated++;\n } catch (err) {\n logError(` FAIL ${label}: ${err}`);\n errors++;\n }\n }\n\n // Migrate the base secret\n await migrateOneSecret(meta.secretPrefix, meta.name);\n\n // Migrate multi-instance keys\n if (schema.keyedBy) {\n const keys = await listInstanceKeys(smClient, meta.secretPrefix);\n for (const key of keys) {\n await migrateOneSecret(`${meta.secretPrefix}/${key}`, `${meta.name}/${key}`);\n }\n }\n\n return { migrated, skipped, errors };\n}\n\n// =============================================================================\n// Main command\n// =============================================================================\n\nexport async function migrateConfigCommand(\n opts: {\n force?: boolean;\n dryRun?: boolean;\n stack?: string;\n stage?: string;\n region?: string;\n },\n): Promise<void> {\n const context = detectContext(resolveStackOption(opts));\n const region = opts.region ?? process.env.AWS_REGION ?? \"us-east-2\";\n\n const ssmClient = new SSMClient({ region });\n const smClient = new SecretsManagerClient({ region });\n\n logInfo(`Migrating .config mirrors for ${context.tenant}/${context.platformEnv}`);\n if (opts.dryRun) logInfo(\"DRY-RUN mode \u2014 no writes\");\n if (opts.force) logInfo(\"FORCE mode \u2014 overwrite existing .config\");\n\n const services = await discoverExternalServices(ssmClient, context.tenant, context.platformEnv);\n\n if (services.size === 0) {\n logInfo(\"No external services found.\");\n return;\n }\n\n let totalMigrated = 0;\n let totalSkipped = 0;\n let totalErrors = 0;\n\n for (const [name, svc] of services) {\n if (!svc.schema) {\n logInfo(`Skipping ${name}: no credential schema`);\n continue;\n }\n\n logInfo(`\\nMigrating: ${name}`);\n const result = await migrateService(smClient, svc.meta, svc.schema, {\n force: !!opts.force,\n dryRun: !!opts.dryRun,\n });\n totalMigrated += result.migrated;\n totalSkipped += result.skipped;\n totalErrors += result.errors;\n }\n\n console.error(\"\");\n logInfo(`Done: ${totalMigrated} migrated, ${totalSkipped} skipped, ${totalErrors} errors`);\n\n if (totalErrors > 0) {\n process.exit(1);\n }\n}\n", "/**\n * mesh secrets - Commands for working with AWS Secrets Manager\n *\n * Commands:\n * mesh secrets exec - Run command with secrets injected as environment variables\n * mesh secrets set - Set credentials for an external service\n */\n\nimport { Command, Option } from \"commander\";\nimport { execCommand } from \"./exec.js\";\nimport { setCommand } from \"./set.js\";\nimport { migrateConfigCommand } from \"./migrate-config.js\";\n\nexport function registerSecretsCommands(program: Command): void {\n const secrets = program\n .command(\"secrets\")\n .description(\"AWS Secrets Manager utilities\");\n\n secrets\n .command(\"exec\")\n .description(\"Run command with secrets as environment variables\")\n .allowUnknownOption(true)\n .action(async (_opts, cmd) => {\n // Get all args after \"secrets exec\"\n const args = cmd.args;\n await execCommand(args);\n });\n\n secrets\n .command(\"set [service]\")\n .description(\"Set credentials for an external service (e.g., mesh secrets set external/symitar)\")\n .option(\"--key <key>\", \"Instance key for multi-instance services (e.g., FI ID)\")\n .option(\"--all\", \"Prompt for all fields including optional ones\")\n .option(\"--json <json>\", \"Non-interactive: provide values as JSON\")\n .option(\"--stack <stack>\", \"Pulumi stack name (override detection)\")\n .addOption(new Option(\"--stage <stack>\", \"Deprecated alias for --stack\").hideHelp())\n .option(\"--region <region>\", \"AWS region (default: us-east-2)\")\n .action(async (service, opts) => {\n await setCommand(service, opts);\n });\n\n secrets\n .command(\"migrate-config\")\n .description(\"Backfill .config mirror secrets for all external services\")\n .option(\"--force\", \"Overwrite existing .config mirrors\")\n .option(\"--dry-run\", \"Show what would be written without writing\")\n .option(\"--stack <stack>\", \"Pulumi stack name (override detection)\")\n .addOption(new Option(\"--stage <stack>\", \"Deprecated alias for --stack\").hideHelp())\n .option(\"--region <region>\", \"AWS region (default: us-east-2)\")\n .action(async (opts) => {\n await migrateConfigCommand(opts);\n });\n}\n", "/**\n * mesh stack \u2014 Manage personal Pulumi stacks.\n *\n * mesh stack init Create a personal dev stack (dev-{github-user})\n * mesh stack init --from uat Base on a different stack\n *\n * Creates Pulumi.<stack>.yaml with:\n * - mesh:deploy: false (skip K8s deployments \u2014 dev-only stack)\n * - mesh:deployerRole copied from the base stack\n * - aws:region copied from the base stack\n */\n\nimport { Command } from \"commander\";\nimport { execFileSync } from \"child_process\";\nimport * as path from \"path\";\nimport * as fs from \"fs\";\nimport { parse as parseYaml } from \"yaml\";\nimport { logError, logInfo, logSuccess, logWarn } from \"../utils/log.js\";\nimport { findAppRoot, findStackConfigs, getCurrentStack, readStackConfig } from \"../utils/pulumi.js\";\nimport { resolveWorktreeIdentity, worktreeStackName } from \"../utils/worktree-identity.js\";\nimport { resolvePulumiEnv } from \"../utils/pulumi-run.js\";\n\n// =============================================================================\n// Helpers\n// =============================================================================\n\n/**\n * Read a top-level key from Pulumi.<stack>.yaml (not under `config:`).\n * Used for `secretsprovider` and `encryptedkey` which live at the root level.\n */\nfunction readTopLevelYamlKey(appRoot: string, stack: string, key: string): string | null {\n const configFile = path.join(appRoot, `Pulumi.${stack}.yaml`);\n if (!fs.existsSync(configFile)) return null;\n\n const content = fs.readFileSync(configFile, \"utf-8\");\n // Match top-level key (no leading whitespace, unlike config values which are indented)\n const pattern = new RegExp(`^${key}:\\\\s*(.+)$`, \"m\");\n const match = content.match(pattern);\n if (!match) return null;\n\n return match[1]!.trim().replace(/^[\"']|[\"']$/g, \"\");\n}\n\n/**\n * Read a key's scalar value from the `config:` block of Pulumi.<stack>.yaml\n * (e.g. `mesh:tenant`). Indented two spaces under `config:`.\n */\nfunction readConfigBlockKey(appRoot: string, stack: string, key: string): string | null {\n const configFile = path.join(appRoot, `Pulumi.${stack}.yaml`);\n if (!fs.existsSync(configFile)) return null;\n\n const content = fs.readFileSync(configFile, \"utf-8\");\n const pattern = new RegExp(`^\\\\s{2}${key.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\")}:\\\\s*(.+)$`, \"m\");\n const match = content.match(pattern);\n if (!match) return null;\n\n return match[1]!.trim().replace(/^[\"']|[\"']$/g, \"\");\n}\n\n\n/**\n * Personal-platform DNS preflight: verify the parent zone's PUBLIC delegation.\n *\n * The env zone ({env}.{parentZone}) is created and NS-delegated inside\n * Route53 by the platform deploy \u2014 but the chain only resolves publicly if\n * the parent zone itself is delegated at the DNS host above it (e.g. the 4\n * NS records for `sandbox` in the Cloudflare meshtech.io zone). Without it,\n * hostnames don't resolve and ACM certs sit in PENDING_VALIDATION forever.\n * This check names the exact records to add instead of leaving that failure\n * to be discovered from a \"not secure / unreachable\" browser error.\n */\nasync function checkParentZoneDelegation(\n parentZone: string,\n awsEnv: NodeJS.ProcessEnv,\n): Promise<void> {\n // What the internet sees\n let publicNs: string[] = [];\n try {\n const { Resolver } = await import(\"node:dns/promises\");\n const resolver = new Resolver();\n resolver.setServers([\"1.1.1.1\", \"8.8.8.8\"]);\n publicNs = (await resolver.resolveNs(parentZone)).map((n) => n.replace(/\\.$/, \"\").toLowerCase());\n } catch {\n // NXDOMAIN / no NS \u2014 treated as \"no public delegation\"\n }\n\n // What Route53 says the zone's nameservers ARE (so the warning can print\n // the exact records to add). Best-effort: skip silently without creds.\n let zoneNs: string[] = [];\n try {\n const { Route53Client, ListHostedZonesByNameCommand, GetHostedZoneCommand } = await import(\n \"@aws-sdk/client-route-53\"\n );\n const client = new Route53Client({\n credentials: awsEnv.AWS_ACCESS_KEY_ID\n ? {\n accessKeyId: awsEnv.AWS_ACCESS_KEY_ID,\n secretAccessKey: awsEnv.AWS_SECRET_ACCESS_KEY ?? \"\",\n sessionToken: awsEnv.AWS_SESSION_TOKEN,\n }\n : undefined,\n });\n const byName = await client.send(\n new ListHostedZonesByNameCommand({ DNSName: parentZone, MaxItems: 1 }),\n );\n const zone = byName.HostedZones?.[0];\n if (zone?.Id && zone.Name === `${parentZone}.`) {\n const detail = await client.send(new GetHostedZoneCommand({ Id: zone.Id }));\n zoneNs = (detail.DelegationSet?.NameServers ?? []).map((n) => n.toLowerCase());\n } else {\n logWarn(\n `Parent zone '${parentZone}' does not exist in Route53 yet \u2014 the platform deploy expects it (it hosts the env-zone delegations). Create it first (one-time, operator step).`,\n );\n return;\n }\n } catch {\n /* creds unavailable or lookup failed \u2014 fall through with what we have */\n }\n\n if (publicNs.length === 0) {\n const records =\n zoneNs.length > 0\n ? zoneNs.map((ns) => ` ${parentZone.split(\".\")[0]} NS ${ns}`).join(\"\\n\")\n : ` (run this command again with AWS credentials to print the exact nameservers)`;\n logWarn(\n `Parent zone '${parentZone}' has NO public NS delegation \u2014 hub/identity/temporal hostnames for this stack will NOT resolve and ACM certs stay pending until it lands.\\n` +\n ` One-time step: at the DNS host for '${parentZone.split(\".\").slice(1).join(\".\")}' (e.g. Cloudflare), add:\\n` +\n `${records}\\n` +\n ` The deploy itself can proceed now (certs validate automatically once delegation propagates).`,\n );\n } else if (zoneNs.length > 0 && !publicNs.some((ns) => zoneNs.includes(ns))) {\n logWarn(\n `Parent zone '${parentZone}' is publicly delegated to DIFFERENT nameservers than the Route53 zone in this account:\\n` +\n ` public: ${publicNs.join(\", \")}\\n` +\n ` zone: ${zoneNs.join(\", \")}\\n` +\n ` The env zone would be created in a zone the internet never consults \u2014 fix the delegation before deploying.`,\n );\n } else {\n logSuccess(`Parent zone delegation OK: ${parentZone} resolves publicly.`);\n }\n}\n\n/**\n * Read the `config:` block from `Pulumi.<stack>.yaml` on disk, in the same shape\n * `pulumi config --json` returns. This is the fallback when the base stack hasn't\n * been initialized in the backend yet (a freshly-generated app): `pulumi config\n * --json --stack <base>` fails, but the config we need still lives in the file.\n * Without this, `mesh stack init` silently drops region/tenant/platform/deployerRole.\n */\nfunction readBaseConfigFromYaml(\n appRoot: string,\n stack: string,\n): Record<string, { value: string; objectValue?: unknown }> {\n const file = path.join(appRoot, `Pulumi.${stack}.yaml`);\n if (!fs.existsSync(file)) return {};\n let doc: { config?: Record<string, unknown> } | null;\n try {\n doc = parseYaml(fs.readFileSync(file, \"utf-8\")) as { config?: Record<string, unknown> } | null;\n } catch {\n return {};\n }\n const cfg = doc?.config ?? {};\n const out: Record<string, { value: string; objectValue?: unknown }> = {};\n for (const [key, val] of Object.entries(cfg)) {\n out[key] =\n val !== null && typeof val === \"object\"\n ? { value: \"\", objectValue: val }\n : { value: String(val) };\n }\n return out;\n}\n\n/**\n * Get GitHub username from gh CLI, falling back to git config.\n */\nfunction getGitHubUsername(): string | null {\n // Try gh CLI first\n try {\n const result = execFileSync(\"gh\", [\"api\", \"user\", \"--jq\", \".login\"], {\n encoding: \"utf-8\",\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n const login = result.trim();\n if (login) return login;\n } catch {}\n\n // Fallback: git config\n try {\n const result = execFileSync(\"git\", [\"config\", \"user.email\"], {\n encoding: \"utf-8\",\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n const email = result.trim();\n // Extract username from GitHub email patterns\n // e.g., user@users.noreply.github.com or user@example.com\n const match = email.match(/^(\\d+\\+)?([^@]+)@/);\n if (match) return match[2]!;\n } catch {}\n\n return null;\n}\n\n/**\n * Find Pulumi.<stack>.yaml files in the app root.\n */\n// =============================================================================\n// Command\n// =============================================================================\n\nexport function registerStackCommand(program: Command): void {\n const stack = program\n .command(\"stack\")\n .description(\"Manage personal Pulumi stacks\");\n\n stack\n .command(\"init\")\n .description(\"Create a personal dev stack (dev-{github-username})\")\n .option(\"--from <stack>\", \"Base stack to copy config from\")\n .option(\"--name <name>\", \"Override stack name (default: dev-{username})\")\n .option(\"--adopt\", \"resume an EXISTING stack with this name (skips the availability check)\", false)\n .option(\n \"--worktree\",\n \"Isolate this stack per git worktree \u2014 append the worktree token to the name so concurrent worktrees deploy to distinct stacks (no SSM/namespace collisions)\",\n )\n .option(\n \"--platform\",\n \"Personal PLATFORM stack: a fully isolated platform env (Zitadel, Hub, Temporal, tenant envs) on the SHARED core \u2014 sets mesh:coreEnv to the base env, mesh:clusterOwner false, disables org-wide singletons (package registry, VPN), and keeps deploy ON. Run from a platform Pulumi program.\",\n false,\n )\n .option(\n \"--parent-zone <zone>\",\n \"With --platform: parent DNS zone for the env zone (mesh:dns.public.parentZone) \u2014 platform hostnames become {sub}.{env}.{parentZone} (e.g. hub.dmb-dev.mesh.meshtech.io), so personal stacks never collide on DNS\",\n )\n .action(async (opts) => {\n const appRoot = findAppRoot(process.cwd());\n if (!appRoot) {\n logError(\"No Pulumi.yaml found. Run from within a Pulumi app directory.\");\n process.exit(1);\n }\n\n // Get GitHub username\n const username = getGitHubUsername();\n if (!username) {\n logError(\n \"Could not determine GitHub username.\\n\" +\n \"Install gh CLI (https://cli.github.com) and run: gh auth login\"\n );\n process.exit(1);\n }\n\n // Determine base stack\n let baseStack = opts.from as string | undefined;\n if (!baseStack) {\n const stacks = findStackConfigs(appRoot);\n if (stacks.includes(\"dev\")) {\n baseStack = \"dev\";\n } else if (stacks.length === 1) {\n baseStack = stacks[0]!;\n } else if (stacks.length > 1) {\n logError(\n `Multiple stacks found: ${stacks.join(\", \")}\\n` +\n \"Specify which to base on: mesh stack init --from <stack>\"\n );\n process.exit(1);\n } else {\n logError(\"No stack configs found (Pulumi.<stack>.yaml).\");\n process.exit(1);\n }\n }\n\n // Verify base config exists\n const baseConfigPath = `${appRoot}/Pulumi.${baseStack}.yaml`;\n if (!fs.existsSync(baseConfigPath)) {\n logError(`Stack config not found: Pulumi.${baseStack}.yaml`);\n process.exit(1);\n }\n\n // Determine new stack name. --worktree appends this worktree's token so\n // concurrent worktrees deploy to distinct stacks: the SSM export paths\n // (apps/{app}/stacks/{stack}/...), Temporal namespace ({tenant}-{stack}-\n // {app}), and Nexus endpoint name all derive from the stack name, so ONE\n // discriminator isolates all three. The primary checkout has an empty\n // token, so --worktree is a no-op there (it IS the canonical stack).\n // Platform stacks follow {tenant}-{env} (parseEnvFromStack derives the\n // env by stripping the tenant prefix), so the personal env is\n // {username}-dev \u2192 stack {tenant}-{username}-dev. App stacks keep the\n // dev-{username} convention.\n const baseTenant = readConfigBlockKey(appRoot, baseStack, \"mesh:tenant\");\n if (opts.platform && !baseTenant) {\n logError(`--platform: could not read mesh:tenant from Pulumi.${baseStack}.yaml \u2014 is this a platform program?`);\n process.exit(1);\n }\n const baseName =\n (opts.name as string) ??\n (opts.platform ? `${baseTenant}-${username}-dev` : `dev-${username}`);\n let newStack = baseName;\n if (opts.worktree) {\n const wt = resolveWorktreeIdentity(appRoot);\n newStack = worktreeStackName(baseName, wt);\n if (wt.token) {\n logInfo(`--worktree: isolating as \"${newStack}\" (linked worktree \"${wt.slug}\")`);\n } else {\n logInfo(\n `--worktree: primary checkout has no worktree token \u2014 using \"${baseName}\" (isolation not needed here).`,\n );\n }\n }\n const newConfigPath = path.join(appRoot, `Pulumi.${newStack}.yaml`);\n\n const configExists = fs.existsSync(newConfigPath);\n\n // Detect KMS secrets provider from base stack config.\n // After migration, stacks have a top-level `secretsprovider:` key in their\n // Pulumi.<stack>.yaml with the KMS URI. Use it for new stacks so they\n // automatically use KMS instead of passphrase encryption.\n const secretsProvider = readTopLevelYamlKey(appRoot, baseStack, \"secretsprovider\");\n\n // Login preflight + deployer creds for the Pulumi backend (MESH-2085):\n // stack init/select/config all hit the S3 state backend and need the\n // deployer role. Resolve it ONCE from the base stack (the new stack has no\n // config yet) \u2014 and get a clear \"run mesh login --device\" instead of a raw\n // NoCredentialProviders \u2014 then reuse the env across every pulumi call below.\n const credEnv = await resolvePulumiEnv({ appRoot, stack: baseStack });\n const pulumiEnv = { ...process.env, ...credEnv };\n delete pulumiEnv.AWS_PROFILE;\n\n // Determinism: a personal stack NAME must be available. The backend is\n // shared, so an existing stack with this name belongs to someone (maybe\n // you, maybe not) \u2014 creating \"into\" it silently adopts their state.\n // Check first and fail with a clear remediation; --adopt is the\n // explicit escape hatch for resuming a stack you know is yours.\n if (!opts.adopt) {\n let existing: string[] = [];\n try {\n const raw = execFileSync(\"pulumi\", [\"stack\", \"ls\", \"--json\"], {\n cwd: appRoot,\n encoding: \"utf-8\",\n env: pulumiEnv,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n existing = (JSON.parse(raw) as Array<{ name: string }>).map((s) => s.name);\n } catch {\n // Backend unreachable \u2014 pulumi stack init below gives the real error.\n }\n if (existing.includes(newStack) || configExists) {\n logError(\n `Personal stack name '${newStack}' is not available` +\n (configExists ? ` (Pulumi.${newStack}.yaml already exists here)` : \" (a stack with this name exists in the backend)\") +\n \".\",\n );\n logInfo(` Pick another name: mesh stack init --name ${newStack}-2`);\n logInfo(` Resume YOUR OWN stack: mesh stack init --name ${newStack} --adopt`);\n process.exit(1);\n }\n }\n\n // Initialize the Pulumi stack\n const initArgs = [\"stack\", \"init\", newStack];\n if (secretsProvider) {\n initArgs.push(\"--secrets-provider\", secretsProvider);\n logInfo(`Using KMS secrets provider: ${secretsProvider}`);\n }\n\n try {\n execFileSync(\"pulumi\", initArgs, {\n cwd: appRoot,\n env: pulumiEnv,\n stdio: \"inherit\",\n });\n logSuccess(`Stack initialized: ${newStack}${secretsProvider ? \" (KMS secrets)\" : \"\"}`);\n } catch (err: any) {\n if (err.stderr?.includes(\"already exists\") && opts.adopt) {\n logWarn(`Stack ${newStack} already exists \u2014 adopting (--adopt).`);\n } else if (err.stderr?.includes(\"already exists\")) {\n logError(`Stack ${newStack} already exists. Re-run with --adopt if it is yours.`);\n process.exit(1);\n } else {\n process.exit(err.status ?? 1);\n }\n }\n\n // Select the new stack\n try {\n execFileSync(\"pulumi\", [\"stack\", \"select\", newStack], {\n cwd: appRoot,\n env: pulumiEnv,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n } catch {}\n\n // Copy config from base stack + add mesh:deploy false\n if (!configExists) {\n // Read base stack config as JSON\n let baseConfig: Record<string, { value: string; secret?: boolean; objectValue?: unknown }> = {};\n try {\n const raw = execFileSync(\n \"pulumi\",\n [\"config\", \"--json\", \"--stack\", baseStack],\n { cwd: appRoot, env: pulumiEnv, encoding: \"utf-8\", stdio: [\"pipe\", \"pipe\", \"pipe\"] },\n );\n baseConfig = JSON.parse(raw);\n } catch {\n // The base stack isn't initialized in the backend (common for a freshly\n // generated app) \u2014 read its config straight from Pulumi.<base>.yaml instead\n // of dropping it. (Previously this fell through with an empty config, leaving\n // the new stack missing region/tenant/platform/deployerRole \u2014 MESH-2096.)\n baseConfig = readBaseConfigFromYaml(appRoot, baseStack);\n if (Object.keys(baseConfig).length === 0) {\n logWarn(\n `Could not read base config from the backend or Pulumi.${baseStack}.yaml \u2014 ` +\n `the new stack will need manual config.`,\n );\n }\n }\n\n // Copy all config keys except mesh:deploy (we'll set that explicitly)\n for (const [key, entry] of Object.entries(baseConfig)) {\n if (key === \"mesh:deploy\") continue;\n\n try {\n if (entry.objectValue !== undefined) {\n // Structured value \u2014 set as JSON (Pulumi parses it back to object)\n execFileSync(\n \"pulumi\",\n [\"config\", \"set\", key, JSON.stringify(entry.objectValue)],\n { cwd: appRoot, env: pulumiEnv, stdio: [\"pipe\", \"pipe\", \"pipe\"] },\n );\n } else if (entry.value === \"true\" || entry.value === \"false\") {\n execFileSync(\n \"pulumi\",\n [\"config\", \"set\", \"--type\", \"bool\", key, entry.value],\n { cwd: appRoot, env: pulumiEnv, stdio: [\"pipe\", \"pipe\", \"pipe\"] },\n );\n } else {\n execFileSync(\n \"pulumi\",\n [\"config\", \"set\", key, entry.value],\n { cwd: appRoot, env: pulumiEnv, stdio: [\"pipe\", \"pipe\", \"pipe\"] },\n );\n }\n } catch {}\n }\n\n if (opts.platform) {\n // Personal PLATFORM stack: an isolated platform env on the shared\n // core. Everything below the platform layer is reused (cluster,\n // VPC, VPN, RDS); everything above it is this env's own.\n const baseEnv =\n readConfigBlockKey(appRoot, baseStack, \"mesh:coreEnv\") ??\n (baseTenant && baseStack.startsWith(`${baseTenant}-`)\n ? baseStack.slice(baseTenant.length + 1)\n : baseStack);\n const setCfg = (args: string[]) => {\n try {\n execFileSync(\"pulumi\", [\"config\", \"set\", ...args], {\n cwd: appRoot,\n env: pulumiEnv,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n } catch {}\n };\n setCfg([\"mesh:coreEnv\", baseEnv]);\n setCfg([\"--type\", \"bool\", \"mesh:clusterOwner\", \"false\"]);\n // Org-wide singletons stay with the primary platform: one package\n // registry per org, and the personal env reuses the shared VPN.\n setCfg([\"--type\", \"bool\", \"mesh:packageRegistry\", \"false\"]);\n setCfg([\"--type\", \"bool\", \"mesh:headscale\", \"false\"]);\n setCfg([\"--type\", \"bool\", \"mesh:subnetRouter\", \"false\"]);\n setCfg([\"--type\", \"bool\", \"mesh:devbox\", \"false\"]);\n // A personal platform env owns its whole DNS zone \u2014 hostname\n // suffixing (subdomain-{stage}) exists to avoid collisions inside a\n // SHARED zone and just makes URLs ugly here. Stable URLs by default.\n setCfg([\"--type\", \"bool\", \"mesh:stableUrl\", \"true\"]);\n // Tenant Pulumi-state bucket names are org-global by convention\n // ({hubTenant}-tenant-{name}-pulumi-state, no env segment) and\n // WILL collide with the primary platform's buckets. Scope each\n // copied tenant's bucket to this env via the documented\n // pulumiStateBucket override.\n try {\n const tenantsRaw = readConfigBlockKey(appRoot, newStack, \"mesh:tenants\");\n if (tenantsRaw) {\n const tenants = JSON.parse(tenantsRaw) as Record<string, Record<string, unknown>>;\n const envSegment = baseTenant && newStack.startsWith(`${baseTenant}-`)\n ? newStack.slice(baseTenant.length + 1)\n : newStack;\n for (const [tName, tCfg] of Object.entries(tenants)) {\n if (!tCfg.pulumiStateBucket) {\n tCfg.pulumiStateBucket = `${baseTenant}-tenant-${tName}-${envSegment}-pulumi-state`;\n }\n }\n setCfg([\"mesh:tenants\", JSON.stringify(tenants)]);\n }\n } catch {\n logWarn(\"Could not env-scope tenant pulumiStateBucket overrides \u2014 check mesh:tenants by hand (bucket names collide across envs otherwise).\");\n }\n // Env-zone DNS: hostnames derive from {env}.{parentZone} so this\n // stack can never collide with another env's hosts.\n // waitForValidation false \u2192 the deploy never blocks on ACM while the\n // parent zone's public delegation is still propagating; the cert\n // issues automatically once it lands.\n if (opts.parentZone) {\n setCfg([\n \"mesh:dns\",\n JSON.stringify({\n public: { parentZone: opts.parentZone, waitForValidation: false },\n }),\n ]);\n } else {\n logWarn(\n \"No --parent-zone given: platform hostnames will derive FLAT from the core zone and can collide with the primary platform. Set it now or later with: mesh deploy config set mesh:dns '{\\\"public\\\":{\\\"parentZone\\\":\\\"<zone>\\\"}}'\",\n );\n }\n if (opts.parentZone) {\n await checkParentZoneDelegation(opts.parentZone as string, pulumiEnv);\n }\n logSuccess(\n `Configured Pulumi.${newStack}.yaml (personal platform env on core '${baseEnv}'${opts.parentZone ? `, DNS zone ${newStack.startsWith(`${baseTenant}-`) ? newStack.slice(baseTenant!.length + 1) : newStack}.${opts.parentZone}` : \"\"})`,\n );\n } else {\n // Set mesh:deploy to false \u2014 personal APP stacks skip K8s deployments\n execFileSync(\"pulumi\", [\"config\", \"set\", \"--type\", \"bool\", \"mesh:deploy\", \"false\"], {\n cwd: appRoot,\n env: pulumiEnv,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n\n logSuccess(`Configured Pulumi.${newStack}.yaml (based on ${baseStack}, deploy: false)`);\n }\n }\n\n console.log(\"\");\n logInfo(opts.platform ? `Your personal platform stack is ready.` : `Your personal stack is ready.`);\n // Qualify with --stack/--stage: right after init the deployer role isn't\n // assumed yet, so `pulumi stack --show-name` can't resolve the selected\n // stack and a bare `mesh deploy up` errors \"Could not determine stack\"\n // (MESH-2097). The explicit name is copy-paste correct.\n logInfo(`Run: mesh deploy up --stack ${newStack} --yes`);\n logInfo(\n opts.platform\n ? `Then point app stacks at it: mesh:platformEnv ${newStack.startsWith(`${baseTenant}-`) ? newStack.slice((baseTenant as string).length + 1) : newStack}`\n : `Then: mesh dev --stage ${newStack}`,\n );\n });\n\n stack\n .command(\"rm <name>\")\n .description(\"Remove a personal Pulumi stack (backend state + local config)\")\n .option(\"--yes\", \"Skip the confirmation prompt\")\n .action(async (name: string, opts) => {\n const appRoot = findAppRoot(process.cwd());\n if (!appRoot) {\n logError(\"No Pulumi.yaml found. Run from within a Pulumi app directory.\");\n process.exit(1);\n }\n\n // Credentialed via the shared chokepoint (MESH-2085) \u2014 the login preflight\n // + deployer role, so `pulumi stack rm` reaches the S3 backend instead of\n // NoCredentialProviders. Prefer the TARGET stack's role; but a half-created\n // stack, or one created in another worktree, may have no local config here\n // (exactly the stacks you most want to rm), so fall back to any OTHER local\n // stack that carries a deployerRole \u2014 personal dev stacks share an account.\n const credStack = readStackConfig(appRoot, name, \"mesh:deployerRole\")\n ? name\n : [getCurrentStack(appRoot), \"dev\", ...findStackConfigs(appRoot)].find(\n (s): s is string =>\n !!s && s !== name && !!readStackConfig(appRoot, s, \"mesh:deployerRole\"),\n ) ?? name;\n const credEnv = await resolvePulumiEnv({ appRoot, stack: credStack });\n const pulumiEnv = { ...process.env, ...credEnv };\n delete pulumiEnv.AWS_PROFILE;\n\n const args = [\"stack\", \"rm\", name];\n if (opts.yes) args.push(\"--yes\");\n try {\n execFileSync(\"pulumi\", args, { cwd: appRoot, env: pulumiEnv, stdio: \"inherit\" });\n logSuccess(`Removed stack ${name}`);\n } catch (err: any) {\n process.exit(err.status ?? 1);\n }\n });\n}\n", "/**\n * Reconstruct an agent conversation's transcript from decoded Temporal history.\n *\n * An agent conversation is a Temporal `agentWorkflow`. Its durable history holds\n * everything needed to replay the human/agent exchange even when the worker can\n * no longer run the workflow (code drift):\n *\n * - `WorkflowExecutionSignaled` with signal name `submit_user_message` \u2192\n * one HUMAN turn. Its input payload is `SubmitUserMessageParams`\n * (agent-sdk `agent-core/workflows/signals.ts`): `{ model, messages,\n * streamId, ... }` where `messages` is a Vercel-AI `ModelMessage[]`; the\n * user text lives in the `user`-role message(s).\n * - `callLLM` `ActivityTaskCompleted` \u2192 one ASSISTANT turn. Its result is\n * `LLMResult` (agent-sdk `agent-core/types.ts`): `{ messages, usage?,\n * telemetry? }` where `messages` is the model's output `ModelMessage[]` \u2014\n * `assistant`-role text parts plus any `tool-call` parts.\n *\n * This module is the PURE reconstruction core: it takes events whose payloads\n * have ALREADY been decrypted into plain objects and returns ordered turns. The\n * Temporal fetch + decrypt wiring lives in `commands/temporal.ts`.\n *\n * Everything here is best-effort and defensive: payload shapes vary across\n * agent-sdk versions, so every field access is guarded and a turn that can't be\n * parsed becomes a placeholder rather than throwing \u2014 the whole point is to\n * recover *something* from an otherwise-unreplayable history.\n */\n\n/** Classification of a single decoded history event. */\nexport interface DecodedEvent {\n /** Temporal event id (stringified). Used in placeholders. */\n eventId: string;\n /** Which kind of conversation event this is. */\n kind: \"userSignal\" | \"callLLMResult\" | \"other\";\n /**\n * The decoded payload object for this event:\n * - `userSignal` \u2192 the `submit_user_message` signal input (SubmitUserMessageParams)\n * - `callLLMResult` \u2192 the `callLLM` activity result (LLMResult)\n * - `other` \u2192 unused\n */\n payload?: unknown;\n}\n\n/**\n * Minimal shape of a raw Temporal history event as consumed by\n * `classifyHistoryEvents`. Only the attribute groups we classify are declared;\n * everything else is ignored. Field access is defensive so partial/variant\n * shapes (across Temporal SDK versions) don't throw.\n */\nexport interface RawHistoryEvent {\n eventId?: unknown;\n activityTaskScheduledEventAttributes?: {\n activityType?: { name?: string | null } | null;\n /**\n * The activity's INPUT payload group. For `callLLM` this is `callLLMArgs`\n * (`{ model, messages }`) whose `messages` is the FULL accumulated\n * conversation \u2014 the highest-fidelity snapshot source.\n */\n input?: { payloads?: unknown[] | null } | null;\n } | null;\n workflowExecutionSignaledEventAttributes?: {\n signalName?: string | null;\n input?: { payloads?: unknown[] | null } | null;\n } | null;\n activityTaskCompletedEventAttributes?: {\n scheduledEventId?: unknown;\n result?: { payloads?: unknown[] | null } | null;\n } | null;\n // Other attribute groups exist on real events but are not classified here.\n [k: string]: unknown;\n}\n\n/**\n * Decrypt+parse a payload group (the `payloads` array from a signal input or\n * activity result) into a plain object. Returns `undefined` when nothing could\n * be decoded, so the pure reconstructor emits a placeholder. Injected so the\n * classification stays pure and unit-testable without a live Temporal codec.\n */\nexport type DecodePayload = (\n payloads: unknown[] | undefined | null,\n) => Promise<unknown>;\n\n/**\n * Classify a raw Temporal history into the ordered `DecodedEvent[]` that\n * `reconstructTranscript` consumes.\n *\n * `ActivityTaskCompleted` events carry only a `scheduledEventId`, not the\n * activity's type name \u2014 so to tell which completions came from `callLLM` we\n * build a map of `ActivityTaskScheduled.eventId \u2192 activityType.name` as we walk\n * the history in event order, then look each completion's `scheduledEventId` up\n * in it. Only `callLLM` completions become `callLLMResult` (assistant) events;\n * completions of other activities (e.g. `routeTools`) are dropped.\n * `submit_user_message` signals become `userSignal` (human) events.\n *\n * Pure aside from the injected `decodePayload` (which performs the decrypt):\n * never throws, and preserves history order.\n */\nexport async function classifyHistoryEvents(\n rawEvents: Iterable<RawHistoryEvent>,\n decodePayload: DecodePayload,\n): Promise<DecodedEvent[]> {\n // scheduledEventId \u2192 activity type name, so we can tell which\n // ActivityTaskCompleted events came from `callLLM`.\n const activityTypeByScheduledId = new Map<string, string>();\n const events: DecodedEvent[] = [];\n\n for (const event of rawEvents) {\n const eventId = String(event.eventId);\n\n const scheduled = event.activityTaskScheduledEventAttributes;\n if (scheduled) {\n const name = scheduled.activityType?.name;\n if (name) activityTypeByScheduledId.set(eventId, name);\n continue;\n }\n\n const signal = event.workflowExecutionSignaledEventAttributes;\n if (signal?.signalName === \"submit_user_message\") {\n events.push({\n eventId,\n kind: \"userSignal\",\n payload: await decodePayload(signal.input?.payloads),\n });\n continue;\n }\n\n const completed = event.activityTaskCompletedEventAttributes;\n if (completed) {\n const scheduledId = String(completed.scheduledEventId);\n if (activityTypeByScheduledId.get(scheduledId) === \"callLLM\") {\n events.push({\n eventId,\n kind: \"callLLMResult\",\n payload: await decodePayload(completed.result?.payloads),\n });\n }\n }\n }\n\n return events;\n}\n\n/**\n * A Vercel-AI `ModelMessage` as it appears in decoded history \u2014 kept structural\n * (not flattened to text) so tool-call / tool-result content parts survive into\n * the snapshot. Typed loosely on purpose: shapes vary across agent-sdk versions\n * and the snapshot is a best-effort passthrough of whatever was persisted.\n */\nexport type ModelMessage = { role?: string; content?: unknown } & Record<\n string,\n unknown\n>;\n\n/**\n * Extract the highest-fidelity STRUCTURED transcript for a store-ready snapshot\n * backfill \u2014 the complete `ModelMessage[]` with tool-call/tool-result parts\n * intact (as opposed to `reconstructTranscript`'s flattened text turns).\n *\n * The source is the `callLLM` activity's SCHEDULED input, `callLLMArgs`\n * (`{ model, messages }`), whose `messages` is the FULL accumulated conversation\n * (user + assistant-with-tool-calls + tool-result messages) up to \u2014 but not\n * including \u2014 that turn's assistant output. We take the LAST `callLLM`\n * scheduled input (the most-accumulated one) and append the LAST `callLLM`\n * completion's output messages (`LLMResult.messages`, the final assistant turn):\n *\n * [...lastScheduledInput.messages, ...lastCompletion.messages]\n *\n * Completions are matched to `callLLM` via `scheduledEventId` (same mapping as\n * `classifyHistoryEvents`).\n *\n * Best-effort and never throws:\n * - no `callLLM` scheduled input (0 assistant turns) \u2192 `[]`;\n * - a scheduled input but no completion (last turn interrupted) \u2192 just the\n * input messages.\n *\n * Pure aside from the injected `decodePayload` (which performs the decrypt).\n */\nexport async function extractSnapshotMessages(\n rawEvents: Iterable<RawHistoryEvent>,\n decodePayload: DecodePayload,\n): Promise<ModelMessage[]> {\n // Track the last `callLLM` scheduled input's payload group and its eventId, so\n // we can (a) decode the most-accumulated messages and (b) match its\n // completion by scheduledEventId.\n let lastCallLLMScheduledId: string | undefined;\n let lastCallLLMInputPayloads: unknown[] | null | undefined;\n // Map every scheduled activity's eventId \u2192 type name so completions resolve.\n const activityTypeByScheduledId = new Map<string, string>();\n // Track the last `callLLM` completion result payloads, keyed by matching the\n // scheduledEventId back to a `callLLM`.\n let lastCallLLMResultPayloads: unknown[] | null | undefined;\n\n for (const event of rawEvents) {\n const eventId = String(event.eventId);\n\n const scheduled = event.activityTaskScheduledEventAttributes;\n if (scheduled) {\n const name = scheduled.activityType?.name;\n if (name) activityTypeByScheduledId.set(eventId, name);\n if (name === \"callLLM\") {\n lastCallLLMScheduledId = eventId;\n lastCallLLMInputPayloads = scheduled.input?.payloads;\n // Reset the result: a completion only \"belongs\" to this newly-scheduled\n // callLLM if it arrives AFTER this point. Without the reset, a mid-turn\n // interrupted last turn (scheduled, never completed) would keep a STALE\n // earlier completion and duplicate that assistant message (it's already\n // inside this turn's accumulated input). Matches the documented contract:\n // scheduled-input-but-no-completion \u2192 just the input messages.\n lastCallLLMResultPayloads = undefined;\n }\n continue;\n }\n\n const completed = event.activityTaskCompletedEventAttributes;\n if (completed) {\n const scheduledId = String(completed.scheduledEventId);\n if (activityTypeByScheduledId.get(scheduledId) === \"callLLM\") {\n lastCallLLMResultPayloads = completed.result?.payloads;\n }\n }\n }\n\n if (lastCallLLMScheduledId === undefined) return [];\n\n const inputArgs = await decodePayload(lastCallLLMInputPayloads);\n const inputMessages = messagesFrom(inputArgs);\n\n const result = await decodePayload(lastCallLLMResultPayloads);\n const resultMessages = messagesFrom(result);\n\n return [...inputMessages, ...resultMessages];\n}\n\n/** Pull a `.messages` array off a decoded `{ messages }` payload, else `[]`. */\nfunction messagesFrom(payload: unknown): ModelMessage[] {\n if (isRecord(payload) && Array.isArray(payload.messages)) {\n return payload.messages as ModelMessage[];\n }\n return [];\n}\n\n/** One reconstructed conversation turn. */\nexport interface Turn {\n role: \"user\" | \"assistant\";\n /** Human-readable text. Empty string is valid (e.g. a tool-only assistant turn). */\n text: string;\n /** Formatted tool-call summaries (`name(compactArgs)`), assistant turns only. */\n toolCalls?: string[];\n /** Originating Temporal event id. */\n eventId: string;\n}\n\n// \u2500\u2500 Extraction helpers (all defensive) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Pull display text out of a ModelMessage `content` (string, or parts array). */\nfunction extractText(content: unknown): string {\n if (typeof content === \"string\") return content;\n if (Array.isArray(content)) {\n return content\n .filter(\n (p): p is { type: string; text?: unknown } =>\n !!p && typeof p === \"object\" && (p as { type?: unknown }).type === \"text\",\n )\n .map((p) => (typeof p.text === \"string\" ? p.text : \"\"))\n .join(\"\");\n }\n return \"\";\n}\n\n/** Compact a tool-call's args to a single truncated JSON line. */\nfunction summarizeArgs(args: unknown): string {\n try {\n const str = JSON.stringify(args ?? {});\n return str.length > 100 ? str.substring(0, 97) + \"...\" : str;\n } catch {\n return \"...\";\n }\n}\n\n/** Format a `tool-call` content part as `name(compactArgs)`. */\nfunction formatToolCall(part: Record<string, unknown>): string {\n const name = typeof part.toolName === \"string\" ? part.toolName : \"?\";\n // AI SDK v5 uses `input`; older payloads use `args`. Accept either.\n const args = \"input\" in part ? part.input : part.args;\n return `${name}(${summarizeArgs(args)})`;\n}\n\nfunction isRecord(v: unknown): v is Record<string, unknown> {\n return !!v && typeof v === \"object\";\n}\n\n/**\n * Extract the human text from a `submit_user_message` signal payload. Returns\n * `null` when nothing recognizable is found (caller emits a placeholder).\n */\nfunction extractUserText(payload: unknown): string | null {\n if (!isRecord(payload)) return null;\n\n const messages = payload.messages;\n if (Array.isArray(messages)) {\n const parts: string[] = [];\n for (const m of messages) {\n if (isRecord(m) && m.role === \"user\") {\n const t = extractText(m.content);\n if (t) parts.push(t);\n }\n }\n if (parts.length > 0) return parts.join(\"\\n\");\n }\n\n // Defensive fallbacks for shape drift \u2014 try common single-field carriers.\n for (const field of [\"content\", \"text\", \"message\"] as const) {\n const v = payload[field];\n if (typeof v === \"string\" && v) return v;\n const t = extractText(v);\n if (t) return t;\n }\n return null;\n}\n\n/**\n * Extract the assistant text + tool calls from a `callLLM` result payload.\n * Returns `null` only when nothing at all could be parsed (no text AND no tool\n * calls) \u2014 a tool-only turn (empty text, non-empty toolCalls) is valid.\n */\nfunction extractAssistantTurn(\n payload: unknown,\n): { text: string; toolCalls: string[] } | null {\n if (!isRecord(payload)) return null;\n\n const messages = payload.messages;\n if (!Array.isArray(messages)) {\n // Defensive fallback: some shapes may carry text directly.\n const t = extractText(payload.content) || extractText(payload.text);\n return t ? { text: t, toolCalls: [] } : null;\n }\n\n let text = \"\";\n const toolCalls: string[] = [];\n for (const m of messages) {\n if (!isRecord(m) || m.role !== \"assistant\") continue;\n text += extractText(m.content);\n if (Array.isArray(m.content)) {\n for (const p of m.content) {\n if (isRecord(p) && p.type === \"tool-call\") {\n toolCalls.push(formatToolCall(p));\n }\n }\n }\n }\n\n if (!text && toolCalls.length === 0) return null;\n return { text, toolCalls };\n}\n\n// \u2500\u2500 Reconstruction \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Reconstruct ordered conversation turns from decoded history events.\n *\n * Pure: no I/O, never throws. `other` events are skipped; unparseable\n * user/assistant events become placeholder turns so the recovery is complete\n * end-to-end even when individual payloads are corrupt.\n */\nexport function reconstructTranscript(events: DecodedEvent[]): Turn[] {\n const turns: Turn[] = [];\n for (const event of events) {\n if (event.kind === \"userSignal\") {\n const text = extractUserText(event.payload);\n turns.push(\n text !== null\n ? { role: \"user\", text, eventId: event.eventId }\n : { role: \"user\", text: placeholder(event.eventId), eventId: event.eventId },\n );\n } else if (event.kind === \"callLLMResult\") {\n const turn = extractAssistantTurn(event.payload);\n if (turn) {\n turns.push({\n role: \"assistant\",\n text: turn.text,\n eventId: event.eventId,\n ...(turn.toolCalls.length > 0 ? { toolCalls: turn.toolCalls } : {}),\n });\n } else {\n turns.push({\n role: \"assistant\",\n text: placeholder(event.eventId),\n eventId: event.eventId,\n });\n }\n }\n // `other` \u2192 skipped\n }\n return turns;\n}\n\nfunction placeholder(eventId: string): string {\n return `_[unparseable turn: ${eventId}]_`;\n}\n\n// \u2500\u2500 Rendering \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Render turns as a readable markdown transcript. */\nexport function renderTranscriptMarkdown(turns: Turn[]): string {\n const blocks: string[] = [];\n for (const turn of turns) {\n const heading = turn.role === \"user\" ? \"## User\" : \"## Assistant\";\n const lines: string[] = [heading, \"\"];\n if (turn.text) lines.push(turn.text);\n if (turn.toolCalls && turn.toolCalls.length > 0) {\n if (turn.text) lines.push(\"\");\n for (const tc of turn.toolCalls) lines.push(`\u2192 tool: ${tc}`);\n }\n blocks.push(lines.join(\"\\n\"));\n }\n return blocks.join(\"\\n\\n\") + \"\\n\";\n}\n", "/**\n * Temporal payload decryption helpers for mesh CLI.\n *\n * Mirrors the AES-256-GCM codec in `@mesh-tech/app-kit/temporal-codec`. The CLI\n * can't depend on app-kit directly because app-kit depends on mesh-cli \u2014 so\n * the codec logic is intentionally duplicated here, kept small, and bounded\n * to read-only decryption (the CLI never encrypts).\n *\n * Wire format (matches app-kit EncryptionCodec):\n * metadata[\"encoding\"] = \"binary/encrypted\"\n * metadata[\"encryption-key-id\"] = first 16 hex chars of SHA-256(encodingKey)\n * data = IV (12 bytes) || ciphertext || GCM auth tag (16 bytes)\n *\n * Decryption of `data` yields a serialized Temporal Payload protobuf, whose\n * inner `encoding` metadata tells you how to interpret the inner bytes\n * (`json/plain`, `binary/plain`, etc.). We hand-decode the Payload message\n * (a trivial 2-field protobuf) instead of depending on `@temporalio/proto`,\n * so the CLI stays dependency-clean and doesn't need a Temporal SDK peer.\n */\n\nimport { execFileSync } from \"child_process\";\nimport { webcrypto as crypto } from \"node:crypto\";\nimport { logSuccess, logWarn } from \"./log.js\";\n\n// \u2500\u2500 Encoding key resolution \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Read the Temporal encoding key from a Kubernetes secret in the given\n * namespace. Returns `undefined` when kubectl is unavailable, the secret\n * doesn't exist, or the caller isn't authenticated to the cluster.\n *\n * The K8s secret is preferred over Pulumi stack output because personal dev\n * stacks ship a placeholder encoding key that cannot decrypt deployed\n * payloads; the K8s secret is always authoritative for a given namespace.\n *\n * @param namespace - Kubernetes namespace matching the Temporal namespace\n * (mesh apps use the same name for both).\n */\nexport function resolveTemporalEncodingKeyFromK8s(\n namespace: string,\n): string | undefined {\n const secretName = `${namespace}-temporal-encoding-key`;\n try {\n const b64 = execFileSync(\n \"kubectl\",\n [\n \"get\",\n \"secret\",\n secretName,\n \"-n\",\n namespace,\n \"-o\",\n \"jsonpath={.data.TEMPORAL_ENCODING_KEY}\",\n ],\n { encoding: \"utf-8\", timeout: 10_000, stdio: [\"pipe\", \"pipe\", \"pipe\"] },\n ).trim();\n\n if (!b64) return undefined;\n return Buffer.from(b64, \"base64\").toString(\"utf-8\");\n } catch {\n // kubectl missing, secret absent, or no cluster access \u2014 caller decides.\n return undefined;\n }\n}\n\n// \u2500\u2500 AES-256-GCM decryption \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst ENCRYPTED_ENCODING = \"binary/encrypted\";\nconst IV_LENGTH = 12;\n\nasync function deriveKey(encodingKey: string): Promise<crypto.CryptoKey> {\n const keyData = await crypto.subtle.digest(\n \"SHA-256\",\n new TextEncoder().encode(encodingKey),\n );\n return crypto.subtle.importKey(\n \"raw\",\n keyData,\n { name: \"AES-GCM\" },\n false,\n [\"decrypt\"],\n );\n}\n\nasync function aesGcmDecrypt(\n data: Uint8Array,\n key: crypto.CryptoKey,\n): Promise<Uint8Array> {\n const iv = data.slice(0, IV_LENGTH);\n const ciphertextWithTag = data.slice(IV_LENGTH);\n const decrypted = await crypto.subtle.decrypt(\n { name: \"AES-GCM\", iv },\n key,\n ciphertextWithTag,\n );\n return new Uint8Array(decrypted);\n}\n\n// \u2500\u2500 Payload decoder \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Minimal shape of a Temporal Payload we care about.\n * Matches `temporal.api.common.v1.Payload` from @temporalio/proto but avoids\n * importing the type at module load time (so the CLI still loads without the\n * Temporal SDK installed).\n */\nexport interface RawPayload {\n metadata?: Record<string, Uint8Array | null | undefined> | null;\n data?: Uint8Array | null;\n}\n\n/**\n * A decrypter closure bound to a specific encoding key. Returns a decoded\n * human-readable string for a single encrypted Payload, or `null` when the\n * payload wasn't encrypted and the caller should fall back to raw decoding.\n *\n * Error paths (`[undecryptable]`, `[decode error: ...]`) are returned as\n * strings rather than thrown \u2014 debugging a history is a best-effort read-only\n * operation and one bad payload shouldn't abort the whole dump.\n */\nexport type PayloadDecrypter = (\n payload: RawPayload | null | undefined,\n) => Promise<string | null>;\n\n/**\n * Build a decrypter closure for the given encoding key.\n */\nexport async function createPayloadDecrypter(\n encodingKey: string,\n): Promise<PayloadDecrypter> {\n const key = await deriveKey(encodingKey);\n\n return async (payload) => {\n if (!payload?.metadata) return null;\n\n const encodingBytes = payload.metadata[\"encoding\"];\n if (!encodingBytes) return null;\n const encoding = new TextDecoder().decode(encodingBytes);\n if (encoding !== ENCRYPTED_ENCODING) return null;\n\n if (!payload.data) return \"[encrypted payload missing data]\";\n\n let inner: RawPayload;\n try {\n const decrypted = await aesGcmDecrypt(payload.data, key);\n inner = decodePayloadProtobuf(decrypted);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return `[undecryptable: ${msg}]`;\n }\n\n return decodeInnerPayload(inner);\n };\n}\n\n/**\n * A closure that decrypts a single encrypted Temporal Payload to its INNER\n * (plaintext) Payload \u2014 the `{ metadata, data }` the worker's codec wrapped \u2014\n * rather than the human-readable string {@link PayloadDecrypter} produces.\n *\n * Returns `null` when the payload isn't encrypted (the caller leaves it as-is).\n * Unlike the display decrypter, decryption errors THROW here: a fixture with a\n * silently-mangled payload would replay wrong, so the caller must surface it.\n */\nexport type RawPayloadDecrypter = (\n payload: RawPayload | null | undefined,\n) => Promise<RawPayload | null>;\n\n/**\n * Build a raw (Payload-in, Payload-out) decrypter for the given encoding key.\n *\n * This is the fixture-capture counterpart of {@link createPayloadDecrypter}:\n * where that one renders a payload for human display (lossy \u2014 binary payloads\n * become placeholders), this one returns the exact decrypted inner Payload so\n * the bytes can be re-serialized into a replayable proto3-JSON history.\n */\nexport async function createRawPayloadDecrypter(\n encodingKey: string,\n): Promise<RawPayloadDecrypter> {\n const key = await deriveKey(encodingKey);\n\n return async (payload) => {\n if (!payload?.metadata) return null;\n\n const encodingBytes = payload.metadata[\"encoding\"];\n if (!encodingBytes) return null;\n const encoding = new TextDecoder().decode(encodingBytes);\n if (encoding !== ENCRYPTED_ENCODING) return null;\n\n if (!payload.data) {\n throw new Error(\"encrypted payload has no data to decrypt\");\n }\n\n const decrypted = await aesGcmDecrypt(payload.data, key);\n return decodePayloadProtobuf(decrypted);\n };\n}\n\n// \u2500\u2500 Hand-rolled Payload protobuf decoder \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// temporal.api.common.v1.Payload has exactly two fields:\n// message Payload {\n// map<string, bytes> metadata = 1; // field 1, length-delimited\n// bytes data = 2; // field 2, length-delimited\n// }\n// A protobuf `map<K, V>` is syntactic sugar for:\n// repeated MapEntry { K key = 1; V value = 2; }\n// so each metadata entry is itself a length-delimited submessage with two\n// inner length-delimited fields.\n//\n// Decoding this by hand avoids pulling in `@temporalio/proto` as a peer dep.\n\nfunction readVarint(buf: Uint8Array, pos: number): { value: number; next: number } {\n let value = 0;\n let shift = 0;\n let next = pos;\n while (next < buf.length) {\n const byte = buf[next]!;\n next += 1;\n value |= (byte & 0x7f) << shift;\n if ((byte & 0x80) === 0) return { value, next };\n shift += 7;\n if (shift >= 32) throw new Error(\"varint too large\");\n }\n throw new Error(\"truncated varint\");\n}\n\nfunction readLengthDelimited(\n buf: Uint8Array,\n pos: number,\n): { bytes: Uint8Array; next: number } {\n const { value: length, next: afterLen } = readVarint(buf, pos);\n const end = afterLen + length;\n if (end > buf.length) throw new Error(\"truncated length-delimited field\");\n return { bytes: buf.slice(afterLen, end), next: end };\n}\n\n/**\n * Decode a serialized `temporal.api.common.v1.Payload`.\n *\n * Unknown fields and wire types are skipped rather than throwing; we only\n * need the two documented fields and Temporal's wire format is stable.\n */\nfunction decodePayloadProtobuf(buf: Uint8Array): RawPayload {\n const metadata: Record<string, Uint8Array> = {};\n let data: Uint8Array | undefined;\n let pos = 0;\n\n while (pos < buf.length) {\n const { value: tag, next: afterTag } = readVarint(buf, pos);\n const fieldNumber = tag >>> 3;\n const wireType = tag & 0x7;\n pos = afterTag;\n\n if (wireType === 2) {\n const { bytes, next } = readLengthDelimited(buf, pos);\n pos = next;\n if (fieldNumber === 1) {\n const entry = decodeMetadataEntry(bytes);\n if (entry) metadata[entry.key] = entry.value;\n } else if (fieldNumber === 2) {\n data = bytes;\n }\n // Other fields: ignore.\n } else if (wireType === 0) {\n // varint \u2014 skip\n pos = readVarint(buf, pos).next;\n } else if (wireType === 1) {\n pos += 8; // fixed64\n } else if (wireType === 5) {\n pos += 4; // fixed32\n } else {\n throw new Error(`unsupported wire type ${wireType} at pos ${pos}`);\n }\n }\n\n return { metadata, data: data ?? new Uint8Array(0) };\n}\n\nfunction decodeMetadataEntry(\n buf: Uint8Array,\n): { key: string; value: Uint8Array } | null {\n let key: string | undefined;\n let value: Uint8Array | undefined;\n let pos = 0;\n\n while (pos < buf.length) {\n const { value: tag, next: afterTag } = readVarint(buf, pos);\n const fieldNumber = tag >>> 3;\n const wireType = tag & 0x7;\n pos = afterTag;\n if (wireType !== 2) {\n // Skip unsupported fields defensively.\n if (wireType === 0) pos = readVarint(buf, pos).next;\n else if (wireType === 1) pos += 8;\n else if (wireType === 5) pos += 4;\n else throw new Error(`unsupported metadata wire type ${wireType}`);\n continue;\n }\n const { bytes, next } = readLengthDelimited(buf, pos);\n pos = next;\n if (fieldNumber === 1) key = new TextDecoder().decode(bytes);\n else if (fieldNumber === 2) value = bytes;\n }\n\n if (key === undefined || value === undefined) return null;\n return { key, value };\n}\n\n/**\n * Render a decrypted inner Payload as a human-readable string.\n *\n * Handles the common encodings Mesh workers emit:\n * - `json/plain` \u2192 pretty-printed JSON\n * - `binary/null` \u2192 literal `null`\n * - `binary/plain` \u2192 `[binary N bytes]`\n * - anything else \u2192 `[encoding=X, N bytes]`\n */\nfunction decodeInnerPayload(payload: RawPayload): string {\n const meta = payload.metadata ?? {};\n const encodingBytes = meta[\"encoding\"];\n const encoding = encodingBytes\n ? new TextDecoder().decode(encodingBytes)\n : \"unknown\";\n const data = payload.data ?? new Uint8Array(0);\n\n if (encoding === \"binary/null\") return \"null\";\n if (encoding === \"json/plain\") {\n const text = new TextDecoder().decode(data);\n try {\n return JSON.stringify(JSON.parse(text), null, 2);\n } catch {\n // Not valid JSON despite the encoding claim \u2014 surface the raw text so\n // the debugger sees whatever garbage the worker actually wrote.\n return text;\n }\n }\n if (encoding === \"binary/plain\") return `[binary, ${data.length} bytes]`;\n return `[encoding=${encoding}, ${data.length} bytes]`;\n}\n\n// \u2500\u2500 High-level helper \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Resolve the Temporal encoding key for a namespace, logging where it came\n * from (or why it couldn't be found). Prefer the K8s secret (authoritative for\n * the namespace); fall back to an explicit TEMPORAL_ENCODING_KEY env var. The\n * env fallback lets you decrypt a workflow's history OFFLINE \u2014 e.g. to\n * reconstruct a conversation, or capture a replay fixture, whose worker can no\n * longer replay it \u2014 using the key from a running `mesh dev` worker env when\n * kubectl/cluster access isn't set up.\n *\n * Returns `undefined` when neither source yields a key.\n */\nexport function resolveEncodingKey(namespace: string): string | undefined {\n const fromK8s = resolveTemporalEncodingKeyFromK8s(namespace);\n const key = fromK8s ?? process.env.TEMPORAL_ENCODING_KEY;\n if (!key) {\n logWarn(\n `Could not read TEMPORAL_ENCODING_KEY from secret ` +\n `${namespace}/${namespace}-temporal-encoding-key, and TEMPORAL_ENCODING_KEY ` +\n \"is not set. Configure kubectl (namespace read \" +\n \"access), or export TEMPORAL_ENCODING_KEY (e.g. from a `mesh dev` worker env).\",\n );\n return undefined;\n }\n logSuccess(\n fromK8s\n ? `Resolved encoding key from ${namespace}-temporal-encoding-key`\n : \"Resolved encoding key from TEMPORAL_ENCODING_KEY env\",\n );\n return key;\n}\n\n/**\n * Resolve the encoding key and build a decrypter for the given namespace.\n * Logs a warning and returns `undefined` when the key can't be read; callers\n * should fall back to printing events without payloads.\n */\nexport async function buildDecrypterForNamespace(\n namespace: string,\n): Promise<PayloadDecrypter | undefined> {\n const key = resolveEncodingKey(namespace);\n if (!key) return undefined;\n return createPayloadDecrypter(key);\n}\n\n/**\n * Resolve the encoding key and build a RAW (Payload-in/Payload-out) decrypter\n * for the given namespace \u2014 used by `capture-history` to decrypt payloads back\n * into replayable proto bytes. Returns `undefined` when the key can't be read;\n * callers decide whether that's fatal.\n */\nexport async function buildRawDecrypterForNamespace(\n namespace: string,\n): Promise<RawPayloadDecrypter | undefined> {\n const key = resolveEncodingKey(namespace);\n if (!key) return undefined;\n return createRawPayloadDecrypter(key);\n}\n", "/**\n * Serialize a fetched Temporal workflow history into the replay-fixture JSON\n * shape \u2014 the same canonical proto3-JSON `{ events: [...] }` that\n * `@mesh-tech/agent-sdk`'s `replay/history-io.ts` `historyToFixture` produces,\n * so a captured file replays via `replayFixture` (which rehydrates it with\n * `historyFromJSON`) for LOCAL debugging. Captured PRODUCTION histories are\n * never committed (they contain real, decrypted customer/conversation data \u2014\n * see the CLI's do-not-commit warning); only synthetic goldens live in\n * `packages/agent-sdk/src/replay/fixtures/`.\n *\n * We reuse `@temporalio/common`'s `historyToJSON` directly (the exact helper\n * agent-sdk's history-io uses) rather than importing `@mesh-tech/agent-sdk`:\n * the CLI has no reason to pull in the whole worker/replay stack, and keeping\n * the dependency pointed at the shared Temporal library guarantees the output\n * round-trips through `historyFromJSON`.\n *\n * The one thing a *real* history needs that a synthetic golden fixture doesn't:\n * its payloads are ENCRYPTED (the worker's AES-GCM codec). `historyToJSON`\n * would just base64 the ciphertext, which `replayFixture`'s plaintext converter\n * can't decode. So before serializing we walk every Payload in the history and\n * replace each encrypted one with its decrypted inner Payload \u2014 yielding a\n * plaintext fixture identical in shape to a codec-free golden capture.\n */\n\n// Explicit `.js` \u2014 this package publishes native ESM, so the compiled dist\n// must use a fully-specified specifier or Node throws ERR_MODULE_NOT_FOUND at\n// runtime (MESH-2262). tsx tolerates the extensionless form; node does not.\nimport { historyToJSON } from \"@temporalio/common/lib/proto-utils.js\";\n\nimport type { RawPayload, RawPayloadDecrypter } from \"./temporal-codec.js\";\n\n/**\n * A Temporal Payload as it appears on a raw history event (proto-decoded):\n * `metadata` is a map of header name \u2192 bytes, `data` is the (possibly\n * encrypted) body bytes. Matches `temporal.api.common.v1.Payload`.\n */\ninterface HistoryPayload {\n metadata?: Record<string, Uint8Array | null | undefined> | null;\n data?: Uint8Array | null;\n}\n\nfunction isPayload(value: unknown): value is HistoryPayload {\n return (\n value != null &&\n typeof value === \"object\" &&\n \"metadata\" in value &&\n \"data\" in value\n );\n}\n\n/**\n * Walk an arbitrary history-event tree and decrypt every encrypted Payload in\n * place, using `decrypt` to turn an encrypted Payload into its plaintext inner\n * Payload. Payloads the decrypter reports as non-encrypted (`null`) are left\n * untouched. Returns the number of payloads that were decrypted.\n *\n * The `{ metadata, data }` heuristic mirrors Temporal's own `fixPayloads` in\n * `@temporalio/common/lib/proto-utils`, so it identifies exactly the nodes\n * proto3-JSON treats as payloads. Once a node is a Payload we do NOT recurse\n * into it (its metadata values are bytes, not nested payloads).\n */\nexport async function decryptHistoryPayloads(\n node: unknown,\n decrypt: RawPayloadDecrypter,\n): Promise<number> {\n if (node == null || typeof node !== \"object\") return 0;\n\n if (isPayload(node)) {\n const inner = await decrypt(node as RawPayload);\n if (inner === null) return 0; // not encrypted \u2014 leave as-is\n // Replace the encrypted envelope with the decrypted inner payload's bytes.\n node.metadata = inner.metadata ?? {};\n node.data = inner.data ?? new Uint8Array(0);\n return 1;\n }\n\n let count = 0;\n if (Array.isArray(node)) {\n for (const item of node) count += await decryptHistoryPayloads(item, decrypt);\n } else {\n for (const value of Object.values(node as Record<string, unknown>)) {\n count += await decryptHistoryPayloads(value, decrypt);\n }\n }\n return count;\n}\n\n/** Result of {@link serializeHistoryToFixture}. */\nexport interface CaptureResult {\n /** The parsed proto3-JSON fixture object (drop-in for `replayFixture`). */\n fixture: unknown;\n /** Total events serialized. */\n eventCount: number;\n /** How many encrypted payloads were decrypted (0 when no decrypter given). */\n decryptedPayloads: number;\n}\n\n/**\n * Turn an ordered list of raw history events into a replay fixture object.\n *\n * @param events - Raw proto-decoded history events, in order (as yielded by the\n * CLI's `iterHistoryEvents` over `getWorkflowExecutionHistory`).\n * @param decrypter - Optional raw payload decrypter. When provided, every\n * encrypted payload in the history is decrypted in place before serialization\n * so the fixture is replayable with a plaintext converter. When omitted, the\n * payloads are serialized as-is (ciphertext, base64-encoded).\n *\n * `historyToJSON` runs its input through protobuf `History.fromObject`, so a\n * plain `{ events }` object of raw events is accepted directly; it returns a\n * proto3-JSON *string* which we parse back to a structured object (the same\n * `JSON.parse(historyToJSON(...))` round-trip `historyToFixture` performs).\n */\nexport async function serializeHistoryToFixture(\n events: unknown[],\n decrypter?: RawPayloadDecrypter,\n): Promise<CaptureResult> {\n let decryptedPayloads = 0;\n if (decrypter) {\n for (const event of events) {\n decryptedPayloads += await decryptHistoryPayloads(event, decrypter);\n }\n }\n\n const fixture = JSON.parse(historyToJSON({ events } as never)) as unknown;\n return { fixture, eventCount: events.length, decryptedPayloads };\n}\n", "/**\n * mesh temporal \u2014 inspect Temporal workflows for the current app/stack.\n *\n * Commands:\n * mesh temporal describe <workflowId> [runId] Show workflow status and metadata\n * mesh temporal history <workflowId> [runId] Show workflow event history\n *\n * Connection info is resolved from the app's Pulumi stack output (same as mesh dev).\n * Uses the raw gRPC API so we can render events without a codec proxy; when\n * `--show-payloads` is set we resolve the app's `TEMPORAL_ENCODING_KEY` from\n * its Kubernetes secret and decrypt inline via the shared codec helper.\n */\n\nimport { spawnSync } from \"node:child_process\";\nimport { writeFileSync, mkdirSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { Command } from \"commander\";\nimport { logError, logInfo, logSuccess, logWarn } from \"../utils/log.js\";\nimport {\n classifyHistoryEvents,\n extractSnapshotMessages,\n reconstructTranscript,\n renderTranscriptMarkdown,\n} from \"../utils/recover-conversation.js\";\nimport {\n findAppRoot,\n findStackConfigs,\n getCurrentStack,\n pulumiStackOutput,\n readStackConfig,\n} from \"../utils/pulumi.js\";\nimport { resolveAwsCredentials } from \"../utils/aws-auth.js\";\nimport { resolveTemporalAuth, acquireTemporalBearer } from \"../utils/temporal-auth.js\";\nimport {\n buildDecrypterForNamespace,\n buildRawDecrypterForNamespace,\n type PayloadDecrypter,\n} from \"../utils/temporal-codec.js\";\n\n// \u2500\u2500 Connection resolution \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\ninterface TemporalConnectionInfo {\n address: string;\n namespace: string;\n /**\n * Context for minting a Zitadel Bearer for auth-enforcing servers. Absent when\n * connecting via explicit --address/env (then auth falls back to ambient env).\n */\n auth?: { tenant: string; env: string; platformName: string };\n}\n\n/**\n * Resolve Temporal address and namespace from the current app's stack output.\n * Falls back to env vars if stack output isn't available.\n */\nasync function resolveConnection(\n options: { stack?: string; address?: string; namespace?: string },\n): Promise<TemporalConnectionInfo> {\n // Explicit overrides take precedence\n if (options.address && options.namespace) {\n return { address: options.address, namespace: options.namespace };\n }\n\n // Try from environment (set by mesh dev)\n if (!options.address && process.env.TEMPORAL_ADDRESS) {\n const address = process.env.TEMPORAL_ADDRESS;\n const namespace = options.namespace ?? process.env.TEMPORAL_NAMESPACE;\n if (namespace) return { address, namespace };\n }\n\n // Resolve from Pulumi stack output\n const appRoot = findAppRoot(process.cwd());\n if (!appRoot) {\n throw new Error(\n \"Not in a Mesh app directory (no Pulumi.yaml found).\\n\" +\n \"Run from an app directory, or provide --address and --namespace.\",\n );\n }\n\n const stack = options.stack ?? getCurrentStack(appRoot);\n if (!stack) {\n const stacks = findStackConfigs(appRoot);\n throw new Error(\n `No Pulumi stack selected.\\n` +\n (stacks.length > 0\n ? `Available: ${stacks.join(\", \")}\\nUse: mesh temporal --stack <name> ...`\n : \"No stack configs found in this directory.\"),\n );\n }\n\n const sa = stack ? [\"--stack\", stack] : [];\n\n // Resolve AWS credentials the same way mesh dev does\n const deployerRole = readStackConfig(appRoot, stack, \"mesh:deployerRole\");\n const awsCreds = deployerRole\n ? (await resolveAwsCredentials(deployerRole, appRoot, stack))?.env\n : undefined;\n\n // Pulumi's `app` output from env.register() is a struct containing a\n // secret-tainted `dev` field (secret because service env vars include values\n // like TEMPORAL_ENCODING_KEY). pulumiStackOutput transparently retries with\n // --show-secrets when it sees a `\"[secret]\"` placeholder, so we can reach\n // the non-sensitive tunnel/namespace fields nested inside.\n let devOutput: any;\n let appOutput: any;\n try {\n const result = pulumiStackOutput(appRoot, \"app\", sa, awsCreds);\n appOutput = JSON.parse(result);\n devOutput = appOutput.dev ?? appOutput;\n } catch {\n // Legacy stacks that exported `dev` directly (pre-env.register() format).\n try {\n const result = pulumiStackOutput(appRoot, \"dev\", sa, awsCreds);\n devOutput = JSON.parse(result);\n appOutput = devOutput;\n } catch {\n throw new Error(\n `Could not read stack output for '${stack}'.\\n` +\n \"Ensure you've run: mesh deploy up\\n\" +\n \"Or provide --address and --namespace explicitly.\",\n );\n }\n }\n\n const tunnel = devOutput?.tunnels?.temporal;\n // namespace lives at the app output level, not inside dev\n const namespace = options.namespace ?? appOutput?.namespace ?? devOutput?.namespace;\n\n if (!tunnel) {\n throw new Error(\"No temporal tunnel found in stack output.\");\n }\n if (!namespace) {\n throw new Error(\"No temporal namespace found in stack output.\");\n }\n\n // Auth context for minting a Bearer, mirroring resolveTemporalAuthVars in dev.ts:\n // tenant/env/name come from the PLATFORM block (platformName is the platform's\n // name, not the app tenant \u2014 it keys the Zitadel issuer lookup).\n const platform = (devOutput?.platform ?? appOutput?.platform) as\n | { tenant?: string; env?: string; name?: string }\n | undefined;\n const auth = platform\n ? {\n tenant: platform.tenant ?? \"mesh\",\n env: platform.env ?? \"dev\",\n platformName: platform.name ?? platform.tenant ?? \"mesh\",\n }\n : undefined;\n\n return {\n address: options.address ?? `${tunnel.host}:${tunnel.port}`,\n namespace,\n auth,\n };\n}\n\n/**\n * Mint a Zitadel Bearer for the connection, or return undefined to connect\n * unauthenticated (correct for local/non-enforcing Temporal). Prefers ambient\n * env creds (e.g. exported by `mesh dev`); otherwise resolves the app's M2M\n * credentials from SSM via the auth context.\n */\nasync function resolveBearerToken(\n auth?: { tenant: string; env: string; platformName: string },\n): Promise<string | undefined> {\n try {\n const haveEnvCreds =\n !!process.env.TEMPORAL_AUTH_CLIENT_ID && !!process.env.ZITADEL_ISSUER;\n const vars =\n !haveEnvCreds && auth\n ? await resolveTemporalAuth(auth.tenant, auth.env, auth.platformName)\n : {};\n return await acquireTemporalBearer(vars);\n } catch (err) {\n logWarn(\n `Temporal auth unavailable (${err instanceof Error ? err.message : String(err)}); ` +\n `connecting unauthenticated`,\n );\n return undefined;\n }\n}\n\n// \u2500\u2500 Event type names \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n// Temporal event type enum \u2192 human-readable name\nconst EVENT_TYPE_NAMES: Record<number, string> = {\n 1: \"WorkflowExecutionStarted\",\n 2: \"WorkflowExecutionCompleted\",\n 3: \"WorkflowExecutionFailed\",\n 4: \"WorkflowExecutionTimedOut\",\n 5: \"WorkflowTaskScheduled\",\n 6: \"WorkflowTaskStarted\",\n 7: \"WorkflowTaskCompleted\",\n 8: \"WorkflowTaskTimedOut\",\n 9: \"WorkflowTaskFailed\",\n 10: \"ActivityTaskScheduled\",\n 11: \"ActivityTaskStarted\",\n 12: \"ActivityTaskCompleted\",\n 13: \"ActivityTaskFailed\",\n 14: \"ActivityTaskTimedOut\",\n 15: \"ActivityTaskCancelRequested\",\n 16: \"ActivityTaskCanceled\",\n 17: \"TimerStarted\",\n 18: \"TimerFired\",\n 19: \"TimerCanceled\",\n 20: \"WorkflowExecutionCancelRequested\",\n 21: \"WorkflowExecutionCanceled\",\n 24: \"WorkflowExecutionSignaled\", // not 22/23 which were removed\n 25: \"WorkflowExecutionTerminated\",\n 26: \"WorkflowExecutionSignaled\",\n 29: \"WorkflowPropertiesModified\",\n 40: \"ChildWorkflowExecutionStarted\",\n 41: \"ChildWorkflowExecutionCompleted\",\n 42: \"ChildWorkflowExecutionFailed\",\n 43: \"ChildWorkflowExecutionCanceled\",\n 44: \"ChildWorkflowExecutionTimedOut\",\n 45: \"ChildWorkflowExecutionTerminated\",\n 46: \"WorkflowPropertiesModified\",\n 48: \"NexusOperationScheduled\",\n 49: \"NexusOperationStarted\",\n 50: \"NexusOperationCompleted\",\n 51: \"NexusOperationFailed\",\n 52: \"NexusOperationCanceled\",\n 53: \"NexusOperationTimedOut\",\n};\n\n// Workflow status enum \u2192 name\nconst STATUS_NAMES: Record<number, string> = {\n 0: \"UNSPECIFIED\",\n 1: \"RUNNING\",\n 2: \"COMPLETED\",\n 3: \"FAILED\",\n 4: \"CANCELED\",\n 5: \"TERMINATED\",\n 6: \"CONTINUED_AS_NEW\",\n 7: \"TIMED_OUT\",\n};\n\n// \u2500\u2500 Commands \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nasync function describeWorkflow(\n workflowId: string,\n runId: string | undefined,\n options: { stack?: string; address?: string; namespace?: string },\n): Promise<void> {\n const conn = await connect(options);\n try {\n const desc = await conn.connection.workflowService.describeWorkflowExecution({\n namespace: conn.namespace,\n execution: { workflowId, runId },\n });\n\n const info = desc.workflowExecutionInfo;\n if (!info) {\n logError(\"No workflow execution info returned.\");\n return;\n }\n\n console.log(`Workflow: ${workflowId}`);\n console.log(`Run ID: ${info.execution?.runId ?? runId ?? \"?\"}`);\n console.log(`Type: ${info.type?.name ?? \"?\"}`);\n console.log(`Status: ${STATUS_NAMES[info.status ?? 0] ?? info.status}`);\n console.log(`Task Queue: ${info.taskQueue ?? \"?\"}`);\n console.log(`Namespace: ${conn.namespace}`);\n\n // Pending activities\n const pending = desc.pendingActivities ?? [];\n if (pending.length > 0) {\n console.log(`\\nPending Activities (${pending.length}):`);\n for (const pa of pending) {\n console.log(` - ${pa.activityType?.name ?? \"?\"} (attempt ${pa.attempt}, state: ${pa.state})`);\n }\n }\n\n // Pending nexus operations\n const pendingNexus = desc.pendingNexusOperations ?? [];\n if (pendingNexus.length > 0) {\n console.log(`\\nPending Nexus Operations (${pendingNexus.length}):`);\n for (const pn of pendingNexus) {\n console.log(` - ${pn.operation ?? \"?\"} \u2192 ${pn.endpoint ?? \"?\"} (state: ${pn.state})`);\n }\n }\n } finally {\n conn.connection.close();\n }\n}\n\n/**\n * Page through a workflow's execution history, yielding each event in order.\n * Shared by `history` (existing-history phase) and `recover-conversation` so the\n * pagination logic lives in one place. Follow-mode long-polling is separate\n * (it uses `waitNewEvent` + terminal detection) and stays in `showHistory`.\n */\nasync function* iterHistoryEvents(\n workflowService: any,\n namespace: string,\n workflowId: string,\n runId: string | undefined,\n maximumPageSize = 100,\n): AsyncGenerator<any> {\n let nextPageToken: Uint8Array | undefined;\n do {\n const resp = await workflowService.getWorkflowExecutionHistory({\n namespace,\n execution: { workflowId, runId },\n maximumPageSize,\n nextPageToken,\n });\n\n for (const event of resp.history?.events ?? []) {\n yield event;\n }\n\n nextPageToken = resp.nextPageToken?.length ? resp.nextPageToken : undefined;\n } while (nextPageToken);\n}\n\nasync function showHistory(\n workflowId: string,\n runId: string | undefined,\n options: {\n stack?: string;\n address?: string;\n namespace?: string;\n limit?: string;\n compact?: boolean;\n follow?: boolean;\n showPayloads?: boolean;\n },\n): Promise<void> {\n const conn = await connect(options);\n const maxEvents = options.follow ? Infinity : parseInt(options.limit ?? \"200\", 10);\n\n // Compact mode skips WorkflowTask* events (scheduling noise)\n const skipTypes = new Set([5, 6, 7, 8, 9]); // WorkflowTask*\n\n // Resolve the per-app encoding key lazily \u2014 only when the caller asks for\n // payload bodies. Failure to resolve is non-fatal: we print the history\n // without payloads and the warning from buildDecrypterForNamespace tells\n // the user why.\n const decrypter: PayloadDecrypter | undefined = options.showPayloads\n ? await buildDecrypterForNamespace(conn.namespace)\n : undefined;\n\n try {\n let totalShown = 0;\n let lastEventId = 0;\n\n console.log(`History for ${workflowId} (namespace: ${conn.namespace})${options.follow ? \" [following]\" : \"\"}\\n`);\n\n // Fetch existing history first\n for await (const event of iterHistoryEvents(\n conn.connection.workflowService,\n conn.namespace,\n workflowId,\n runId,\n )) {\n lastEventId = Number(event.eventId);\n const eventType = event.eventType ?? 0;\n if (options.compact !== false && skipTypes.has(eventType)) continue;\n await printEvent(event, decrypter);\n totalShown++;\n if (totalShown >= maxEvents) break;\n }\n\n if (!options.follow) {\n console.log(`\\n${totalShown} events shown.`);\n return;\n }\n\n // Follow mode: long-poll for new events until workflow completes\n const terminalTypes = new Set([2, 3, 4, 21, 27, 28]); // Completed, Failed, TimedOut, Canceled, Terminated, ContinuedAsNew\n let done = false;\n\n while (!done) {\n try {\n const resp = await conn.connection.workflowService.getWorkflowExecutionHistory({\n namespace: conn.namespace,\n execution: { workflowId, runId },\n maximumPageSize: 100,\n waitNewEvent: true,\n // Start after the last event we've seen\n ...(lastEventId > 0 ? { skipArchival: true } : {}),\n });\n\n for (const event of resp.history?.events ?? []) {\n const eid = Number(event.eventId);\n if (eid <= lastEventId) continue; // already shown\n lastEventId = eid;\n\n const eventType = event.eventType ?? 0;\n if (options.compact !== false && skipTypes.has(eventType)) continue;\n await printEvent(event, decrypter);\n totalShown++;\n\n // Check if workflow reached a terminal state\n if (terminalTypes.has(eventType)) {\n done = true;\n }\n }\n } catch (err: any) {\n // Connection reset or workflow completed between polls\n if (err?.code === 5 /* NOT_FOUND */ || err?.message?.includes(\"not found\")) {\n console.log(\"\\nWorkflow completed or not found.\");\n done = true;\n } else {\n throw err;\n }\n }\n }\n\n console.log(`\\n${totalShown} events shown (workflow ended).`);\n } finally {\n conn.connection.close();\n }\n}\n\nasync function printEvent(\n event: any,\n decrypter: PayloadDecrypter | undefined,\n): Promise<void> {\n const eventType = event.eventType ?? 0;\n const typeName = EVENT_TYPE_NAMES[eventType] ?? `Unknown(${eventType})`;\n const id = String(event.eventId).padStart(4);\n const detail = extractEventDetail(event);\n const detailStr = detail ? ` \u2014 ${detail}` : \"\";\n console.log(`${id} ${typeName}${detailStr}`);\n\n if (!decrypter) return;\n\n // Print any named payload groups attached to this event \u2014 activity input/\n // output, signal input, workflow start args, etc. \u2014 decrypted and pretty-\n // printed under the header line with a 6-space indent so they align under\n // the event ID column.\n for (const group of extractEventPayloads(event)) {\n const rendered = await renderPayloads(group.payloads, decrypter);\n if (rendered === null) continue;\n console.log(` ${group.label}:`);\n for (const line of rendered.split(\"\\n\")) {\n console.log(` ${line}`);\n }\n }\n}\n\ninterface PayloadGroup {\n label: string;\n payloads: unknown[];\n}\n\n/**\n * Pick out the payload-bearing fields on a history event. Returns an empty\n * array for events that carry no interesting data (workflow task lifecycle,\n * timers, property modifications, etc.).\n */\nfunction extractEventPayloads(event: any): PayloadGroup[] {\n const groups: PayloadGroup[] = [];\n const pushIfAny = (label: string, payloads: unknown[] | undefined | null) => {\n if (payloads && payloads.length > 0) groups.push({ label, payloads });\n };\n\n if (event.workflowExecutionStartedEventAttributes) {\n pushIfAny(\"input\", event.workflowExecutionStartedEventAttributes.input?.payloads);\n }\n if (event.workflowExecutionCompletedEventAttributes) {\n pushIfAny(\"result\", event.workflowExecutionCompletedEventAttributes.result?.payloads);\n }\n if (event.workflowExecutionFailedEventAttributes) {\n const failure = event.workflowExecutionFailedEventAttributes.failure;\n if (failure?.message) groups.push({ label: \"failure\", payloads: [{ __failure: failure }] });\n }\n if (event.workflowExecutionSignaledEventAttributes) {\n pushIfAny(\"signal input\", event.workflowExecutionSignaledEventAttributes.input?.payloads);\n }\n if (event.activityTaskScheduledEventAttributes) {\n pushIfAny(\"input\", event.activityTaskScheduledEventAttributes.input?.payloads);\n }\n if (event.activityTaskCompletedEventAttributes) {\n pushIfAny(\"result\", event.activityTaskCompletedEventAttributes.result?.payloads);\n }\n if (event.activityTaskFailedEventAttributes) {\n const failure = event.activityTaskFailedEventAttributes.failure;\n if (failure?.message) groups.push({ label: \"failure\", payloads: [{ __failure: failure }] });\n }\n if (event.nexusOperationScheduledEventAttributes) {\n const input = event.nexusOperationScheduledEventAttributes.input;\n if (input) pushIfAny(\"input\", [input]);\n }\n if (event.nexusOperationCompletedEventAttributes) {\n const result = event.nexusOperationCompletedEventAttributes.result;\n if (result) pushIfAny(\"result\", [result]);\n }\n if (event.nexusOperationFailedEventAttributes) {\n const failure = event.nexusOperationFailedEventAttributes.failure;\n if (failure?.message) groups.push({ label: \"failure\", payloads: [{ __failure: failure }] });\n }\n return groups;\n}\n\n/**\n * Render one or more payloads into a multi-line string, or return `null`\n * when nothing rendered (e.g. all payloads were non-encrypted and empty).\n *\n * Failures (`{ __failure: ... }`) are rendered specially since they're a\n * structured error, not an encrypted payload.\n */\nasync function renderPayloads(\n payloads: unknown[],\n decrypter: PayloadDecrypter,\n): Promise<string | null> {\n const parts: string[] = [];\n for (const payload of payloads) {\n if (payload && typeof payload === \"object\" && \"__failure\" in payload) {\n const failure = (payload as { __failure: { message?: string; stackTrace?: string; cause?: unknown } }).__failure;\n parts.push(renderFailure(failure));\n continue;\n }\n const decoded = await decrypter(payload as Parameters<PayloadDecrypter>[0]);\n if (decoded === null) {\n parts.push(\"[non-encrypted payload]\");\n } else {\n parts.push(decoded);\n }\n }\n return parts.length > 0 ? parts.join(\"\\n---\\n\") : null;\n}\n\nfunction renderFailure(failure: { message?: string; stackTrace?: string; cause?: unknown }): string {\n const lines = [failure.message ?? \"(no message)\"];\n if (failure.stackTrace) lines.push(failure.stackTrace);\n return lines.join(\"\\n\");\n}\n\n/** Extract a human-readable detail string from event attributes. */\nfunction extractEventDetail(event: any): string | null {\n // Activity scheduled\n if (event.activityTaskScheduledEventAttributes) {\n const a = event.activityTaskScheduledEventAttributes;\n return `activity: ${a.activityType?.name ?? \"?\"}, queue: ${a.taskQueue?.name ?? \"?\"}`;\n }\n // Activity completed\n if (event.activityTaskCompletedEventAttributes) {\n return `scheduledId: ${event.activityTaskCompletedEventAttributes.scheduledEventId}`;\n }\n // Activity failed\n if (event.activityTaskFailedEventAttributes) {\n const a = event.activityTaskFailedEventAttributes;\n const msg = a.failure?.message ?? \"\";\n return `scheduledId: ${a.scheduledEventId}${msg ? `, error: ${msg.slice(0, 120)}` : \"\"}`;\n }\n // Activity timed out\n if (event.activityTaskTimedOutEventAttributes) {\n return `scheduledId: ${event.activityTaskTimedOutEventAttributes.scheduledEventId}`;\n }\n // Nexus scheduled\n if (event.nexusOperationScheduledEventAttributes) {\n const a = event.nexusOperationScheduledEventAttributes;\n return `endpoint: ${a.endpoint ?? \"?\"}, operation: ${a.operation ?? \"?\"}, service: ${a.service ?? \"?\"}`;\n }\n // Nexus completed/failed/timed out\n if (event.nexusOperationCompletedEventAttributes) {\n return `scheduledId: ${event.nexusOperationCompletedEventAttributes.scheduledEventId}`;\n }\n if (event.nexusOperationFailedEventAttributes) {\n const a = event.nexusOperationFailedEventAttributes;\n return `scheduledId: ${a.scheduledEventId}, error: ${a.failure?.message?.slice(0, 120) ?? \"?\"}`;\n }\n if (event.nexusOperationTimedOutEventAttributes) {\n return `scheduledId: ${event.nexusOperationTimedOutEventAttributes.scheduledEventId}`;\n }\n // Signal\n if (event.workflowExecutionSignaledEventAttributes) {\n return `signal: ${event.workflowExecutionSignaledEventAttributes.signalName ?? \"?\"}`;\n }\n // Workflow started\n if (event.workflowExecutionStartedEventAttributes) {\n const a = event.workflowExecutionStartedEventAttributes;\n return `type: ${a.workflowType?.name ?? \"?\"}, queue: ${a.taskQueue?.name ?? \"?\"}`;\n }\n // Workflow completed/failed\n if (event.workflowExecutionCompletedEventAttributes) return null;\n if (event.workflowExecutionFailedEventAttributes) {\n return `error: ${event.workflowExecutionFailedEventAttributes.failure?.message?.slice(0, 120) ?? \"?\"}`;\n }\n // Timer\n if (event.timerStartedEventAttributes) {\n const dur = event.timerStartedEventAttributes.startToFireTimeout;\n return `timerId: ${event.timerStartedEventAttributes.timerId}, duration: ${dur?.seconds ?? \"?\"}s`;\n }\n if (event.timerFiredEventAttributes) {\n return `timerId: ${event.timerFiredEventAttributes.timerId}`;\n }\n return null;\n}\n\n/**\n * Reconstruct an agent conversation's transcript from its durable Temporal\n * history \u2014 for when the worker can no longer replay it (code drift) but the\n * history is intact. Fetches the full history (same client/decrypt path as\n * `history`), classifies the `submit_user_message` signals (human turns) and\n * `callLLM` activity completions (assistant turns), decrypts their payloads,\n * and renders an ordered transcript.\n */\nasync function recoverConversation(\n workflowId: string,\n runId: string | undefined,\n options: {\n stack?: string;\n address?: string;\n namespace?: string;\n out?: string;\n json?: boolean;\n snapshot?: boolean;\n },\n): Promise<void> {\n const conn = await connect(options);\n\n // The history is encrypted \u2014 without the key there's nothing to reconstruct,\n // so (unlike `history`) a missing key is fatal here.\n const decrypter = await buildDecrypterForNamespace(conn.namespace);\n if (!decrypter) {\n conn.connection.close();\n throw new Error(\n \"Cannot decrypt conversation payloads: no encoding key available.\\n\" +\n \"Set TEMPORAL_ENCODING_KEY (e.g. from a `mesh dev` worker env) or configure \" +\n \"kubectl namespace read access, then retry.\",\n );\n }\n\n try {\n // Decode one payload group (signal input / activity result) into a plain\n // object. The decrypter yields pretty-printed JSON; parse it back. Any\n // failure returns undefined so the pure reconstructor emits a placeholder.\n const decodePayload = async (\n payloads: unknown[] | undefined | null,\n ): Promise<unknown> => {\n const first = payloads?.[0];\n if (first === undefined) return undefined;\n const decoded = await decrypter(first as Parameters<typeof decrypter>[0]);\n if (decoded === null) return undefined;\n try {\n return JSON.parse(decoded);\n } catch {\n return undefined;\n }\n };\n\n // Collect the full history in order, then classify it (which activity\n // completions were `callLLM`, which signals were `submit_user_message`)\n // via the shared pure helper.\n const rawEvents = [];\n for await (const event of iterHistoryEvents(\n conn.connection.workflowService,\n conn.namespace,\n workflowId,\n runId,\n )) {\n rawEvents.push(event);\n }\n\n // --snapshot: emit the store-ready conversation blob with STRUCTURED\n // ModelMessage[] (tool-call parts intact) for a full-fidelity backfill,\n // rather than the flattened text turns. artifacts/focus are left empty \u2014\n // the artifact index isn't reconstructable from history here, and the store\n // defaults them.\n if (options.snapshot) {\n const messages = await extractSnapshotMessages(rawEvents, decodePayload);\n const blob = {\n conversationId: workflowId,\n messages,\n artifacts: [] as unknown[],\n focus: null,\n };\n const output = JSON.stringify(blob, null, 2) + \"\\n\";\n if (options.out) {\n writeFileSync(options.out, output);\n logSuccess(\n `Wrote snapshot (${messages.length} messages) to ${options.out}`,\n );\n } else {\n process.stdout.write(output);\n }\n return;\n }\n\n const events = await classifyHistoryEvents(rawEvents, decodePayload);\n const turns = reconstructTranscript(events);\n\n const output = options.json\n ? JSON.stringify(\n {\n turns: turns.map((t) => ({\n role: t.role,\n text: t.text,\n ...(t.toolCalls ? { toolCalls: t.toolCalls } : {}),\n })),\n },\n null,\n 2,\n ) + \"\\n\"\n : renderTranscriptMarkdown(turns);\n\n if (options.out) {\n writeFileSync(options.out, output);\n logSuccess(`Wrote ${turns.length} turns to ${options.out}`);\n } else {\n process.stdout.write(output);\n }\n } finally {\n conn.connection.close();\n }\n}\n\n/**\n * Capture a workflow's FULL durable Temporal history to a replay fixture JSON\n * file \u2014 for LOCAL replay debugging of a specific production break. This is the\n * real-history counterpart of the CI gate's synthetic golden fixtures: the\n * output is the same proto3-JSON `{ events }` shape `@mesh-tech/agent-sdk`'s\n * `historyToFixture` produces, so it runs through `replayFixture` locally. It\n * is never committed to the replay fixtures dir \u2014 those are synthetic goldens;\n * this file holds real decrypted production data (see warning below).\n *\n * Payloads are DECRYPTED (via the same codec `history --show-payloads` uses) so\n * the fixture replays under agent-sdk's plaintext converter. Because that means\n * the file contains real customer/conversation data, the default output path is\n * `~/.mesh/replay-histories/` \u2014 outside any git repo \u2014 and a loud warning is\n * printed. An explicit `--out` inside a git repo is checked with\n * `git check-ignore`; a non-ignored path gets a loud warning (but is not\n * blocked). Like `recover-conversation`, a missing encoding key is fatal \u2014 an\n * encrypted fixture can't be replayed.\n */\nasync function captureHistory(\n workflowId: string,\n runId: string | undefined,\n options: {\n stack?: string;\n address?: string;\n namespace?: string;\n out?: string;\n },\n): Promise<void> {\n const conn = await connect(options);\n\n // A fixture whose payloads stay encrypted can't be replayed (the replayer\n // uses a codec-free converter), so \u2014 like recover-conversation \u2014 treat a\n // missing key as fatal rather than emitting a useless file.\n const decrypter = await buildRawDecrypterForNamespace(conn.namespace);\n if (!decrypter) {\n conn.connection.close();\n throw new Error(\n \"Cannot decrypt history payloads: no encoding key available.\\n\" +\n \"A replay fixture needs decrypted payloads. Set TEMPORAL_ENCODING_KEY \" +\n \"(e.g. from a `mesh dev` worker env) or configure kubectl namespace read \" +\n \"access, then retry.\",\n );\n }\n\n try {\n const events: unknown[] = [];\n for await (const event of iterHistoryEvents(\n conn.connection.workflowService,\n conn.namespace,\n workflowId,\n runId,\n )) {\n events.push(event);\n }\n\n if (events.length === 0) {\n throw new Error(\n `No history events found for workflow '${workflowId}'` +\n (runId ? ` (run ${runId})` : \"\") +\n `. Check the workflow id and namespace (${conn.namespace}).`,\n );\n }\n\n // Lazy import \u2014 pulls in @temporalio/common only when actually capturing,\n // so the CLI still loads without the Temporal SDK installed.\n const { serializeHistoryToFixture } = await import(\n \"../utils/capture-history.js\"\n );\n const { fixture, eventCount, decryptedPayloads } =\n await serializeHistoryToFixture(events, decrypter);\n\n const outPath =\n options.out ??\n join(homedir(), \".mesh\", \"replay-histories\", `${sanitizeFileId(workflowId)}.json`);\n mkdirSync(dirname(outPath), { recursive: true });\n if (options.out) warnIfNotGitIgnored(options.out);\n writeFileSync(outPath, JSON.stringify(fixture, null, 2) + \"\\n\");\n\n logSuccess(\n `Wrote replay history (${eventCount} events, ${decryptedPayloads} payloads decrypted) to ${outPath}`,\n );\n logWarn(\n \"\u26A0 This file contains DECRYPTED payloads \u2014 real customer/conversation \" +\n \"data.\\n\" +\n \" For LOCAL replay debugging ONLY. Do NOT commit it. (CI golden \" +\n \"fixtures are synthetic; this is the debugging counterpart.)\",\n );\n } finally {\n conn.connection.close();\n }\n}\n\n/** Make a workflow id safe to use as a filename (slashes, spaces, etc.). */\nfunction sanitizeFileId(id: string): string {\n return id.replace(/[^A-Za-z0-9._-]/g, \"_\");\n}\n\n/**\n * A replay fixture holds real DECRYPTED production data, so when the user\n * points `--out` at a path inside a git repo we check whether that path is\n * git-ignored (`git check-ignore`) and print a LOUD warning when it is not \u2014\n * we warn, we don't block. Best-effort: silent when git is unavailable or the\n * path is outside any repo (exit code 128), since there is nothing to commit\n * it into.\n */\nfunction warnIfNotGitIgnored(outPath: string): void {\n const abs = resolve(outPath);\n try {\n // Exit 0 = ignored, 1 = in a repo but NOT ignored, 128 = not a repo.\n const res = spawnSync(\"git\", [\"-C\", dirname(abs), \"check-ignore\", \"-q\", abs], {\n stdio: \"ignore\",\n });\n if (res.status !== 1) return;\n } catch {\n return; // git missing/unusable \u2014 can't check, stay quiet\n }\n logWarn(\n \"\u26A0\u26A0\u26A0 OUTPUT PATH IS INSIDE A GIT REPO AND IS *NOT* GITIGNORED \u26A0\u26A0\u26A0\\n\" +\n ` ${abs}\\n` +\n \" This fixture contains DECRYPTED production payloads. Add it to \" +\n \".gitignore or move it outside the repo \u2014 do NOT commit it.\",\n );\n}\n\nasync function terminateWorkflow(\n workflowId: string,\n runId: string | undefined,\n options: { stack?: string; address?: string; namespace?: string; reason?: string },\n): Promise<void> {\n const conn = await connect(options);\n try {\n await conn.connection.workflowService.terminateWorkflowExecution({\n namespace: conn.namespace,\n workflowExecution: { workflowId, runId },\n reason: options.reason ?? \"terminated via mesh temporal\",\n identity: \"mesh-cli\",\n });\n logSuccess(\n `Terminated ${workflowId}${runId ? ` (run ${runId})` : \"\"} in namespace ${conn.namespace}`,\n );\n } finally {\n conn.connection.close();\n }\n}\n\nasync function connect(\n options: { stack?: string; address?: string; namespace?: string },\n) {\n const info = await resolveConnection(options);\n logInfo(`Connecting to ${info.address} (namespace: ${info.namespace})`);\n\n // Dynamic import \u2014 @temporalio/client is only available in workspaces\n // that have it installed. The mesh-cli uses it from the monorepo.\n const { Connection } = await import(\"@temporalio/client\");\n\n // Attach a Zitadel Bearer when the server enforces auth. Without it the\n // MeshAuthorizer denies calls with \"Request unauthorized\" (e.g. terminate).\n const token = await resolveBearerToken(info.auth);\n const metadata = token ? { authorization: `Bearer ${token}` } : undefined;\n const connection = await Connection.connect({ address: info.address, metadata });\n\n return { connection, namespace: info.namespace };\n}\n\n// \u2500\u2500 Registration \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport function registerTemporalCommands(program: Command): void {\n const temporal = program\n .command(\"temporal\")\n .description(\"Inspect Temporal workflows for the current app/stack\");\n\n const sharedOpts = (cmd: Command) =>\n cmd\n .option(\"--stack <stack>\", \"Pulumi stack name (auto-detected from current directory)\")\n .option(\"--address <addr>\", \"Temporal server address (default: from stack output)\")\n .option(\"--namespace <ns>\", \"Temporal namespace (default: from stack output)\");\n\n sharedOpts(\n temporal\n .command(\"describe <workflowId> [runId]\")\n .description(\"Show workflow status and metadata\"),\n ).action(async (workflowId: string, runId: string | undefined, opts) => {\n try {\n await describeWorkflow(workflowId, runId, opts);\n } catch (err) {\n logError(err instanceof Error ? err.message : String(err));\n process.exitCode = 1;\n }\n });\n\n sharedOpts(\n temporal\n .command(\"terminate <workflowId> [runId]\")\n .description(\"Terminate a running workflow (e.g. a wedged/looping conversation)\"),\n )\n .option(\"--reason <reason>\", \"Termination reason (recorded in workflow history)\")\n .action(async (workflowId: string, runId: string | undefined, opts) => {\n try {\n await terminateWorkflow(workflowId, runId, opts);\n } catch (err) {\n logError(err instanceof Error ? err.message : String(err));\n process.exitCode = 1;\n }\n });\n\n sharedOpts(\n temporal\n .command(\"history <workflowId> [runId]\")\n .description(\"Show workflow event history\")\n .option(\"-n, --limit <n>\", \"Maximum events to show (default: 200)\")\n .option(\"-f, --follow\", \"Tail the history, waiting for new events until the workflow completes\")\n .option(\"--no-compact\", \"Show all events including WorkflowTask scheduling noise\")\n .option(\"-p, --show-payloads\", \"Decrypt and print activity inputs/outputs (reads TEMPORAL_ENCODING_KEY from the app's K8s secret via kubectl)\"),\n ).action(async (workflowId: string, runId: string | undefined, opts) => {\n try {\n await showHistory(workflowId, runId, opts);\n } catch (err) {\n logError(err instanceof Error ? err.message : String(err));\n process.exitCode = 1;\n }\n });\n\n sharedOpts(\n temporal\n .command(\"recover-conversation <workflowId> [runId]\")\n .description(\n \"Reconstruct an agent conversation transcript from durable Temporal history \" +\n \"(for when the worker can no longer replay it). Requires the encoding key \u2014 \" +\n \"reads TEMPORAL_ENCODING_KEY (or the app's K8s secret).\",\n )\n .option(\"--out <path>\", \"Write the transcript to a file instead of stdout\")\n .option(\"--json\", \"Emit a structured { turns: [...] } JSON array instead of markdown\")\n .option(\n \"--snapshot\",\n \"Emit a store-ready conversation blob { conversationId, messages, artifacts, focus } \" +\n \"with STRUCTURED ModelMessage[] (tool-call parts intact) for a full-fidelity backfill\",\n ),\n ).action(async (workflowId: string, runId: string | undefined, opts) => {\n try {\n await recoverConversation(workflowId, runId, opts);\n } catch (err) {\n logError(err instanceof Error ? err.message : String(err));\n process.exitCode = 1;\n }\n });\n\n sharedOpts(\n temporal\n .command(\"capture-history <workflowId> [runId]\")\n .description(\n \"Capture a workflow's full history to a replay fixture JSON (proto3-JSON, \" +\n \"DECRYPTED payloads) for LOCAL replay debugging. Requires the encoding key. \" +\n \"Defaults to ~/.mesh/replay-histories/<workflowId>.json (outside any repo) \u2014 \" +\n \"do NOT commit the output.\",\n )\n .option(\n \"--out <path>\",\n \"Output path (default: ~/.mesh/replay-histories/<workflowId>.json; a non-gitignored \" +\n \"path inside a git repo triggers a loud warning)\",\n ),\n ).action(async (workflowId: string, runId: string | undefined, opts) => {\n try {\n await captureHistory(workflowId, runId, opts);\n } catch (err) {\n logError(err instanceof Error ? err.message : String(err));\n process.exitCode = 1;\n }\n });\n}\n", "/**\n * mesh tenant \u2014 register and inspect app tenants on a Mesh platform stack.\n *\n * `mesh tenant add <name>` closes the gap the app-tenant doctor punts on:\n * its \"not registered\" check names `mesh deploy up # platform repo: add the\n * tenant under mesh:tenants first` as the fix, but that first half \u2014 \"add the\n * tenant under mesh:tenants\" \u2014 had no command and meant hand-editing\n * Pulumi.<stack>.yaml. This command performs the registration itself: run from\n * the PLATFORM layer of a tenant platform repo (e.g. mesh-sandbox/platform),\n * it inserts the tenant into the stack config's `mesh:tenants` map\n * (comment-preserving round-trip) and prints the deploy + verify steps that\n * make the registration live.\n *\n * `mesh tenant list` prints what the stack config declares, so \"is it\n * registered?\" is answerable without opening YAML.\n */\n\nimport { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport { parseDocument, YAMLMap, isMap } from \"yaml\";\nimport { logInfo, logWarn } from \"../utils/log.js\";\nimport { MeshCliError, emitJsonPayload } from \"../utils/errors.js\";\nimport { findAppRoot, findStackConfigs, getCurrentStack } from \"../utils/pulumi.js\";\nimport { atomicWriteFileSync } from \"./login.js\";\n\n// =============================================================================\n// Pure helpers (unit-tested)\n// =============================================================================\n\n/** Same rule `mesh init platform` applies to tenant names. */\nexport function validateTenantName(name: string): boolean {\n return /^[a-z][a-z0-9-]*$/.test(name) && !name.endsWith(\"-\");\n}\n\n/**\n * \"{tenant}-{env}\" \u2192 \"{env}\" (mesh-dev \u2192 dev). The last dash-segment is the\n * env by the platform stack naming convention; null when there is no dash to\n * split on, in which case the caller must pass --subdomain explicitly.\n */\nexport function deriveEnvFromStack(stack: string): string | null {\n const m = stack.match(/-([a-z0-9]+)$/);\n return m ? (m[1] ?? null) : null;\n}\n\nexport interface TenantAddSpec {\n name: string;\n displayName?: string;\n subdomain: string;\n zitadelOrgId?: string;\n}\n\nexport type TenantAddResult =\n | { ok: true; yaml: string; createdTenantsBlock: boolean }\n | { ok: false; reason: \"exists\" | \"no-config\"; detail: string };\n\n/**\n * Insert a tenant under `config.\"mesh:tenants\"` in a Pulumi stack config.\n * Round-trips through the yaml Document API so existing comments and entries\n * survive verbatim. Refuses (rather than merges) when the tenant is already\n * declared \u2014 an existing entry may carry fields (zitadelOrgId, nodePools\u2026)\n * that a re-add would silently drop.\n */\nexport function addTenantToStackConfig(yamlText: string, spec: TenantAddSpec): TenantAddResult {\n const doc = parseDocument(yamlText);\n const config = doc.getIn([\"config\"]);\n if (!isMap(config)) {\n return { ok: false, reason: \"no-config\", detail: \"no top-level `config:` map in the stack config\" };\n }\n\n const tenantsPath = [\"config\", \"mesh:tenants\"];\n let createdTenantsBlock = false;\n if (!isMap(doc.getIn(tenantsPath))) {\n if (doc.hasIn(tenantsPath)) {\n return { ok: false, reason: \"no-config\", detail: \"`mesh:tenants` exists but is not a map\" };\n }\n doc.setIn(tenantsPath, new YAMLMap());\n createdTenantsBlock = true;\n }\n\n if (doc.hasIn([...tenantsPath, spec.name])) {\n return { ok: false, reason: \"exists\", detail: `tenant '${spec.name}' is already declared in mesh:tenants` };\n }\n\n const entry: Record<string, string> = {};\n if (spec.displayName) entry.displayName = spec.displayName;\n entry.subdomain = spec.subdomain;\n if (spec.zitadelOrgId) entry.zitadelOrgId = spec.zitadelOrgId;\n doc.setIn([...tenantsPath, spec.name], doc.createNode(entry));\n\n // Keep the rewrite surgical: no flow-seq re-padding ([\"a\"] \u2192 [ \"a\" ]) and no\n // long-line rewrapping on parts of the file this command never touched.\n return {\n ok: true,\n yaml: doc.toString({ flowCollectionPadding: false, lineWidth: 0 }),\n createdTenantsBlock,\n };\n}\n\n/** Read the `mesh:tenants` map (name \u2192 config) out of a stack config, if any. */\nexport function listTenantsInStackConfig(\n yamlText: string,\n): Array<{ name: string; displayName?: string; subdomain?: string }> {\n const doc = parseDocument(yamlText);\n const tenants = doc.getIn([\"config\", \"mesh:tenants\"]);\n if (!isMap(tenants)) return [];\n return tenants.items.map((item) => {\n const name = String((item.key as { value?: unknown })?.value ?? item.key);\n const value = item.value;\n const get = (key: string): string | undefined => {\n if (!isMap(value)) return undefined;\n const v = value.get(key, false);\n return typeof v === \"string\" ? v : undefined;\n };\n return { name, displayName: get(\"displayName\"), subdomain: get(\"subdomain\") };\n });\n}\n\n// =============================================================================\n// Command plumbing\n// =============================================================================\n\ninterface ResolvedStackConfig {\n appRoot: string;\n stack: string;\n file: string;\n content: string;\n}\n\n/**\n * Resolve which Pulumi.<stack>.yaml to operate on: --stack wins, else the\n * currently-selected pulumi stack, else the single stack config in the dir.\n */\nfunction resolveStackConfig(explicitStack?: string): ResolvedStackConfig {\n const appRoot = findAppRoot(process.cwd());\n if (!appRoot) {\n throw new MeshCliError(\n \"No Pulumi.yaml found. Run from the PLATFORM layer of a tenant platform repo (the directory whose stack config carries mesh:tenants).\",\n );\n }\n const stacks = findStackConfigs(appRoot);\n const stack = explicitStack ?? getCurrentStack(appRoot) ?? (stacks.length === 1 ? stacks[0] : null);\n if (!stack) {\n throw new MeshCliError(\n `Could not determine the stack (found: ${stacks.join(\", \") || \"none\"}).`,\n { remediation: { command: \"mesh tenant add <name> --stack <stack>\" } },\n );\n }\n const file = path.join(appRoot, `Pulumi.${stack}.yaml`);\n if (!fs.existsSync(file)) {\n throw new MeshCliError(`Stack config not found: ${file}`, {\n remediation: { command: \"mesh tenant add <name> --stack <stack>\" },\n });\n }\n return { appRoot, stack, file, content: fs.readFileSync(file, \"utf-8\") };\n}\n\n/**\n * The two real platform-layer project names are `mesh-platform`\n * (mesh-sandbox/platform) and `{tenant}-platform` (the `mesh init platform`\n * scaffold); the sibling core layer is `{tenant}-core`. Anchoring on the\n * suffix keeps an app incidentally named e.g. `platform-api` out.\n */\nfunction readProjectName(appRoot: string): string {\n const projectDoc = parseDocument(fs.readFileSync(path.join(appRoot, \"Pulumi.yaml\"), \"utf-8\"));\n return String(projectDoc.get(\"name\") ?? \"\");\n}\n\nfunction looksLikePlatformLayer(projectName: string): boolean {\n return projectName.endsWith(\"-platform\");\n}\n\n/**\n * Guard against registering tenants on the wrong layer (core / an app): only\n * proceed without an existing `mesh:tenants` block when the Pulumi project\n * name says this is a platform layer.\n */\nfunction assertPlatformLayer(appRoot: string, content: string): void {\n if (parseDocument(content).hasIn([\"config\", \"mesh:tenants\"])) return;\n const projectName = readProjectName(appRoot);\n if (!looksLikePlatformLayer(projectName)) {\n throw new MeshCliError(\n `This looks like the wrong layer: project '${projectName}' has no mesh:tenants block and does not look like a platform layer. App tenants are registered on the tenant platform repo's PLATFORM stack (e.g. mesh-sandbox/platform).`,\n );\n }\n}\n\nexport function registerTenantCommands(program: Command): void {\n const tenant = program.command(\"tenant\").description(\"Register and inspect app tenants on a platform stack\");\n\n tenant\n .command(\"add <name>\")\n .description(\n \"Register an app tenant in the platform stack config (mesh:tenants) \u2014 then `mesh deploy up` makes it live.\",\n )\n .option(\"--display-name <name>\", \"display name shown in the Hub UI (default: the tenant slug)\")\n .option(\"--subdomain <subdomain>\", \"tenant subdomain (default: {name}-{env} derived from the stack name)\")\n .option(\"--zitadel-org-id <id>\", \"existing Zitadel organization ID to bind (optional)\")\n .option(\"--stack <stack>\", \"platform stack to register on (default: current stack, else the only one)\")\n .option(\"--json\", \"machine-readable output\", false)\n .action(\n async (\n name: string,\n opts: {\n displayName?: string;\n subdomain?: string;\n zitadelOrgId?: string;\n stack?: string;\n json: boolean;\n },\n ) => {\n if (!validateTenantName(name)) {\n throw new MeshCliError(`Invalid tenant name '${name}' (lowercase alphanumeric + dashes).`);\n }\n const resolved = resolveStackConfig(opts.stack);\n assertPlatformLayer(resolved.appRoot, resolved.content);\n\n const env = deriveEnvFromStack(resolved.stack);\n const subdomain = opts.subdomain ?? (env ? `${name}-${env}` : null);\n if (!subdomain) {\n throw new MeshCliError(\n `Cannot derive a default subdomain from stack '${resolved.stack}'.`,\n { remediation: { command: `mesh tenant add ${name} --subdomain <subdomain>` } },\n );\n }\n\n const result = addTenantToStackConfig(resolved.content, {\n name,\n displayName: opts.displayName,\n subdomain,\n zitadelOrgId: opts.zitadelOrgId,\n });\n if (!result.ok) {\n if (result.reason === \"exists\") {\n throw new MeshCliError(\n `${result.detail} (${path.basename(resolved.file)}). Edit the existing entry instead of re-adding it.`,\n );\n }\n throw new MeshCliError(`${resolved.file}: ${result.detail}`);\n }\n\n // Pulumi.<stack>.yaml holds every capability toggle and the tenants map \u2014\n // an interrupt mid-write must not truncate it.\n atomicWriteFileSync(resolved.file, result.yaml, fs.statSync(resolved.file).mode & 0o777);\n\n if (opts.json) {\n emitJsonPayload({\n ok: true,\n tenant: name,\n stack: resolved.stack,\n file: resolved.file,\n entry: { displayName: opts.displayName, subdomain, zitadelOrgId: opts.zitadelOrgId },\n deploy: `mesh deploy up -s ${resolved.stack}`,\n });\n return;\n }\n\n logInfo(\n `Tenant '${name}' registered in ${path.basename(resolved.file)} (mesh:tenants, subdomain '${subdomain}')${\n result.createdTenantsBlock ? \" \u2014 created the mesh:tenants block\" : \"\"\n }`,\n );\n console.log(\"\");\n console.log(\"Next steps:\");\n console.log(` mesh deploy preview -s ${resolved.stack} # expect only '${name}'-scoped additions`);\n console.log(` mesh deploy up -s ${resolved.stack} # provision tenant infra + Hub registry entry`);\n console.log(\"\");\n console.log(\"Then, from the tenant's apps repo:\");\n console.log(` mesh init app-tenant --tenant ${name} # the doctor should now pass`);\n console.log(` mesh create-app --tenant ${name} --name <app>`);\n },\n );\n\n tenant\n .command(\"list\")\n .description(\"List app tenants declared in the platform stack config\")\n .option(\"--stack <stack>\", \"platform stack to read (default: current stack, else the only one)\")\n .option(\"--json\", \"machine-readable output\", false)\n .action(async (opts: { stack?: string; json: boolean }) => {\n const resolved = resolveStackConfig(opts.stack);\n const tenants = listTenantsInStackConfig(resolved.content);\n if (opts.json) {\n emitJsonPayload({ ok: true, stack: resolved.stack, tenants });\n return;\n }\n if (tenants.length === 0) {\n // \"No tenants\" on a non-platform layer means \"wrong directory\", not\n // \"this platform has no tenants\" \u2014 warn rather than let it mislead.\n const projectName = readProjectName(resolved.appRoot);\n if (!looksLikePlatformLayer(projectName)) {\n logWarn(\n `Project '${projectName}' does not look like a platform layer \u2014 tenants are declared on the tenant platform repo's PLATFORM stack (e.g. mesh-sandbox/platform).`,\n );\n }\n logInfo(`No tenants declared in ${path.basename(resolved.file)}.`);\n return;\n }\n logInfo(`Tenants on stack '${resolved.stack}':`);\n for (const t of tenants) {\n const display = t.displayName ? ` (${t.displayName})` : \"\";\n console.log(` ${chalk.cyan(t.name.padEnd(20))}${t.subdomain ?? \"\"}${chalk.dim(display)}`);\n }\n });\n}\n", "/**\n * mesh tunnel - SSM tunneling to platform services\n *\n * Commands:\n * mesh tunnel dev Start all dev tunnels (temporal + db)\n * mesh tunnel --services Start specific services\n * mesh tunnel --list List available services\n * mesh tunnel external <name> Tunnel to a registered external service\n */\n\nimport { Command } from \"commander\";\nimport { spawn, ChildProcess } from \"child_process\";\nimport * as fs from \"fs\";\nimport * as os from \"os\";\nimport * as path from \"path\";\nimport {\n SecretsManagerClient,\n GetSecretValueCommand,\n} from \"@aws-sdk/client-secrets-manager\";\nimport {\n detectContext,\n getPlatformBastionInfo,\n logInfo,\n logError,\n} from \"../../utils/index.js\";\nimport type { ServiceEndpoint } from \"../../utils/bastion.js\";\n\ninterface TunnelOptions {\n tenant: string;\n env: string;\n list?: boolean;\n services?: string;\n dbPort?: string;\n temporalUiPort?: string;\n temporalFrontendPort?: string;\n}\n\n/**\n * Resolve tenant/env without ceremony: explicit flags win, otherwise the\n * same Pulumi/SST context detection `mesh dev` uses (mesh:tenant + stack\n * file in the current app dir).\n *\n * Returns the detected app `stage` alongside the platform `env` because they\n * are genuinely different values \u2014 detectContext() strips the tenant prefix\n * and runs the result through the platform-env map, so a stack\n * `Pulumi.scu-dev.yaml` yields stage `scu-dev` but platform env `dev`.\n * Callers that key on the app axis (credential secrets) need the former.\n */\nfunction resolveTenantEnv(options: { tenant?: string; env?: string }): {\n tenant: string;\n env: string;\n stage?: string;\n} {\n if (options.tenant && options.env) {\n // Fully explicit: nothing was detected, so there is no app stage to offer \u2014\n // the credential axis falls back to --env, exactly as `mesh db \u2026` does.\n return { tenant: options.tenant, env: options.env };\n }\n // `options.env` is a platform env, not a stage; passing it as detectContext's\n // stage hint is deliberate (it's the best hint available) but does make that\n // function's own \"Stage: \u2026\" log line read as an env when only -e was given.\n const ctx = detectContext(options.env);\n return {\n tenant: options.tenant ?? ctx.tenant,\n env: options.env ?? ctx.platformEnv,\n stage: ctx.stage,\n };\n}\n\n/**\n * aws:region from the nearest Pulumi config in cwd. Prefers the stack actually\n * being targeted; otherwise stack files before the project file, and among\n * several stacks this is a best-effort pick (readdir order).\n */\nfunction readPulumiAwsRegion(stage?: string): string | undefined {\n const preferred = stage ? `Pulumi.${stage}.yaml` : undefined;\n const rank = (f: string): number =>\n f === preferred ? 0 : f === \"Pulumi.yaml\" ? 2 : 1;\n try {\n const files = fs\n .readdirSync(\".\")\n .filter((f) => f.startsWith(\"Pulumi.\") && f.endsWith(\".yaml\"))\n .sort((a, b) => rank(a) - rank(b));\n for (const f of files) {\n const m = fs\n .readFileSync(f, \"utf-8\")\n .match(/^\\s*aws:region:\\s*[\"']?([^\"'\\n]+)[\"']?/m);\n if (m?.[1]) return m[1].trim();\n }\n } catch {\n /* unreadable cwd \u2014 fall through */\n }\n return undefined;\n}\n\n/** `~/.aws` section headers a profile can appear under, in precedence order. */\nfunction awsProfileSections(name: string): Array<[string, string]> {\n return [\n [path.join(os.homedir(), \".aws\", \"config\"), `[profile ${name}]`],\n [path.join(os.homedir(), \".aws\", \"credentials\"), `[${name}]`],\n ];\n}\n\nfunction awsProfileExists(name: string): boolean {\n for (const [file, header] of awsProfileSections(name)) {\n try {\n const lines = fs.readFileSync(file, \"utf-8\").split(\"\\n\");\n if (lines.some((l) => l.trim() === header)) return true;\n } catch {\n /* file absent */\n }\n }\n return false;\n}\n\n/** `region = \u2026` from a specific section of an ini-style `~/.aws` file. */\nexport function parseProfileRegion(\n text: string,\n header: string\n): string | undefined {\n let inSection = false;\n for (const raw of text.split(\"\\n\")) {\n const line = raw.trim();\n if (line.startsWith(\"[\")) {\n inSection = line === header;\n continue;\n }\n if (!inSection) continue;\n const m = line.match(/^region\\s*=\\s*(.+)$/);\n // AWS's shared-config parser strips whitespace-prefixed inline comments\n // (`region = us-east-1 # prod` means us-east-1); match it. The regex\n // already ate leading whitespace, so the first split segment is the value.\n const value = m?.[1]?.split(/\\s+[#;]/)[0]?.trim();\n if (value) return value;\n }\n return undefined;\n}\n\nfunction awsProfileRegion(profile: string | undefined): string | undefined {\n if (!profile) return undefined;\n for (const [file, header] of awsProfileSections(profile)) {\n try {\n const region = parseProfileRegion(fs.readFileSync(file, \"utf-8\"), header);\n if (region) return region;\n } catch {\n /* file absent */\n }\n }\n return undefined;\n}\n\n/**\n * Section headers for the SDK's implicit `[default]` profile. Spelled\n * `[default]` in BOTH files \u2014 `~/.aws/config` has no `[profile default]`\n * form \u2014 so it cannot be routed through awsProfileSections(\"default\").\n */\nexport function awsDefaultProfileSections(): Array<[string, string]> {\n return [\n [path.join(os.homedir(), \".aws\", \"config\"), \"[default]\"],\n [path.join(os.homedir(), \".aws\", \"credentials\"), \"[default]\"],\n ];\n}\n\n/** Region the SDK would take from `[default]` when no named profile is in play. */\nfunction awsDefaultProfileRegion(): string | undefined {\n for (const [file, header] of awsDefaultProfileSections()) {\n try {\n const region = parseProfileRegion(fs.readFileSync(file, \"utf-8\"), header);\n if (region) return region;\n } catch {\n /* file absent */\n }\n }\n return undefined;\n}\n\n/**\n * Fill AWS_PROFILE/AWS_REGION so tunnels run without env-var ceremony:\n * profile by tenant convention ({tenant}-{env}, then {tenant}) when no\n * credentials are already present, then region from the nearest Pulumi config,\n * else that profile's own region. Applies to both the SDK lookups and the\n * spawned `aws ssm start-session`.\n *\n * Order matters: AWS_REGION in the environment outranks a profile's own\n * `region` in both the SDK v3 chain and the `aws` CLI, so the profile must be\n * resolved FIRST and its region consulted BEFORE any platform default \u2014\n * otherwise a stack that isn't in us-east-2 (tests/tenants/bigbank,\n * tests/tenants/mesh/apps/hello are us-east-1) gets silently redirected when\n * run from a directory with no Pulumi.*.yaml. Same call `dev.ts:3157` and\n * `utils/tailscale.ts:611` make.\n *\n * us-east-2 survives only as the last resort, because this module builds its\n * SecretsManagerClient inline (`new SecretsManagerClient({})`) \u2014 aws-auth.ts's\n * DEFAULT_REGION is module-private to that file and does NOT backstop it, so\n * dropping the default outright turns a no-Pulumi/no-profile-region directory\n * into `Region is missing` rather than a working tunnel.\n */\nfunction applyAwsDefaults(tenant: string, env: string, stage?: string): void {\n if (!process.env.AWS_PROFILE && !process.env.AWS_ACCESS_KEY_ID) {\n const profile = [`${tenant}-${env}`, tenant].find(awsProfileExists);\n if (profile) {\n process.env.AWS_PROFILE = profile;\n logInfo(`AWS profile: ${profile} (from ~/.aws, tenant convention)`);\n }\n }\n if (!process.env.AWS_REGION && !process.env.AWS_DEFAULT_REGION) {\n // stack config > the effective profile's own region > platform default.\n // When no named profile is in play the SDK's effective profile is\n // `[default]`, so consult ITS region before inventing us-east-2 \u2014\n // otherwise a plain `[default]`-only setup gets silently redirected.\n const region =\n readPulumiAwsRegion(stage) ??\n (process.env.AWS_PROFILE\n ? awsProfileRegion(process.env.AWS_PROFILE)\n : awsDefaultProfileRegion()) ??\n \"us-east-2\";\n process.env.AWS_REGION = region;\n logInfo(`AWS region: ${region} (auto)`);\n }\n}\n\n/**\n * Service definitions with their local ports and display names\n */\nconst SERVICE_CONFIG: Record<\n string,\n { bastionKey: string; localPort: number; displayName: string }\n> = {\n \"temporal-frontend\": {\n bastionKey: \"temporal-frontend\",\n localPort: 7233,\n displayName: \"Temporal Frontend (gRPC)\",\n },\n \"temporal-ui\": {\n bastionKey: \"temporal-ui\",\n localPort: 8080,\n displayName: \"Temporal Web UI\",\n },\n db: {\n bastionKey: \"rds\",\n localPort: 5432,\n displayName: \"Database (PostgreSQL)\",\n },\n};\n\n/**\n * Service groups for convenience commands\n */\nconst SERVICE_GROUPS: Record<string, string[]> = {\n dev: [\"temporal-frontend\", \"temporal-ui\", \"db\"],\n temporal: [\"temporal-frontend\", \"temporal-ui\"],\n};\n\n/**\n * Get the effective local port for a service, using custom port if provided\n */\nfunction getEffectivePort(serviceName: string, options: TunnelOptions): number {\n const config = SERVICE_CONFIG[serviceName];\n if (!config) return 0;\n\n switch (serviceName) {\n case \"db\":\n return options.dbPort ? parseInt(options.dbPort, 10) : config.localPort;\n case \"temporal-ui\":\n return options.temporalUiPort\n ? parseInt(options.temporalUiPort, 10)\n : config.localPort;\n case \"temporal-frontend\":\n return options.temporalFrontendPort\n ? parseInt(options.temporalFrontendPort, 10)\n : config.localPort;\n default:\n return config.localPort;\n }\n}\n\n/**\n * Parse services from --services flag or group name\n */\nfunction parseServices(input: string): string[] {\n // Check if it's a group name\n if (SERVICE_GROUPS[input]) {\n return SERVICE_GROUPS[input];\n }\n // Otherwise parse as comma-separated list\n return input.split(\",\").map((s) => s.trim());\n}\n\n/**\n * Spawn an SSM tunnel to a service endpoint\n */\nfunction spawnSsmTunnel(\n instanceId: string,\n service: ServiceEndpoint,\n localPort: number\n): ChildProcess {\n return spawn(\n \"aws\",\n [\n \"ssm\",\n \"start-session\",\n \"--target\",\n instanceId,\n \"--document-name\",\n \"AWS-StartPortForwardingSessionToRemoteHost\",\n \"--parameters\",\n JSON.stringify({\n host: [service.host],\n portNumber: [String(service.port)],\n localPortNumber: [String(localPort)],\n }),\n ],\n { stdio: \"inherit\" }\n );\n}\n\n/**\n * List available services\n */\nasync function listServices(options: TunnelOptions): Promise<void> {\n const { tenant, env } = options;\n const bastion = await getPlatformBastionInfo(tenant, env);\n\n console.log(\"\");\n logInfo(`Tenant: ${tenant}, Platform Env: ${env}`);\n console.log(\"\");\n console.log(\"Available services:\");\n console.log(\"\");\n\n for (const [name, config] of Object.entries(SERVICE_CONFIG)) {\n const endpoint = bastion.services[config.bastionKey];\n const status = endpoint ? \"\u2713\" : \"\u2717\";\n const localPort = getEffectivePort(name, options);\n console.log(\n ` ${status} ${name.padEnd(20)} localhost:${localPort} \u2192 ${endpoint?.host ?? \"not available\"}:${endpoint?.port ?? \"\"}`\n );\n }\n\n console.log(\"\");\n console.log(\"Service groups:\");\n for (const [group, services] of Object.entries(SERVICE_GROUPS)) {\n console.log(` ${group.padEnd(20)} ${services.join(\", \")}`);\n }\n\n console.log(\"\");\n logInfo(\"Usage:\");\n console.log(\" mesh tunnel dev # All dev services\");\n console.log(\" mesh tunnel --services temporal # Just temporal services\");\n console.log(\" mesh tunnel --services db # Just database\");\n console.log(\" mesh tunnel external <name> # Registered external service\");\n console.log(\"\");\n}\n\n/**\n * Start tunnels to multiple services\n */\nasync function tunnelServices(\n serviceNames: string[],\n options: TunnelOptions\n): Promise<void> {\n const { tenant, env } = options;\n const bastion = await getPlatformBastionInfo(tenant, env);\n\n // Resolve service names to configs and endpoints\n const servicesToStart: Array<{\n name: string;\n config: (typeof SERVICE_CONFIG)[string];\n endpoint: ServiceEndpoint;\n }> = [];\n\n for (const name of serviceNames) {\n const config = SERVICE_CONFIG[name];\n if (!config) {\n logError(`Unknown service: ${name}`);\n logInfo(`Available services: ${Object.keys(SERVICE_CONFIG).join(\", \")}`);\n process.exit(1);\n }\n\n const endpoint = bastion.services[config.bastionKey];\n if (!endpoint) {\n logError(`Service '${name}' not available in platform bastion.`);\n logInfo(\"Make sure the service is enabled and deployed.\");\n process.exit(1);\n }\n\n servicesToStart.push({ name, config, endpoint });\n }\n\n if (servicesToStart.length === 0) {\n logError(\"No services specified.\");\n process.exit(1);\n }\n\n console.log(\"\");\n logInfo(`Tenant: ${tenant}, Platform Env: ${env}`);\n console.log(\"\");\n logInfo(\"Starting tunnels...\");\n\n for (const { name, config, endpoint } of servicesToStart) {\n const localPort = getEffectivePort(name, options);\n console.log(\n ` ${config.displayName.padEnd(25)} localhost:${localPort} \u2192 ${endpoint.host}:${endpoint.port}`\n );\n }\n\n console.log(\"\");\n logInfo(\"Press Ctrl+C to stop the tunnels\");\n console.log(\"\");\n\n const processes: ChildProcess[] = [];\n\n for (const { name, endpoint } of servicesToStart) {\n const localPort = getEffectivePort(name, options);\n processes.push(spawnSsmTunnel(bastion.instanceId, endpoint, localPort));\n }\n\n // Handle cleanup on exit\n const cleanup = () => {\n for (const proc of processes) {\n proc.kill();\n }\n process.exit(0);\n };\n\n process.on(\"SIGINT\", cleanup);\n process.on(\"SIGTERM\", cleanup);\n\n // Wait for any process to exit\n await Promise.race(\n processes.map(\n (proc) =>\n new Promise<void>((resolve) => {\n proc.on(\"exit\", () => resolve());\n proc.on(\"error\", () => resolve());\n })\n )\n );\n\n cleanup();\n}\n\ninterface ExternalTunnelOptions {\n tenant: string;\n env: string;\n /** App stage detected from cwd, when it differs from the platform env. */\n stage?: string;\n appTenant?: string;\n appStage?: string;\n key?: string;\n port?: string;\n}\n\n/**\n * The credential axis (app tenant/stage) the ExternalService secret is keyed\n * on, which is NOT the platform axis that hosts the bastion.\n *\n * Precedence: explicit --app-tenant/--app-stage, then the stage detected from\n * cwd (a tenant-prefixed stack like `scu-dev` maps to platform env `dev`, and\n * the secret is keyed on the former), then the platform tenant/env.\n */\nexport function resolveCredentialAxis(options: {\n tenant: string;\n env: string;\n stage?: string;\n appTenant?: string;\n appStage?: string;\n}): { appTenant: string; appStage: string } {\n return {\n appTenant: options.appTenant ?? options.tenant,\n appStage: options.appStage ?? options.stage ?? options.env,\n };\n}\n\nfunction isValidPort(port: number): boolean {\n return Number.isInteger(port) && port >= 1 && port <= 65535;\n}\n\n/**\n * Secrets Manager id for an ExternalService's credentials.\n *\n * Mirrors what the primitive builds (ExternalService.ts) and what apps resolve\n * at runtime (libs/secrets): keyed on the APP tenant/stage, with multi-instance\n * (credentials.keyedBy) services storing one secret per instance under the base.\n */\nexport function externalSecretId(\n appTenant: string,\n appStage: string,\n name: string,\n key?: string\n): string {\n const base = `mesh/${appTenant}/${appStage}/external/${name}`;\n return key ? `${base}/${key}` : base;\n}\n\n/**\n * Pull the tunnel endpoint out of a credential secret. The local port defaults\n * to the remote port so `localhost:<same-port>` behaves like the real service.\n * Throws with a user-facing message when the secret isn't tunnelable or the\n * `--port` override isn't a valid port number.\n */\nexport function resolveExternalPorts(\n creds: Record<string, string | number>,\n portOverride?: string\n): { host: string; remotePort: number; localPort: number } {\n const host = typeof creds.host === \"string\" ? creds.host.trim() : \"\";\n const remotePort = Number(creds.port);\n if (!host || !isValidPort(remotePort)) {\n throw new Error(\n \"Secret has no usable host/port fields \u2014 only host:port externals are tunnelable.\"\n );\n }\n\n if (portOverride === undefined) {\n return { host, remotePort, localPort: remotePort };\n }\n\n const localPort = Number(portOverride);\n if (!isValidPort(localPort)) {\n throw new Error(\n `--port must be an integer between 1 and 65535 (got \"${portOverride}\").`\n );\n }\n return { host, remotePort, localPort };\n}\n\n/**\n * Tunnel to a registered external service (ExternalService primitive).\n *\n * The service's credential secret (mesh/{app-tenant}/{app-stage}/external/{name})\n * is the source of truth for host/port \u2014 the same values deployed apps resolve\n * at runtime via resolveCredentials() \u2014 so anything the platform bastion can\n * reach is tunnelable without a per-service CLI entry.\n */\nasync function tunnelExternal(\n name: string,\n options: ExternalTunnelOptions\n): Promise<void> {\n const { tenant, env, key } = options;\n // The bastion lives in the platform tenant/env; the credential secret is\n // keyed on the app tenant/stage. Those are different axes (a platform env\n // like `dev-temporal` can host an app at stage `dev`), so they default to\n // each other but stay separately overridable \u2014 same as `mesh db \u2026`.\n const { appTenant, appStage } = resolveCredentialAxis(options);\n const secretId = externalSecretId(appTenant, appStage, name, key);\n const setHint = `mesh secrets set external/${name}${key ? ` --key=${key}` : \"\"}`;\n\n const sm = new SecretsManagerClient({});\n let creds: Record<string, string | number>;\n try {\n const out = await sm.send(new GetSecretValueCommand({ SecretId: secretId }));\n creds = JSON.parse(out.SecretString ?? \"{}\");\n } catch (err) {\n logError(\n `Could not read ${secretId}: ${err instanceof Error ? err.message : String(err)}`\n );\n logInfo(`Is the external service registered and seeded? (${setHint})`);\n logInfo(\n `Credential axis used: app tenant '${appTenant}', app stage '${appStage}' (override with --app-tenant/--app-stage) \u2014 ` +\n `zero-flag runs key on the stage detected from the app dir, while explicit -t/-e keys on the platform env.`\n );\n if (!key) {\n logInfo(\n \"Multi-instance externals (credentials.keyedBy) store one secret per instance \u2014 pass --key <key>.\"\n );\n }\n process.exit(1);\n }\n\n let host: string;\n let remotePort: number;\n let localPort: number;\n try {\n ({ host, remotePort, localPort } = resolveExternalPorts(creds, options.port));\n } catch (err) {\n logError(err instanceof Error ? err.message : String(err));\n logInfo(`Secret: ${secretId}`);\n process.exit(1);\n }\n\n const bastion = await getPlatformBastionInfo(tenant, env);\n\n console.log(\"\");\n logInfo(`Tenant: ${tenant}, Platform Env: ${env}`);\n if (appTenant !== tenant || appStage !== env) {\n logInfo(`App credentials: tenant=${appTenant}, stage=${appStage}`);\n }\n console.log(\"\");\n console.log(\n ` ${name.padEnd(25)} localhost:${localPort} \u2192 ${host}:${remotePort}`\n );\n console.log(\"\");\n logInfo(\"Press Ctrl+C to stop the tunnel\");\n console.log(\"\");\n\n const proc = spawnSsmTunnel(\n bastion.instanceId,\n { host, port: remotePort },\n localPort\n );\n\n const cleanup = () => {\n proc.kill();\n process.exit(0);\n };\n process.on(\"SIGINT\", cleanup);\n process.on(\"SIGTERM\", cleanup);\n\n await new Promise<void>((resolve) => {\n proc.on(\"exit\", () => resolve());\n proc.on(\"error\", () => resolve());\n });\n\n cleanup();\n}\n\n/**\n * Register tunnel commands with the CLI\n */\nexport function registerTunnelCommands(program: Command): void {\n const tunnel = program\n .command(\"tunnel\")\n .description(\"Start SSM tunnel to platform services\")\n .option(\n \"-t, --tenant <tenant>\",\n \"Platform tenant (default: detected from Pulumi/SST config in cwd)\"\n )\n .option(\n \"-e, --env <env>\",\n \"Platform environment (default: detected from cwd, else dev)\"\n )\n .option(\"-l, --list\", \"List available services\")\n .option(\"-s, --services <services>\", \"Services to tunnel (comma-separated or group name)\")\n .option(\"--db-port <port>\", \"Custom local port for database (default: 5432)\")\n .option(\"--temporal-ui-port <port>\", \"Custom local port for Temporal UI (default: 8080)\")\n .option(\"--temporal-frontend-port <port>\", \"Custom local port for Temporal Frontend (default: 7233)\")\n .argument(\"[group]\", \"Service group to tunnel (e.g., dev, temporal)\")\n .action(\n async (\n group: string | undefined,\n rawOptions: Omit<TunnelOptions, \"tenant\" | \"env\"> & {\n tenant?: string;\n env?: string;\n }\n ) => {\n const { tenant, env, stage } = resolveTenantEnv(rawOptions);\n applyAwsDefaults(tenant, env, stage);\n const options: TunnelOptions = { ...rawOptions, tenant, env };\n\n // Handle --list\n if (options.list) {\n await listServices(options);\n return;\n }\n\n // Determine which services to start\n let services: string[];\n\n if (options.services) {\n // Explicit --services flag\n services = parseServices(options.services);\n } else if (group) {\n // Positional group argument\n services = parseServices(group);\n } else {\n // No services specified - show help\n await listServices(options);\n return;\n }\n\n await tunnelServices(services, options);\n }\n );\n\n tunnel\n .command(\"external\")\n .description(\n \"Tunnel to a registered external service via the platform bastion \" +\n \"(host/port from mesh/{app-tenant}/{app-stage}/external/{name})\"\n )\n .argument(\"<name>\", \"External service name (e.g., plaid-db)\")\n .option(\n \"-t, --tenant <tenant>\",\n \"Platform tenant (default: detected from Pulumi/SST config in cwd)\"\n )\n .option(\n \"-e, --env <env>\",\n \"Platform environment (default: detected from cwd, else dev)\"\n )\n .option(\n \"--app-tenant <tenant>\",\n \"Tenant for the external service's credentials (default: --tenant)\"\n )\n .option(\n \"--app-stage <stage>\",\n \"Stage for the external service's credentials (default: --env)\"\n )\n .option(\n \"-k, --key <key>\",\n \"Instance key for a multi-instance external (credentials.keyedBy)\"\n )\n .option(\n \"-p, --port <port>\",\n \"Local port (default: the service's remote port)\"\n )\n .action(\n async (name: string, _options: ExternalTunnelOptions, command: Command) => {\n // -t/-e are also declared on the parent `tunnel` command, which\n // consumes them wherever they appear \u2014 merge both scopes, then fall\n // back to Pulumi/SST context detection.\n const merged = command.optsWithGlobals<Partial<ExternalTunnelOptions>>();\n const { tenant, env, stage } = resolveTenantEnv(merged);\n applyAwsDefaults(tenant, env, stage);\n await tunnelExternal(name, { ...merged, tenant, env, stage });\n }\n );\n}\n", "import { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\n\nexport const execFileAsync = promisify(execFile);\n\nexport interface VcsTarget {\n baseUrl: string;\n repo?: string;\n}\n\nexport interface CommonOpts {\n url?: string;\n token?: string;\n context?: string;\n}\n\n/** https://host/git/<repo> (origin remote) \u2192 { baseUrl: https://host, repo }. */\nexport function parseRemote(remoteUrl: string): VcsTarget | null {\n const m = remoteUrl.trim().match(/^(https?:\\/\\/[^/]+)\\/git\\/([^/]+?)(?:\\.git)?$/);\n return m ? { baseUrl: m[1]!, repo: m[2]! } : null;\n}\n\nexport async function resolveTarget(\n opts: CommonOpts & { repo?: string; cwd?: string },\n): Promise<VcsTarget> {\n // An explicit base URL (flag or env) overrides only the BASE URL \u2014 it must\n // not suppress origin-derived repo resolution. Commands like `propose` carry\n // no repo argument and rely on the clone's origin remote; returning early\n // here with `repo: undefined` (the prior behaviour) broke them whenever\n // VCS_URL/--url was set. So resolve the repo independently: explicit repo \u2192\n // origin-derived \u2192 undefined.\n const explicitBase = opts.url ?? process.env.VCS_URL;\n\n let originTarget: VcsTarget | null = null;\n try {\n const { stdout } = await execFileAsync(\"git\", [\"remote\", \"get-url\", \"origin\"], {\n cwd: opts.cwd ?? process.cwd(),\n });\n originTarget = parseRemote(stdout);\n } catch {\n // not in a clone\n }\n\n const baseUrl = (explicitBase ?? originTarget?.baseUrl)?.replace(/\\/$/, \"\");\n if (!baseUrl) {\n throw new Error(\n \"vcs service URL not found: pass --url, set VCS_URL, or run inside a vcs clone\",\n );\n }\n return { baseUrl, repo: opts.repo ?? originTarget?.repo };\n}\n\nexport async function resolveToken(opts: CommonOpts): Promise<string> {\n if (opts.token) return opts.token;\n if (process.env.VCS_TOKEN) return process.env.VCS_TOKEN;\n if (opts.context) {\n const { getValidToken } = await import(\"../login.js\");\n const token = await getValidToken(opts.context);\n if (token) return token;\n }\n throw new Error(\n \"no token: pass --token, set VCS_TOKEN, or pass --context <platform-context> (after mesh login)\",\n );\n}\n\n/** Minimal authenticated JSON call against the vcs API. */\nexport async function vcsApi(\n baseUrl: string,\n token: string,\n path: string,\n method = \"GET\",\n body?: unknown,\n): Promise<unknown> {\n const res = await fetch(`${baseUrl}${path}`, {\n method,\n headers: {\n authorization: `Bearer ${token}`,\n ...(body !== undefined ? { \"content-type\": \"application/json\" } : {}),\n },\n ...(body !== undefined ? { body: JSON.stringify(body) } : {}),\n });\n const data = (await res.json().catch(() => ({}))) as Record<string, unknown>;\n if (!res.ok) {\n throw new Error(\n `${method} ${path} failed (${res.status}): ${String(data.error ?? \"unknown error\")}`,\n );\n }\n return data;\n}\n", "import { execFileAsync, resolveToken, type CommonOpts } from \"./common.js\";\n\nexport async function cloneCommand(\n repo: string,\n dest: string | undefined,\n opts: CommonOpts,\n): Promise<void> {\n const baseUrl = (opts.url ?? process.env.VCS_URL)?.replace(/\\/$/, \"\");\n if (!baseUrl) throw new Error(\"clone requires --url or VCS_URL\");\n const token = await resolveToken(opts);\n await execFileAsync(\"git\", [\n \"clone\",\n \"-c\",\n `http.extraHeader=Authorization: Bearer ${token}`,\n `${baseUrl}/git/${repo}`,\n dest ?? repo,\n ]);\n // Persist the auth header for future fetches in THIS clone only.\n // Dev-grade: tokens land in .git/config \u2014 revisit with a credential helper\n // once non-dev tokens are routine.\n await execFileAsync(\n \"git\",\n [\"config\", \"http.extraHeader\", `Authorization: Bearer ${token}`],\n { cwd: dest ?? repo },\n );\n console.log(\n `cloned ${repo} \u2192 ${dest ?? repo} (read-only remote; use 'mesh vcs propose' to submit changes)`,\n );\n}\n", "/**\n * `mesh vcs get <repo> <path>` \u2014 read a SPECIFIC path (a file or subtree) from\n * a repo, never the whole repo. The discretionary doc-pull the conversation\n * `references[]` catalog points at: a `pull` bundle lists which repos/docs a\n * conversation touched, and this fetches just the ones the agent/user wants.\n *\n * Resolves the vcs service either from an agent target (`--target`, via the\n * shared agent-targets registry \u2192 derived `vcs.<baseDomain>` + mesh-login\n * token) or directly (`--url` + `--token`/`--context`).\n */\nimport { writeFile, mkdir } from \"node:fs/promises\";\nimport { join, dirname } from \"node:path\";\nimport { createVcsFolderReader, deriveVcsBaseUrl } from \"@mesh-tech/agent-targets\";\nimport { resolveTarget } from \"../agent-api-client.js\";\nimport { getValidToken } from \"../login.js\";\nimport { resolveToken, type CommonOpts } from \"./common.js\";\nimport { logInfo } from \"../../utils/log.js\";\n\ninterface GetOpts extends CommonOpts {\n target?: string;\n output?: string;\n}\n\nexport async function getCommand(repo: string, path: string, opts: GetOpts): Promise<void> {\n let vcsBaseUrl: string | null;\n let token: string | undefined;\n\n if (opts.target) {\n const t = resolveTarget({ target: opts.target });\n vcsBaseUrl = deriveVcsBaseUrl(t.apiBaseUrl);\n token = t.token ?? (await getValidToken(t.loginContext ?? \"mesh.dev\")) ?? undefined;\n } else {\n vcsBaseUrl = (opts.url ?? process.env.VCS_URL)?.replace(/\\/$/, \"\") ?? null;\n token = await resolveToken(opts);\n }\n\n if (!vcsBaseUrl) throw new Error(\"vcs get requires --target <name> or --url <vcs-url>\");\n if (!token) throw new Error(\"no token: pass --target (after mesh login), or --token / --context\");\n\n const reader = createVcsFolderReader({ vcsBaseUrl, token });\n try {\n const { ref, files } = await reader.readPath(repo, path);\n if (files.length === 0) {\n logInfo(`no files at ${repo}:${path}`);\n return;\n }\n if (opts.output) {\n for (const f of files) {\n const abs = join(opts.output, f.path);\n await mkdir(dirname(abs), { recursive: true });\n await writeFile(abs, f.contents);\n }\n logInfo(`wrote ${files.length} file(s) from ${repo}:${path} (${ref}) \u2192 ${opts.output}`);\n } else {\n for (const f of files) {\n if (files.length > 1) process.stdout.write(`\\n=== ${f.path} ===\\n`);\n process.stdout.write(f.contents);\n }\n }\n } finally {\n await reader.cleanup();\n }\n}\n", "import { resolveTarget, resolveToken, vcsApi, type CommonOpts } from \"./common.js\";\n\nasync function call(\n opts: CommonOpts,\n repo: string,\n path: string,\n method = \"GET\",\n body?: unknown,\n): Promise<unknown> {\n const target = await resolveTarget({ ...opts, repo });\n const token = await resolveToken(opts);\n return vcsApi(target.baseUrl, token, `/v1/repos/${repo}${path}`, method, body);\n}\n\nexport async function draftsListCommand(\n repo: string,\n opts: CommonOpts & { all?: boolean },\n): Promise<void> {\n const data = (await call(opts, repo, `/drafts${opts.all ? \"?all=true\" : \"\"}`)) as {\n drafts: Array<{ draftId: string; title: string; status: string; state: string; updatedAt: string }>;\n };\n const drafts = data.drafts;\n if (drafts.length === 0) {\n console.log(\"no drafts\");\n return;\n }\n for (const d of drafts) {\n console.log(`${d.draftId} [${d.state}] ${d.title} (updated ${d.updatedAt})`);\n }\n}\n\nexport async function draftsShowCommand(\n repo: string,\n draftId: string,\n opts: CommonOpts,\n): Promise<void> {\n const d = (await call(opts, repo, `/drafts/${draftId}`)) as {\n draftId: string; title: string; status: string; state: string;\n headSha?: string; mergeable?: boolean;\n changedFiles?: Array<{ status: \"A\" | \"M\" | \"D\"; path: string }>;\n };\n console.log(`${d.draftId} [${d.state}] ${d.title}`);\n if (d.headSha !== undefined) {\n console.log(`head: ${d.headSha}`);\n }\n if (d.mergeable === false) {\n console.log(\"\u26A0 the page changed while this draft was being edited\");\n }\n if (d.changedFiles) {\n for (const f of d.changedFiles) {\n console.log(` ${f.status} ${f.path}`);\n }\n }\n}\n\nexport async function draftsCreateCommand(\n repo: string,\n opts: CommonOpts & { title?: string },\n): Promise<void> {\n const d = (await call(opts, repo, \"/drafts\", \"POST\", opts.title ? { title: opts.title } : {})) as {\n draftId: string; headSha: string; title: string; state: string;\n };\n console.log(`draft ${d.draftId} created \u2014 submit with: mesh vcs drafts submit ${repo} ${d.draftId}`);\n}\n\nexport async function draftsSubmitCommand(\n repo: string,\n draftId: string,\n opts: CommonOpts & { note?: string },\n): Promise<void> {\n const d = (await call(\n opts,\n repo,\n `/drafts/${draftId}/submit`,\n \"POST\",\n opts.note ? { note: opts.note } : {},\n )) as { draftId: string; proposalId: string; state: string; mergeable: boolean };\n console.log(`draft ${d.draftId} submitted for review [${d.state}]`);\n}\n\nexport async function draftsDiscardCommand(\n repo: string,\n draftId: string,\n opts: CommonOpts,\n): Promise<void> {\n const d = (await call(opts, repo, `/drafts/${draftId}/discard`, \"POST\", {})) as {\n draftId: string; state: string;\n };\n console.log(`draft ${d.draftId} discarded`);\n}\n", "import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport {\n execFileAsync,\n resolveTarget,\n resolveToken,\n vcsApi,\n type CommonOpts,\n} from \"./common.js\";\n\nexport interface FileChange {\n status: string;\n path: string;\n}\n\n/** Parse `git status --porcelain -z` output into adds/modifies/deletes.\n *\n * Porcelain -z format: records are NUL-terminated. Normal record: `XY PATH`.\n * Rename/copy record (X or Y is R/C): `XY PATH\\0ORIGPATH` \u2014 the FOLLOWING NUL\n * field is the source/original path. Renames expand to a delete of the old path\n * plus a write of the new path. Copies only emit a write of the new path (the\n * source still exists on disk). This stateful walk avoids mis-parsing the bare\n * orig-path token as a status-prefixed record.\n */\nexport function parseStatus(out: string): FileChange[] {\n const tokens = out.split(\"\\0\");\n const changes: FileChange[] = [];\n let i = 0;\n while (i < tokens.length) {\n const entry = tokens[i];\n if (!entry) {\n i++;\n continue; // trailing empty from the final NUL\n }\n const status = entry.slice(0, 2); // XY \u2014 do NOT trim before classifying\n const newPath = entry.slice(3);\n const isRename =\n status[0] === \"R\" || status[1] === \"R\";\n const isCopy =\n !isRename && (status[0] === \"C\" || status[1] === \"C\");\n if (isRename || isCopy) {\n const origPath = tokens[i + 1] ?? \"\";\n i += 2; // consume the orig-path field too\n if (isRename && origPath && !origPath.endsWith(\"/\")) {\n changes.push({ status: \"D\", path: origPath });\n }\n if (newPath && !newPath.endsWith(\"/\")) {\n changes.push({ status: \"A\", path: newPath });\n }\n continue;\n }\n i++;\n if (newPath.length > 0 && !newPath.endsWith(\"/\")) {\n changes.push({ status: status.trim(), path: newPath });\n }\n }\n return changes;\n}\n\nexport interface ProposeOpts extends CommonOpts {\n message?: string;\n proposalId?: string;\n revise?: string;\n mergeParent?: string;\n}\n\nexport async function proposeCommand(opts: ProposeOpts): Promise<void> {\n const cwd = process.cwd();\n const target = await resolveTarget(opts);\n if (!target.repo) {\n throw new Error(\"could not determine repo from the origin remote (pass --url from a clone)\");\n }\n const token = await resolveToken(opts);\n\n // --untracked-files=all: a brand-new directory otherwise collapses to a\n // single \"?? dir/\" entry, which parseStatus skips \u2014 silently dropping the\n // new files inside it from the proposal.\n const { stdout: statusOut } = await execFileAsync(\n \"git\",\n [\"status\", \"--porcelain\", \"-z\", \"--untracked-files=all\"],\n { cwd },\n );\n const changes = parseStatus(statusOut);\n if (changes.length === 0) {\n console.log(\"working tree clean \u2014 nothing to propose\");\n return;\n }\n\n const operations = await Promise.all(\n changes.map(async (c) =>\n c.status.startsWith(\"D\")\n ? { op: \"delete\" as const, path: c.path }\n : {\n op: \"write\" as const,\n path: c.path,\n content: await readFile(join(cwd, c.path), \"utf8\"),\n },\n ),\n );\n\n // New proposals diff against the clone's HEAD; revisions against the\n // proposal's current head (the author proposed from this clone).\n let baseCommit: string;\n if (opts.revise) {\n const state = (await vcsApi(\n target.baseUrl,\n token,\n `/v1/repos/${target.repo}/proposals/${opts.revise}`,\n )) as { headSha?: string };\n if (!state.headSha) throw new Error(`cannot resolve head of proposal ${opts.revise}`);\n baseCommit = state.headSha;\n } else {\n const { stdout: head } = await execFileAsync(\"git\", [\"rev-parse\", \"HEAD\"], { cwd });\n baseCommit = head.trim();\n }\n\n const body = {\n ...(opts.proposalId && !opts.revise ? { proposalId: opts.proposalId } : {}),\n baseCommit,\n message: opts.message ?? `Update ${operations.length} file(s)`,\n operations,\n ...(opts.mergeParent ? { mergeParent: opts.mergeParent } : {}),\n };\n const path = opts.revise\n ? `/v1/repos/${target.repo}/proposals/${opts.revise}/revisions`\n : `/v1/repos/${target.repo}/proposals`;\n const data = (await vcsApi(target.baseUrl, token, path, \"POST\", body)) as {\n proposalId: string;\n sha: string;\n };\n console.log(\n `proposal ${data.proposalId} @ ${data.sha.slice(0, 8)} \u2014 review: mesh vcs show ${target.repo} ${data.proposalId} --url ${target.baseUrl}`,\n );\n}\n", "import { resolveTarget, resolveToken, vcsApi, type CommonOpts } from \"./common.js\";\n\nasync function call(\n opts: CommonOpts,\n repo: string,\n path: string,\n method = \"GET\",\n body?: unknown,\n): Promise<unknown> {\n const target = await resolveTarget({ ...opts, repo });\n const token = await resolveToken(opts);\n return vcsApi(target.baseUrl, token, `/v1/repos/${repo}${path}`, method, body);\n}\n\nexport async function proposalsCommand(repo: string, opts: CommonOpts): Promise<void> {\n console.log(JSON.stringify(await call(opts, repo, \"/proposals\"), null, 2));\n}\n\nexport async function showCommand(\n repo: string,\n id: string,\n opts: CommonOpts,\n): Promise<void> {\n console.log(JSON.stringify(await call(opts, repo, `/proposals/${id}`), null, 2));\n}\n\nexport async function diffCommand(\n repo: string,\n id: string,\n opts: CommonOpts,\n): Promise<void> {\n const d = (await call(opts, repo, `/proposals/${id}/diff`)) as { patch: string };\n console.log(d.patch);\n}\n\nexport async function approveCommand(\n repo: string,\n id: string,\n opts: CommonOpts & { sha?: string },\n): Promise<void> {\n const sha =\n opts.sha ??\n ((await call(opts, repo, `/proposals/${id}`)) as { headSha: string }).headSha;\n await call(opts, repo, `/proposals/${id}/approve`, \"POST\", { sha });\n console.log(`approved ${id} @ ${sha.slice(0, 8)}`);\n}\n\nexport async function rejectCommand(\n repo: string,\n id: string,\n opts: CommonOpts & { reason?: string },\n): Promise<void> {\n await call(opts, repo, `/proposals/${id}/reject`, \"POST\", { reason: opts.reason });\n console.log(`rejected ${id}`);\n}\n\nexport async function commentCommand(\n repo: string,\n id: string,\n text: string,\n opts: CommonOpts,\n): Promise<void> {\n await call(opts, repo, `/proposals/${id}/comment`, \"POST\", { text });\n console.log(\"comment added\");\n}\n\nexport async function requestChangesCommand(\n repo: string,\n id: string,\n opts: CommonOpts & { note?: string },\n): Promise<void> {\n await call(opts, repo, `/proposals/${id}/request-changes`, \"POST\", { note: opts.note });\n console.log(`changes requested on ${id}`);\n}\n", "import type { Command } from \"commander\";\nimport { cloneCommand } from \"./clone.js\";\nimport { getCommand } from \"./get.js\";\nimport {\n draftsCreateCommand,\n draftsDiscardCommand,\n draftsListCommand,\n draftsShowCommand,\n draftsSubmitCommand,\n} from \"./drafts.js\";\nimport { proposeCommand } from \"./propose.js\";\nimport {\n approveCommand,\n commentCommand,\n diffCommand,\n proposalsCommand,\n rejectCommand,\n requestChangesCommand,\n showCommand,\n} from \"./review.js\";\n\nfunction withCommon(cmd: Command): Command {\n return cmd\n .option(\"--url <url>\", \"vcs service URL (or VCS_URL, or derived from origin remote)\")\n .option(\"--token <token>\", \"bearer token (or VCS_TOKEN)\")\n .option(\"--context <context>\", \"mesh login context to mint a token from\");\n}\n\nexport function registerVcsCommands(program: Command): void {\n const vcs = program\n .command(\"vcs\")\n .description(\"Versioned content repos (mesh.vcs): clone, get, propose, review\");\n\n withCommon(\n vcs.command(\"clone <repo> [dest]\").description(\"Clone a repo (read-only remote)\"),\n ).action(cloneCommand);\n\n withCommon(\n vcs\n .command(\"get <repo> <path>\")\n .description(\"Read a specific path (file or subtree) from a repo \u2014 one doc, not the whole repo\")\n .option(\"--target <name>\", \"agent target (agent-targets registry) to derive the vcs URL + auth\")\n .option(\"-o, --output <dir>\", \"write file(s) here instead of stdout\"),\n ).action(getCommand);\n\n withCommon(\n vcs\n .command(\"propose\")\n .description(\"Propose the working tree's changes (run inside a clone)\")\n .option(\"-m, --message <message>\", \"proposal message\")\n .option(\"--proposal-id <id>\", \"explicit proposal id\")\n .option(\"--revise <id>\", \"add a revision to an existing proposal\")\n .option(\"--merge-parent <sha>\", \"conflict resolution: main sha incorporated\"),\n ).action(proposeCommand);\n\n withCommon(vcs.command(\"proposals <repo>\").description(\"List open proposals\")).action(\n proposalsCommand,\n );\n withCommon(vcs.command(\"show <repo> <id>\").description(\"Show proposal state\")).action(\n showCommand,\n );\n withCommon(vcs.command(\"diff <repo> <id>\").description(\"Show proposal diff\")).action(\n diffCommand,\n );\n withCommon(\n vcs\n .command(\"approve <repo> <id>\")\n .description(\"Approve at the current head (payload-bound)\")\n .option(\"--sha <sha>\", \"approve a specific head sha\"),\n ).action(approveCommand);\n withCommon(\n vcs\n .command(\"reject <repo> <id>\")\n .description(\"Reject a proposal\")\n .option(\"--reason <reason>\", \"rejection reason\"),\n ).action(rejectCommand);\n withCommon(\n vcs.command(\"comment <repo> <id> <text>\").description(\"Comment on a proposal\"),\n ).action(commentCommand);\n withCommon(\n vcs\n .command(\"request-changes <repo> <id>\")\n .description(\"Ask the author for changes (review stays open)\")\n .option(\"--note <note>\", \"what needs to change\"),\n ).action(requestChangesCommand);\n\n const drafts = vcs.command(\"drafts\").description(\"Work-in-progress drafts\");\n withCommon(\n drafts.command(\"list <repo>\").description(\"List open drafts\").option(\"--all\", \"include closed drafts\"),\n ).action(draftsListCommand);\n withCommon(drafts.command(\"show <repo> <id>\").description(\"Show draft status\")).action(\n draftsShowCommand,\n );\n withCommon(\n drafts\n .command(\"create <repo>\")\n .description(\"Create a draft\")\n .option(\"--title <title>\", \"draft title\"),\n ).action(draftsCreateCommand);\n withCommon(\n drafts\n .command(\"submit <repo> <id>\")\n .description(\"Submit a draft for review\")\n .option(\"--note <note>\", \"note to reviewers\"),\n ).action(draftsSubmitCommand);\n withCommon(drafts.command(\"discard <repo> <id>\").description(\"Discard a draft\")).action(\n draftsDiscardCommand,\n );\n}\n", "/**\n * Workflow Intermediate Representation (WorkflowIR)\n *\n * Canonical graph model used by the workflow visualizer and patch stream.\n * This file intentionally contains browser-safe types + pure patch helpers.\n */\n\nexport interface WorkflowIR {\n name: string;\n description: string;\n nodes: WorkflowNode[];\n edges: WorkflowEdge[];\n /** Ordered node IDs for the \"happy path\" spine in the visualizer. */\n mainPath: string[];\n /**\n * Signal handlers registered by the workflow \u2014 part of the workflow's\n * external interface, not its sequential flow.\n */\n signals?: WorkflowHandler[];\n /**\n * Query handlers registered by the workflow \u2014 synchronous read-only\n * accessors into workflow state.\n */\n queries?: WorkflowHandler[];\n /**\n * Update handlers (validate + handle) registered by the workflow.\n */\n updates?: WorkflowHandler[];\n /**\n * Shared UI spec registry \u2014 json-render specs keyed by \"workflow/view\".\n * Nodes reference specs via their uiSpec.workflow + uiSpec.view fields.\n * Declared once here, consumed by any number of nodes with different state.\n */\n uiSpecs?: Record<string, unknown>;\n}\n\n/** A signal, query, or update handler registered by the workflow. */\nexport interface WorkflowHandler {\n /** Handler name (e.g. \"submitUserMessage\") */\n name: string;\n /** Human-readable label */\n label: string;\n /** Description from nearby comment or JSDoc */\n description?: string;\n}\n\ninterface WorkflowNodeBase {\n id: string;\n label: string;\n description?: string;\n /** Description from a @guard annotation that gates this node. */\n guardDescription?: string;\n /** When present, this node has an associated UI view that can be drilled into. */\n uiSpec?: UISpec;\n /** Draft \"what might this look like\" copy for a UI not yet built (no spec yet). Set during\n * design for human-facing nodes; the node-detail offers to build it. */\n uiIntent?: string;\n /** Reference to the built ui-design entity (a `uiDesignWorkflow`) once its UI has been built.\n * The design lives in its own entity; the node holds only this reference. */\n uiDesign?: { workflowId: string; title?: string };\n}\n\n/**\n * UI spec reference \u2014 identifies a json-render view to display.\n * Nodes with uiSpec are drillable: clicking opens a UIRenderPanel\n * instead of a WorkflowCanvas column.\n */\nexport interface UISpec {\n /** Workflow name (registry key) the UI belongs to */\n workflow: string;\n /** View name within the workflow (e.g. \"entry\", \"approval\", \"result\") */\n view: string;\n /** Inline json-render spec \u2014 when provided, rendered directly without fetching. */\n spec?: unknown;\n /** Initial state to pass to the renderer. Lets multiple nodes reuse the same\n * spec with different state (e.g. form vs. read-only confirmation). */\n state?: Record<string, unknown>;\n}\n\nexport interface StartNode extends WorkflowNodeBase {\n type: \"start\";\n /** JSON Schema describing the workflow's input parameter */\n inputSchema?: JsonSchema;\n /**\n * Rendering hint: a synthesized parallel fork bar (from a layout's\n * collapseParallelFanOuts) renders as a span bar, not a pill. Ignored by the\n * interpreter \u2014 purely a diagram concern. (Consumed by @mesh-tech/canvas-workflow.)\n */\n role?: \"fork\";\n}\n\nexport interface EndNode extends WorkflowNodeBase {\n type: \"end\";\n outcome?: \"success\" | \"failure\";\n /** JSON Schema describing the workflow's return value */\n outputSchema?: JsonSchema;\n /**\n * Rendering hint: a synthesized parallel join bar renders as a span bar, not\n * a pill. Ignored by the interpreter \u2014 purely a diagram concern.\n */\n role?: \"join\";\n}\n\nexport interface ActionNode extends WorkflowNodeBase {\n type: \"action\";\n actionType?: string;\n operation?: string;\n /** Semantic category for icon selection: data, notification, approval, human, document, financial */\n category?: string;\n /** Guard condition \u2014 when set, this action only runs if the condition is true. */\n condition?: string;\n /** JSON Schema describing the activity's input parameter(s) */\n inputSchema?: JsonSchema;\n /** JSON Schema describing the activity's return value */\n outputSchema?: JsonSchema;\n // --- Execution truth (consumed by the IR interpreter; rendering ignores). ---\n // Expression fields (`predicate`, `inputBinding`, `forEach`) are evaluated in the\n // workflow expression language (currently CEL). Names are language-neutral by design.\n /** Capability/service to dispatch this action to (canonical had only `operation`). */\n service?: string;\n /** Availability overlay stamped at enrichment: false = the bound operation is\n * not enabled in the deployment (designable, but the interpreter refuses to run\n * it until enabled). undefined = not overlaid / not gated. */\n available?: boolean;\n /** Input mapping: an expression over the run context (input + prior node outputs)\n * producing this action's input value. Omitted \u2192 the workflow input. Validated\n * against `inputSchema` before dispatch (fail-closed). */\n inputBinding?: string;\n /** Saga compensation: op run in reverse if a later step fails. */\n compensation?: { service: string; operation: string };\n}\n\n/**\n * Subset of JSON Schema used to describe workflow/activity data shapes.\n * Supports objects, arrays, unions, primitives, and descriptions.\n */\nexport interface JsonSchema {\n /** JSON Schema type */\n type?: \"string\" | \"number\" | \"integer\" | \"boolean\" | \"object\" | \"array\" | \"null\";\n /** Type name from source (e.g., \"AgentWorkflowInput\", \"LLMResult\") */\n title?: string;\n /** Description from JSDoc comment */\n description?: string;\n /** Object properties */\n properties?: Record<string, JsonSchema>;\n /** Required property names */\n required?: string[];\n /** Array item schema */\n items?: JsonSchema;\n /** Union types (TypeScript `A | B`) */\n anyOf?: JsonSchema[];\n /** Constant/literal value */\n const?: string | number | boolean;\n /** Enum values */\n enum?: (string | number | boolean | null)[];\n /** Whether the value can be undefined (TypeScript optional) */\n optional?: boolean;\n}\n\nexport interface DecisionNode extends WorkflowNodeBase {\n type: \"decision\";\n /** Human-legible label (rendering). */\n condition?: string;\n /** Execution truth: the branch predicate expression (interpreter evaluates this;\n * `condition` is its rendered label). \"full truth in the IR; legibility is a\n * render policy.\" Language-neutral name; currently CEL. */\n predicate?: string;\n}\n\nexport interface WaitNode extends WorkflowNodeBase {\n type: \"wait\";\n waitFor?: string;\n timeout?: string;\n /** Guard condition \u2014 when set, this wait only happens if the condition is true. */\n condition?: string;\n}\n\nexport interface ParallelNode extends WorkflowNodeBase {\n type: \"parallel\";\n branches?: string[];\n /** Representative sub-graph for drill-down (e.g. the child workflow executed per branch). */\n childGraph?: WorkflowIR | null;\n /** Execution truth: the concrete branch sub-graphs run concurrently (Promise.all).\n * Rendering uses `branches`/`childGraph`; the interpreter uses this. */\n branchGraphs?: WorkflowIR[];\n}\n\nexport interface ChildWorkflowNode extends WorkflowNodeBase {\n type: \"child_workflow\";\n /** Temporal workflow type name. */\n workflowType: string;\n taskQueue?: string;\n /** Embedded sub-graph (null if not yet resolved). */\n childGraph?: WorkflowIR | null;\n}\n\n/**\n * Logical group \u2014 represents a collapsible compound step containing\n * an inner sub-graph. Used for:\n * - for-each loops (the body is the childGraph)\n * - inlined function calls (the function body is the childGraph)\n * - signal/query handler registration blocks\n *\n * Rendered like a child_workflow node: single node in the parent graph,\n * drill-down reveals the childGraph.\n */\nexport interface GroupNode extends WorkflowNodeBase {\n type: \"group\";\n /** What kind of grouping: loop, function, handlers, etc. */\n groupType: \"loop\" | \"function\" | \"handlers\" | \"setup\" | \"guard\";\n /**\n * Guard condition \u2014 when groupType is \"guard\", this is the condition\n * that gates execution. Rendered with dashed border, no Start/End.\n */\n condition?: string;\n /** Embedded sub-graph with the group's inner nodes. */\n childGraph: WorkflowIR;\n // --- Execution truth (consumed by the IR interpreter; rendering ignores). ---\n /** groupType \"guard\": predicate expression gating the inline body (`condition` = label). */\n predicate?: string;\n /** groupType \"loop\": expression yielding the collection to iterate. */\n forEach?: string;\n}\n\nexport interface NexusOperationNode extends WorkflowNodeBase {\n type: \"nexus_operation\";\n /** Nexus operation name. */\n operation: string;\n /** Nexus service name. */\n service: string;\n /** Configured endpoint name. */\n endpoint?: string;\n /** Availability overlay stamped at enrichment: false = the bound operation is\n * not enabled in the deployment (designable, but the interpreter refuses to run\n * it until enabled). undefined = not overlaid / not gated. */\n available?: boolean;\n /** Input mapping expression over the run context producing the op input\n * (validated against the op's input schema before dispatch). */\n inputBinding?: string;\n /** Backing implementation \u2014 may be unknown (opaque). */\n backing?: {\n type: \"workflow\" | \"activity\" | \"unknown\";\n workflowType?: string;\n namespace?: string;\n backingGraph?: WorkflowIR | null;\n };\n}\n\n/**\n * Placeholder \u2014 a design-phase stub for a service that doesn't exist yet.\n *\n * Rendered with dashed border, amber/yellow color, and a stub icon.\n * During Play mode, the node pulses while waiting for a mock response.\n * The Zod-derived schemas (inputSchema/outputSchema) define the contract\n * that will become the real service's types.\n */\nexport interface PlaceholderNode extends WorkflowNodeBase {\n type: \"placeholder\";\n /** Raw placeholder name (used as Redis/signal key) */\n name: string;\n /** JSON Schema for the placeholder's input (derived from Zod @input tag) */\n inputSchema?: JsonSchema;\n /** JSON Schema for the placeholder's output (derived from Zod @output tag) */\n outputSchema?: JsonSchema;\n /** References to saved scenarios for this placeholder */\n scenarios?: Array<{ name: string; id: string }>;\n}\n\n/**\n * UI node \u2014 a step where the UI *is* the action (entry form, result display,\n * approval screen). Always drillable: clicking opens a UIRenderPanel column.\n */\nexport interface UINode extends WorkflowNodeBase {\n type: \"ui\";\n /** The UI spec to render when drilled into. Optional: a ui node can exist in a DRAFT state \u2014\n * a `uiIntent` describing the screen with no spec yet \u2014 before its UI is built (which attaches\n * a `uiDesign` reference). Legacy nodes carry an inline/registry `uiSpec` instead. */\n uiSpec?: UISpec;\n}\n\nexport type WorkflowNode =\n | StartNode\n | EndNode\n | ActionNode\n | DecisionNode\n | WaitNode\n | ParallelNode\n | ChildWorkflowNode\n | NexusOperationNode\n | GroupNode\n | PlaceholderNode\n | UINode;\n\nexport interface WorkflowEdge {\n from: string;\n to: string;\n /** When `from` is a group node, the childGraph terminal `end` id this edge\n * continues from (the group's typed exit). Absent on edges out of non-group\n * nodes and on a legacy single-exit group's sole edge. */\n fromExit?: string;\n label?: string;\n isMainPath?: boolean;\n isExceptional?: boolean;\n isTimeout?: boolean;\n}\n\n/** Base patch operations on the workflow IR. */\ntype WorkflowPatchOp =\n | { op: \"replace\"; workflow: WorkflowIR }\n | { op: \"addNode\"; node: WorkflowNode; index?: number }\n | { op: \"updateNode\"; nodeId: string; patch: Partial<Omit<WorkflowNode, \"id\">> }\n | { op: \"removeNode\"; nodeId: string; removeAttachedEdges?: boolean }\n | {\n op: \"addEdge\";\n from: string;\n to: string;\n fromExit?: string;\n label?: string;\n index?: number;\n isMainPath?: boolean;\n isExceptional?: boolean;\n isTimeout?: boolean;\n }\n | {\n op: \"updateEdge\";\n from: string;\n to: string;\n patch: Partial<Omit<WorkflowEdge, \"from\" | \"to\">>;\n }\n | { op: \"removeEdge\"; from: string; to: string }\n | {\n op: \"group\";\n /** Existing node ids at this level to wrap into the new group. */\n nodeIds: string[];\n /** Id for the new group node. */\n groupId: string;\n /** Label for the new group node. */\n label: string;\n /** Defaults to \"function\" (a named sub-process). */\n groupType?: \"loop\" | \"function\" | \"handlers\" | \"setup\" | \"guard\";\n }\n | { op: \"setMainPath\"; mainPath: string[] }\n | { op: \"setUiSpecs\"; uiSpecs: Record<string, unknown> }\n | { op: \"setMeta\"; name?: string; description?: string; signals?: WorkflowHandler[] }\n | { op: \"batch\"; patches: WorkflowPatch[] };\n\n/**\n * A patch operation, optionally scoped to a child workflow.\n *\n * When `scope` is provided, the patch targets a nested child graph.\n * Each entry is a node ID whose `childGraph` (or `backing.backingGraph`)\n * is traversed to reach the target workflow.\n *\n * Example: `{ op: \"updateNode\", nodeId: \"wait_4\", scope: [\"action_1\"], patch: { ... } }`\n * applies the updateNode to the childGraph of node \"action_1\".\n */\nexport type WorkflowPatch = WorkflowPatchOp & { scope?: string[] };\n\n/**\n * Compute the happy path via BFS from start to a success end node.\n * Prioritises isMainPath edges and avoids exceptional/timeout edges,\n * falling back to any end node, then to allowing exceptional edges.\n *\n * Note: among equal-length paths the result depends on BFS enqueue\n * order, not a true \"shortest\" guarantee. This is acceptable because\n * workflow graphs rarely have competing equal-length alternatives.\n *\n * Used by both the AST extractor and the runtime normalizer to ensure\n * consistent main-path computation.\n */\nexport function computeHappyPath(nodes: WorkflowNode[], edges: WorkflowEdge[]): string[] {\n const startNode = nodes.find((n) => n.type === \"start\");\n const endNodes = nodes.filter((n) => n.type === \"end\");\n if (!startNode || endNodes.length === 0) return [];\n\n const adjacency = new Map<string, WorkflowEdge[]>();\n for (const edge of edges) {\n const list = adjacency.get(edge.from) ?? [];\n list.push(edge);\n adjacency.set(edge.from, list);\n }\n\n // Build a set of wait node IDs \u2014 paths through waits are deprioritized\n // since they require external signals (human approval, webhooks, etc.)\n const waitNodeIds = new Set(nodes.filter((n) => n.type === \"wait\").map((n) => n.id));\n\n /** Check if a node is reachable from a given start within a few hops via a wait node. */\n function pathHasWait(startId: string): boolean {\n const visited = new Set<string>();\n const queue = [startId];\n for (let depth = 0; depth < 6 && queue.length > 0; depth++) {\n const next: string[] = [];\n for (const id of queue) {\n if (waitNodeIds.has(id)) return true;\n if (visited.has(id)) continue;\n visited.add(id);\n for (const e of adjacency.get(id) ?? []) {\n if (!e.isExceptional && !e.isTimeout) next.push(e.to);\n }\n }\n queue.length = 0;\n queue.push(...next);\n }\n return false;\n }\n const successEndIds = new Set(\n endNodes.filter((n) => (n as EndNode).outcome !== \"failure\").map((n) => n.id),\n );\n const failureEndIds = new Set(\n endNodes.filter((n) => (n as EndNode).outcome === \"failure\").map((n) => n.id),\n );\n const allEndIds = new Set(endNodes.map((n) => n.id));\n\n function bfs(targetIds: Set<string>, allowExceptional: boolean): string[] | null {\n const queue: Array<{ id: string; path: string[] }> = [{ id: startNode!.id, path: [startNode!.id] }];\n const visited = new Set<string>([startNode!.id]);\n\n while (queue.length > 0) {\n const { id, path } = queue.shift()!;\n if (targetIds.has(id)) return path;\n\n const neighbors = adjacency.get(id) ?? [];\n // When any outgoing edge is marked isMainPath, follow ONLY those edges.\n // This implements guided traversal: the extractor marks the continuing\n // branch of guard clauses, and we follow that guidance exclusively.\n const hasMainEdge = neighbors.some((e) => e.isMainPath);\n const candidates = hasMainEdge\n ? neighbors.filter((e) => e.isMainPath)\n : neighbors;\n\n // Sort remaining candidates: no-wait > wait, skip exceptional\n const sorted = [...candidates].sort((a, b) => {\n const aErr = a.isExceptional || a.isTimeout;\n const bErr = b.isExceptional || b.isTimeout;\n if (aErr && !bErr) return 1;\n if (!aErr && bErr) return -1;\n const aWait = waitNodeIds.has(a.to) || pathHasWait(a.to);\n const bWait = waitNodeIds.has(b.to) || pathHasWait(b.to);\n if (aWait && !bWait) return 1;\n if (!aWait && bWait) return -1;\n return 0;\n });\n\n for (const neighbor of sorted) {\n if (visited.has(neighbor.to)) continue;\n if (!allowExceptional && (neighbor.isExceptional || neighbor.isTimeout || failureEndIds.has(neighbor.to))) continue;\n visited.add(neighbor.to);\n queue.push({ id: neighbor.to, path: [...path, neighbor.to] });\n }\n }\n return null;\n }\n\n return bfs(successEndIds, false)\n ?? bfs(allEndIds, false)\n ?? bfs(allEndIds, true)\n ?? [];\n}\n\nexport class WorkflowPatchError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"WorkflowPatchError\";\n }\n}\n\nfunction cloneWorkflow(workflow: WorkflowIR): WorkflowIR {\n // Use JSON round-trip instead of structuredClone \u2014 the Temporal workflow\n // sandbox doesn't expose structuredClone, and WorkflowIR is plain JSON.\n return JSON.parse(JSON.stringify(workflow));\n}\n\nfunction cloneMaybeWorkflow(workflow: WorkflowIR | null): WorkflowIR | null {\n return workflow ? cloneWorkflow(workflow) : null;\n}\n\nfunction upsertAtIndex<T>(items: T[], item: T, index?: number): T[] {\n const next = [...items];\n if (index === undefined || index < 0 || index >= next.length) {\n next.push(item);\n return next;\n }\n next.splice(index, 0, item);\n return next;\n}\n\nfunction edgeMatches(edge: WorkflowEdge, from: string, to: string): boolean {\n return edge.from === from && edge.to === to;\n}\n\nfunction ensureNodeExists(workflow: WorkflowIR, nodeId: string): void {\n if (!workflow.nodes.some((node) => node.id === nodeId)) {\n throw new WorkflowPatchError(`Node not found: ${nodeId}`);\n }\n}\n\nfunction ensureNoDuplicateNode(workflow: WorkflowIR, nodeId: string): void {\n if (workflow.nodes.some((node) => node.id === nodeId)) {\n throw new WorkflowPatchError(`Duplicate node id: ${nodeId}`);\n }\n}\n\n/**\n * `addEdge` identity: two edges are the SAME edge only when `from`, `to`, AND\n * `fromExit` all match. This is intentionally narrower than {@link edgeMatches}\n * (from+to only, used by `updateEdge`/`removeEdge` to target \"the\" edge\n * between a pair of nodes) \u2014 a group can fan out multiple distinct exit arms\n * to the same external target, each keyed by a different `fromExit`, and\n * those are NOT duplicates of one another.\n */\nfunction isDuplicateEdge(workflow: WorkflowIR, edge: WorkflowEdge): boolean {\n return workflow.edges.some(\n (existing) =>\n existing.from === edge.from && existing.to === edge.to && existing.fromExit === edge.fromExit,\n );\n}\n\nfunction sanitizeMainPath(workflow: WorkflowIR, mainPath: string[]): string[] {\n const nodeIds = new Set(workflow.nodes.map((node) => node.id));\n const seen = new Set<string>();\n const normalized: string[] = [];\n\n for (const nodeId of mainPath) {\n if (!nodeIds.has(nodeId)) {\n throw new WorkflowPatchError(`Main path references unknown node: ${nodeId}`);\n }\n if (seen.has(nodeId)) {\n continue;\n }\n seen.add(nodeId);\n normalized.push(nodeId);\n }\n\n return normalized;\n}\n\n/**\n * Resolve a child graph from a node. Checks childGraph first, then backing.backingGraph.\n */\nfunction getChildGraph(node: WorkflowNode): WorkflowIR | null {\n if ('childGraph' in node && (node as any).childGraph) return (node as any).childGraph;\n if ('backing' in node && (node as any).backing?.backingGraph) return (node as any).backing.backingGraph;\n return null;\n}\n\n/**\n * Set a child graph on a node, returning a new node with the updated graph.\n */\nfunction setChildGraph(node: WorkflowNode, childGraph: WorkflowIR): WorkflowNode {\n if ('childGraph' in node) return { ...node, childGraph } as WorkflowNode;\n if ('backing' in node && (node as any).backing?.backingGraph) {\n return { ...node, backing: { ...(node as any).backing, backingGraph: childGraph } } as WorkflowNode;\n }\n // Fallback: attach as childGraph\n return { ...node, childGraph } as WorkflowNode;\n}\n\n/**\n * Apply a patch within a nested child graph, rebuilding the parent chain.\n * scope is a path of node IDs: [\"action_1\"] means \"inside action_1's childGraph\",\n * [\"action_1\", \"loop_3\"] means \"inside action_1's child, then inside loop_3's child\".\n */\nfunction applyScopedPatch(workflow: WorkflowIR, scope: string[], patch: WorkflowPatch): WorkflowIR {\n const [headId, ...rest] = scope;\n const next = cloneWorkflow(workflow);\n const nodeIndex = next.nodes.findIndex((n) => n.id === headId);\n if (nodeIndex === -1) {\n throw new WorkflowPatchError(`Scoped patch: node '${headId}' not found in current graph`);\n }\n\n const node = next.nodes[nodeIndex]!;\n let childGraph = getChildGraph(node);\n if (!childGraph) {\n // Bootstrap: the FIRST scoped patch into a still-empty container starts an\n // empty interior, so a group's body can be built incrementally with scoped\n // patches (as the design guide instructs) instead of forcing the whole\n // childGraph to be supplied inline up front. Only container node types can\n // hold a child graph \u2014 scoping into a leaf node is still a real error.\n const canHoldChildGraph = node.type === \"group\" || node.type === \"child_workflow\";\n if (!canHoldChildGraph) {\n throw new WorkflowPatchError(\n `Scoped patch: node '${headId}' (type '${node.type}') cannot hold a child graph`,\n );\n }\n childGraph = { name: \"\", description: \"\", nodes: [], edges: [], mainPath: [] };\n }\n\n // Strip scope from the patch for the recursive call\n const unscopedPatch: WorkflowPatch = { ...patch, scope: rest.length > 0 ? rest : undefined };\n const updatedChild = applyWorkflowPatch(childGraph, unscopedPatch);\n\n next.nodes[nodeIndex] = setChildGraph(node, updatedChild);\n return next;\n}\n\n/**\n * Wrap a set of existing sibling nodes into a new `group` sub-process, rewiring\n * the boundary edges.\n *\n * **Entry constraint (unchanged):** the wrapped region must have exactly one\n * entry point (the unique node that has an incoming boundary edge, or \u2014 if no\n * external predecessors \u2014 the unique node with no internal in-edge). Selections\n * with 0 or 2+ entry points are rejected.\n *\n * **Multi-exit support:** a region may have any number of outgoing boundary\n * edges. The op synthesises one childGraph `end` node per outgoing edge, using\n * the id `${groupId}__exit_<n>` (1-based). Each exit node's `outcome` is\n * `\"failure\"` when the original edge was `isExceptional` or `isTimeout`;\n * otherwise `\"success\"`. In the parent graph, each synthesised exit end becomes\n * one `fromExit` edge (`from: groupId, to: <original external target>,\n * fromExit: \"<exitEndId>\"`), carrying the original edge's `isMainPath`,\n * `isExceptional`, and `isTimeout` flags.\n *\n * **Fully-terminal region:** when the region has no outgoing boundary edges at\n * all, a single synthesised `${groupId}__end` node (outcome `\"success\"`) is\n * added to the childGraph and no parent exit edges are emitted.\n */\nfunction wrapIntoGroup(\n workflow: WorkflowIR,\n nodeIds: string[],\n groupId: string,\n label: string,\n groupType: \"loop\" | \"function\" | \"handlers\" | \"setup\" | \"guard\",\n): WorkflowIR {\n if (nodeIds.length === 0) throw new WorkflowPatchError(\"group: nodeIds is empty\");\n const inSet = new Set(nodeIds);\n if (workflow.nodes.some((n) => n.id === groupId)) {\n throw new WorkflowPatchError(`group: id '${groupId}' already exists`);\n }\n for (const id of nodeIds) {\n const node = workflow.nodes.find((n) => n.id === id);\n if (!node) throw new WorkflowPatchError(`group: node '${id}' not found`);\n if (node.type === \"start\" || node.type === \"end\") {\n throw new WorkflowPatchError(`group: cannot wrap a '${node.type}' node ('${id}')`);\n }\n }\n\n // Classify every edge relative to the wrapped set.\n const internal: WorkflowEdge[] = [];\n const incoming: WorkflowEdge[] = [];\n const outgoing: WorkflowEdge[] = [];\n const external: WorkflowEdge[] = [];\n for (const e of workflow.edges) {\n const f = inSet.has(e.from);\n const t = inSet.has(e.to);\n if (f && t) internal.push(e);\n else if (!f && t) incoming.push(e);\n else if (f && !t) outgoing.push(e);\n else external.push(e);\n }\n\n // Entry node(s): targets of incoming boundary edges, else region heads.\n const entryNodes = new Set(incoming.map((e) => e.to));\n if (entryNodes.size === 0) {\n const internalIn = new Set(internal.map((e) => e.to));\n for (const id of nodeIds) if (!internalIn.has(id)) entryNodes.add(id);\n }\n // Exit node(s): sources of outgoing boundary edges, else region tails.\n const exitNodes = new Set(outgoing.map((e) => e.from));\n if (exitNodes.size === 0) {\n const internalOut = new Set(internal.map((e) => e.from));\n for (const id of nodeIds) if (!internalOut.has(id)) exitNodes.add(id);\n }\n if (entryNodes.size !== 1) {\n throw new WorkflowPatchError(\n `group: the selection has ${entryNodes.size} entry points; wrap a single-entry region`,\n );\n }\n const entry = [...entryNodes][0]!;\n\n // Build the interior: synthesized start around the grouped nodes, then either:\n // (a) terminal region (outgoing is empty) \u2014 single synthesized end for the body\n // (b) multi-exit region \u2014 one synthesized exit `end` per outgoing boundary edge\n const startId = `${groupId}__start`;\n const groupedNodes = workflow.nodes.filter((n) => inSet.has(n.id));\n const inParentMain = workflow.mainPath.filter((id) => inSet.has(id));\n\n let childGraph: WorkflowIR;\n let parentExitEdges: WorkflowEdge[];\n // Terminal `end`s reached ONLY from within the region get PULLED inside the\n // group (they terminate the run there \u2014 the interpreter's terminal-exit\n // semantics); these ids are removed from the parent below.\n const pulledIds = new Set<string>();\n\n if (outgoing.length === 0) {\n // Terminal region: no boundary exits \u2014 synthesize a single end node.\n const endId = `${groupId}__end`;\n const childNodes: WorkflowNode[] = [\n { id: startId, type: \"start\", label: \"Start\" } as WorkflowNode,\n ...groupedNodes,\n { id: endId, type: \"end\", label: \"Done\", outcome: \"success\" } as WorkflowNode,\n ];\n const childEdges: WorkflowEdge[] = [\n { from: startId, to: entry, isMainPath: true },\n ...internal,\n ...[...exitNodes].map((from) => ({ from, to: endId, isMainPath: true }) as WorkflowEdge),\n ];\n childGraph = {\n name: label,\n description: \"\",\n nodes: childNodes,\n edges: childEdges,\n mainPath: [startId, ...(inParentMain.length ? inParentMain : nodeIds), endId],\n };\n parentExitEdges = [];\n } else {\n // Multi-exit region. Group the outgoing boundary edges by their external\n // target, then for each DISTINCT target decide:\n // - PULL INSIDE: the target is a terminal `end` reached only from within\n // the region (sole-reference) \u2192 move the real end node into the\n // childGraph; the in-region edges to it become internal edges; no parent\n // edge (the run ends there via the interpreter's terminal-exit path).\n // - EXIT: otherwise \u2192 one synthesized `${groupId}__exit_<n>` end + one\n // keyed `fromExit` parent edge to the original target (deduped per target,\n // so several in-region edges to the same target collapse to one exit).\n const byTarget = new Map<string, WorkflowEdge[]>();\n for (const e of outgoing) {\n const arr = byTarget.get(e.to);\n if (arr) arr.push(e);\n else byTarget.set(e.to, [e]);\n }\n const isSoleRefTerminal = (target: string): boolean => {\n const node = workflow.nodes.find((n) => n.id === target);\n if (!node || node.type !== \"end\") return false;\n // No edge from OUTSIDE the region reaches it.\n return workflow.edges.every((e) => e.to !== target || inSet.has(e.from));\n };\n // Preserve each in-region edge's own flags onto its internal childGraph edge.\n const toChildEdge = (e: WorkflowEdge, to: string): WorkflowEdge => ({\n from: e.from,\n to,\n ...(e.label ? { label: e.label } : {}),\n ...(e.isMainPath ? { isMainPath: true } : {}),\n ...(e.isExceptional ? { isExceptional: true } : {}),\n ...(e.isTimeout ? { isTimeout: true } : {}),\n });\n\n const extraChildNodes: WorkflowNode[] = [];\n const exitChildEdges: WorkflowEdge[] = [];\n parentExitEdges = [];\n let exitN = 0;\n for (const [target, edges] of byTarget) {\n if (isSoleRefTerminal(target)) {\n const endNode = workflow.nodes.find((n) => n.id === target)!;\n extraChildNodes.push(endNode);\n pulledIds.add(target);\n for (const e of edges) exitChildEdges.push(toChildEdge(e, target));\n } else {\n exitN += 1;\n const exitId = `${groupId}__exit_${exitN}`;\n const first = edges[0]!;\n const anyMain = edges.some((e) => e.isMainPath);\n const allExceptional = edges.every((e) => e.isExceptional || e.isTimeout);\n // Label the exit from its boundary edge (\"approved\" -> \"Approved\") so it\n // reads as the outcome, not a generic \"Exit N\".\n const exitLabel = first.label\n ? first.label.charAt(0).toUpperCase() + first.label.slice(1)\n : workflow.nodes.find((n) => n.id === target)?.label ?? `Exit ${exitN}`;\n extraChildNodes.push({\n id: exitId,\n type: \"end\",\n label: exitLabel,\n outcome: allExceptional ? \"failure\" : \"success\",\n } as WorkflowNode);\n for (const e of edges) exitChildEdges.push(toChildEdge(e, exitId));\n parentExitEdges.push({\n from: groupId,\n to: target,\n fromExit: exitId,\n ...(first.label ? { label: first.label } : {}),\n ...(anyMain ? { isMainPath: true } : {}),\n ...(!anyMain && edges.every((e) => e.isExceptional) ? { isExceptional: true } : {}),\n ...(!anyMain && edges.every((e) => e.isTimeout) ? { isTimeout: true } : {}),\n });\n }\n }\n\n // Center the HAPPY path: pick the success-outcome continuing exit and mark the\n // route entry -> ... -> success-exit as the childGraph main path, so the layout\n // spines the approved path rather than an escalation/exceptional branch.\n const successExit = extraChildNodes.find(\n (n) => n.type === \"end\" && !pulledIds.has(n.id) && (n as { outcome?: string }).outcome === \"success\",\n );\n const mainEdgeKeys = new Set<string>();\n const edgeKey = (a: string, b: string) => `${a}\\0${b}`;\n let mainBody: string[] = inParentMain.length ? inParentMain : nodeIds;\n let mainTail: string[] = [];\n if (successExit) {\n const exitSources = new Set(exitChildEdges.filter((e) => e.to === successExit.id).map((e) => e.from));\n // BFS from the entry over NON-exceptional internal edges to the nearest source.\n const adj = new Map<string, string[]>();\n for (const e of internal) {\n if (e.isExceptional || e.isTimeout) continue;\n const arr = adj.get(e.from);\n if (arr) arr.push(e.to);\n else adj.set(e.from, [e.to]);\n }\n const prev = new Map<string, string>();\n const visited = new Set<string>([entry]);\n const queue: string[] = [entry];\n let found: string | undefined;\n while (queue.length > 0) {\n const cur = queue.shift()!;\n if (exitSources.has(cur)) { found = cur; break; }\n for (const nx of adj.get(cur) ?? []) {\n if (!visited.has(nx)) { visited.add(nx); prev.set(nx, cur); queue.push(nx); }\n }\n }\n if (found) {\n const path: string[] = [];\n for (let c: string | undefined = found; c !== undefined; c = prev.get(c)) path.unshift(c);\n for (let i = 0; i < path.length - 1; i++) mainEdgeKeys.add(edgeKey(path[i]!, path[i + 1]!));\n mainEdgeKeys.add(edgeKey(found, successExit.id));\n mainBody = path;\n mainTail = [successExit.id];\n }\n }\n // Clone every interior edge (never mutate the input) and flag the happy ones.\n const markMain = (e: WorkflowEdge): WorkflowEdge =>\n mainEdgeKeys.has(edgeKey(e.from, e.to)) ? { ...e, isMainPath: true } : { ...e };\n\n childGraph = {\n name: label,\n description: \"\",\n nodes: [{ id: startId, type: \"start\", label: \"Start\" } as WorkflowNode, ...groupedNodes, ...extraChildNodes],\n edges: [\n { from: startId, to: entry, isMainPath: true },\n ...internal.map(markMain),\n ...exitChildEdges.map(markMain),\n ],\n mainPath: [startId, ...mainBody, ...mainTail],\n };\n }\n\n const groupNode = { id: groupId, type: \"group\", groupType, label, childGraph } as unknown as WorkflowNode;\n\n // Rewire the parent: the group takes the first grouped node's slot; the rest\n // of the grouped nodes (and internal edges) move into the interior.\n const newNodes: WorkflowNode[] = [];\n let placed = false;\n for (const n of workflow.nodes) {\n if (inSet.has(n.id)) {\n if (!placed) {\n newNodes.push(groupNode);\n placed = true;\n }\n } else if (!pulledIds.has(n.id)) {\n // Pulled-inside terminal ends now live in the childGraph, not the parent.\n newNodes.push(n);\n }\n }\n const seen = new Set<string>();\n const newEdges: WorkflowEdge[] = [];\n const pushEdge = (e: WorkflowEdge) => {\n const key = `${e.from} ${e.to} ${e.fromExit ?? \"\"} ${e.label ?? \"\"}`;\n if (seen.has(key)) return;\n seen.add(key);\n newEdges.push(e);\n };\n for (const e of external) pushEdge(e);\n for (const e of incoming) pushEdge({ ...e, to: groupId });\n // Every outgoing boundary edge is now represented either by a keyed `fromExit`\n // parent edge (exit targets) or by a pulled-inside terminal end (no parent\n // edge). A fully-terminal region (`outgoing` empty) yields no parent edges.\n for (const e of parentExitEdges) pushEdge(e);\n\n const newMain: string[] = [];\n let mainInserted = false;\n for (const id of workflow.mainPath) {\n if (inSet.has(id)) {\n if (!mainInserted) {\n newMain.push(groupId);\n mainInserted = true;\n }\n } else {\n newMain.push(id);\n }\n }\n\n return { ...workflow, nodes: newNodes, edges: newEdges, mainPath: newMain };\n}\n\n\n/** A fresh, empty canonical WorkflowIR \u2014 the base to patch onto when no\n * workflow exists yet. */\nexport function emptyWorkflowIR(name = \"untitled\"): WorkflowIR {\n return { name, description: \"\", nodes: [], edges: [], mainPath: [] };\n}\n\nexport function applyWorkflowPatch(workflow: WorkflowIR, patch: WorkflowPatch): WorkflowIR {\n // Handle scoped patches \u2014 apply within a nested child graph.\n if (patch.scope && patch.scope.length > 0) {\n return applyScopedPatch(workflow, patch.scope, patch);\n }\n\n if (patch.op === \"batch\") {\n return patch.patches.reduce((current, operation) => applyWorkflowPatch(current, operation), workflow);\n }\n\n if (patch.op === \"replace\") {\n return cloneWorkflow(patch.workflow);\n }\n\n const next = cloneWorkflow(workflow);\n\n switch (patch.op) {\n case \"addNode\": {\n ensureNoDuplicateNode(next, patch.node.id);\n next.nodes = upsertAtIndex(next.nodes, patch.node, patch.index);\n return next;\n }\n\n case \"updateNode\": {\n const index = next.nodes.findIndex((node) => node.id === patch.nodeId);\n if (index === -1) {\n throw new WorkflowPatchError(`Node not found: ${patch.nodeId}`);\n }\n const existing = next.nodes.at(index);\n if (!existing) {\n throw new WorkflowPatchError(`Node not found at index: ${index}`);\n }\n next.nodes[index] = {\n ...existing,\n ...patch.patch,\n id: existing.id,\n } as WorkflowNode;\n return next;\n }\n\n case \"removeNode\": {\n ensureNodeExists(next, patch.nodeId);\n next.nodes = next.nodes.filter((node) => node.id !== patch.nodeId);\n next.mainPath = next.mainPath.filter((nodeId) => nodeId !== patch.nodeId);\n\n const shouldRemoveEdges = patch.removeAttachedEdges ?? true;\n if (shouldRemoveEdges) {\n next.edges = next.edges.filter((edge) => edge.from !== patch.nodeId && edge.to !== patch.nodeId);\n }\n\n return next;\n }\n\n case \"addEdge\": {\n ensureNodeExists(next, patch.from);\n ensureNodeExists(next, patch.to);\n const edge: WorkflowEdge = {\n from: patch.from,\n to: patch.to,\n ...(patch.fromExit !== undefined ? { fromExit: patch.fromExit } : {}),\n ...(patch.label !== undefined ? { label: patch.label } : {}),\n ...(patch.isMainPath !== undefined ? { isMainPath: patch.isMainPath } : {}),\n ...(patch.isExceptional !== undefined ? { isExceptional: patch.isExceptional } : {}),\n ...(patch.isTimeout !== undefined ? { isTimeout: patch.isTimeout } : {}),\n };\n // Idempotent: adding an edge that already exists (same from/to/fromExit)\n // is a no-op, not a rejection \u2014 an agent batching a whole design at once\n // shouldn't get a hard \"Duplicate edge\" failure for repeating an edge it\n // (or an earlier patch in the same batch) already established. An edge\n // that differs only in `fromExit` is a distinct exit arm, not a dup.\n if (isDuplicateEdge(next, edge)) {\n return next;\n }\n next.edges = upsertAtIndex(next.edges, edge, patch.index);\n return next;\n }\n\n case \"updateEdge\": {\n const index = next.edges.findIndex((edge) => edgeMatches(edge, patch.from, patch.to));\n if (index === -1) {\n throw new WorkflowPatchError(`Edge not found: ${patch.from} -> ${patch.to}`);\n }\n const existing = next.edges.at(index);\n if (!existing) {\n throw new WorkflowPatchError(`Edge not found at index: ${index}`);\n }\n next.edges[index] = {\n ...existing,\n ...patch.patch,\n from: patch.from,\n to: patch.to,\n };\n return next;\n }\n\n case \"removeEdge\": {\n const initialLength = next.edges.length;\n next.edges = next.edges.filter((edge) => !edgeMatches(edge, patch.from, patch.to));\n if (next.edges.length === initialLength) {\n throw new WorkflowPatchError(`Edge not found: ${patch.from} -> ${patch.to}`);\n }\n return next;\n }\n\n case \"group\": {\n return wrapIntoGroup(next, patch.nodeIds, patch.groupId, patch.label, patch.groupType ?? \"function\");\n }\n\n case \"setMainPath\": {\n next.mainPath = sanitizeMainPath(next, patch.mainPath);\n return next;\n }\n\n case \"setUiSpecs\": {\n next.uiSpecs = { ...next.uiSpecs, ...patch.uiSpecs };\n return next;\n }\n\n case \"setMeta\": {\n // Only overwrite the fields the patch actually carries \u2014 setMeta is a\n // partial update (rename without clobbering the description, etc.).\n if (patch.name !== undefined) next.name = patch.name;\n if (patch.description !== undefined) next.description = patch.description;\n if (patch.signals !== undefined) next.signals = patch.signals;\n return next;\n }\n\n default:\n return next;\n }\n}\n\n/**\n * Convenience helper for applying a patch list as a single transactional update.\n */\nexport function applyWorkflowPatches(\n workflow: WorkflowIR,\n patches: WorkflowPatch[],\n): WorkflowIR {\n return patches.reduce((current, patch) => applyWorkflowPatch(current, patch), workflow);\n}\n\n/** A single patch failure surfaced by {@link validateWorkflowPatches}, with the\n * offending patch's position in the batch. */\nexport interface PatchError {\n index: number;\n op: string;\n message: string;\n}\n\n/**\n * Dry-runs a whole patch batch against a clone of `ir` and returns every\n * failure with its index, instead of throwing on the first bad patch (as\n * {@link applyWorkflowPatches} does). A failing patch is skipped so later,\n * independent patches still get a chance to apply \u2014 this lets a caller\n * surface every problem in a batch at once rather than fixing one at a time.\n * Returns `[]` when every patch applies cleanly.\n */\nexport function validateWorkflowPatches(\n ir: WorkflowIR,\n patches: ReadonlyArray<WorkflowPatch>,\n): PatchError[] {\n const errors: PatchError[] = [];\n let clone = cloneWorkflow(ir);\n patches.forEach((patch, index) => {\n try {\n clone = applyWorkflowPatch(clone, patch);\n } catch (err) {\n errors.push({\n index,\n op: (patch as { op?: string }).op ?? \"?\",\n message: err instanceof Error ? err.message : String(err),\n });\n }\n });\n return errors;\n}\n\n/**\n * Stateful patch stream with undo/redo support.\n */\nexport class WorkflowPatchStream {\n private currentWorkflow: WorkflowIR | null;\n private undoStack: Array<WorkflowIR | null> = [];\n private redoStack: Array<WorkflowIR | null> = [];\n\n constructor(initialWorkflow: WorkflowIR | null = null) {\n this.currentWorkflow = cloneMaybeWorkflow(initialWorkflow);\n }\n\n get current(): WorkflowIR | null {\n return cloneMaybeWorkflow(this.currentWorkflow);\n }\n\n get canUndo(): boolean {\n return this.undoStack.length > 0;\n }\n\n get canRedo(): boolean {\n return this.redoStack.length > 0;\n }\n\n reset(workflow: WorkflowIR | null = null): WorkflowIR | null {\n this.currentWorkflow = cloneMaybeWorkflow(workflow);\n this.undoStack = [];\n this.redoStack = [];\n return this.current;\n }\n\n apply(patchOrPatches: WorkflowPatch | WorkflowPatch[]): WorkflowIR {\n const patches = Array.isArray(patchOrPatches) ? patchOrPatches : [patchOrPatches];\n if (patches.length === 0) {\n if (!this.currentWorkflow) {\n throw new WorkflowPatchError(\"Cannot apply empty patch list without an initial workflow\");\n }\n return cloneWorkflow(this.currentWorkflow);\n }\n\n const previous = cloneMaybeWorkflow(this.currentWorkflow);\n let next = cloneMaybeWorkflow(this.currentWorkflow);\n\n for (const patch of patches) {\n if (!next) {\n if (patch.op !== \"replace\") {\n throw new WorkflowPatchError(\n \"Patch stream is empty. First patch must be a replace operation.\",\n );\n }\n next = cloneWorkflow(patch.workflow);\n continue;\n }\n next = applyWorkflowPatch(next, patch);\n }\n\n if (!next) {\n throw new WorkflowPatchError(\"Patch application produced an empty workflow\");\n }\n\n this.undoStack.push(previous);\n this.redoStack = [];\n this.currentWorkflow = next;\n return cloneWorkflow(next);\n }\n\n undo(): WorkflowIR | null {\n if (!this.canUndo) {\n return this.current;\n }\n\n const previous = this.undoStack.pop() ?? null;\n this.redoStack.push(cloneMaybeWorkflow(this.currentWorkflow));\n this.currentWorkflow = cloneMaybeWorkflow(previous);\n return this.current;\n }\n\n redo(): WorkflowIR | null {\n if (!this.canRedo) {\n return this.current;\n }\n\n const next = this.redoStack.pop() ?? null;\n this.undoStack.push(cloneMaybeWorkflow(this.currentWorkflow));\n this.currentWorkflow = cloneMaybeWorkflow(next);\n return this.current;\n }\n}\n", "/**\n * Workflow IR Validator\n *\n * Pure static analysis for WorkflowIR graphs. Detects structural issues like\n * missing timeout edges, unhandled failure paths in child workflows, unreachable\n * nodes, and dead-end branches. Results are indexed by node ID for O(1) lookup.\n */\n\nimport type {\n WorkflowIR,\n WorkflowNode,\n WorkflowEdge,\n} from \"./workflow-ir.js\";\n\n// \u2500\u2500 Types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport type DiagnosticSeverity = \"warning\" | \"error\";\n\nexport type DiagnosticCode =\n | \"WAIT_NO_TIMEOUT_EDGE\"\n | \"DECISION_DEAD_END\"\n | \"CHILD_FAILURE_UNHANDLED\"\n | \"NEXUS_FAILURE_UNHANDLED\"\n | \"UNREACHABLE_NODE\"\n | \"TERMINAL_NON_END\"\n | \"TIMEOUT_ON_NON_WAIT\";\n\nexport interface WorkflowDiagnostic {\n code: DiagnosticCode;\n severity: DiagnosticSeverity;\n nodeId: string;\n message: string;\n}\n\nexport interface WorkflowValidationResult {\n diagnostics: WorkflowDiagnostic[];\n byNodeId: Map<string, WorkflowDiagnostic[]>;\n}\n\nexport interface ValidateOptions {\n /** Maximum recursion depth for child/backing graphs. Default: 10 */\n maxDepth?: number;\n}\n\n// \u2500\u2500 Helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction outgoingEdges(edges: WorkflowEdge[], nodeId: string): WorkflowEdge[] {\n return edges.filter((e) => e.from === nodeId);\n}\n\nfunction incomingEdges(edges: WorkflowEdge[], nodeId: string): WorkflowEdge[] {\n return edges.filter((e) => e.to === nodeId);\n}\n\nfunction hasFailureEnd(workflow: WorkflowIR): boolean {\n return workflow.nodes.some(\n (n) => n.type === \"end\" && n.outcome === \"failure\",\n );\n}\n\nfunction hasExceptionalEdge(edges: WorkflowEdge[], nodeId: string): boolean {\n return edges.some((e) => e.from === nodeId && e.isExceptional);\n}\n\n// \u2500\u2500 Validator \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport function validateWorkflowIR(\n workflow: WorkflowIR,\n options?: ValidateOptions,\n): WorkflowValidationResult {\n const maxDepth = options?.maxDepth ?? 10;\n const diagnostics: WorkflowDiagnostic[] = [];\n\n collectDiagnostics(workflow, diagnostics, 0, maxDepth);\n\n const byNodeId = new Map<string, WorkflowDiagnostic[]>();\n for (const d of diagnostics) {\n const existing = byNodeId.get(d.nodeId);\n if (existing) {\n existing.push(d);\n } else {\n byNodeId.set(d.nodeId, [d]);\n }\n }\n\n return { diagnostics, byNodeId };\n}\n\nfunction collectDiagnostics(\n workflow: WorkflowIR,\n out: WorkflowDiagnostic[],\n depth: number,\n maxDepth: number,\n): void {\n if (depth > maxDepth) return;\n\n const { nodes, edges } = workflow;\n const nodeMap = new Map<string, WorkflowNode>();\n for (const node of nodes) {\n nodeMap.set(node.id, node);\n }\n\n for (const node of nodes) {\n const outEdges = outgoingEdges(edges, node.id);\n const inEdges = incomingEdges(edges, node.id);\n\n // WAIT_NO_TIMEOUT_EDGE\n if (node.type === \"wait\" && node.timeout) {\n if (!outEdges.some((e) => e.isTimeout)) {\n out.push({\n code: \"WAIT_NO_TIMEOUT_EDGE\",\n severity: \"warning\",\n nodeId: node.id,\n message: `Wait node \"${node.label}\" has timeout (${node.timeout}) but no timeout edge.`,\n });\n }\n }\n\n // DECISION_DEAD_END\n if (node.type === \"decision\" && outEdges.length < 2) {\n out.push({\n code: \"DECISION_DEAD_END\",\n severity: \"warning\",\n nodeId: node.id,\n message: `Decision node \"${node.label}\" has ${outEdges.length} outgoing edge(s); expected at least 2.`,\n });\n }\n\n // CHILD_FAILURE_UNHANDLED\n if (node.type === \"child_workflow\" && node.childGraph) {\n if (hasFailureEnd(node.childGraph) && !hasExceptionalEdge(edges, node.id)) {\n out.push({\n code: \"CHILD_FAILURE_UNHANDLED\",\n severity: \"warning\",\n nodeId: node.id,\n message: `Child workflow \"${node.label}\" can fail but parent has no error edge.`,\n });\n }\n collectDiagnostics(node.childGraph, out, depth + 1, maxDepth);\n }\n\n // NEXUS_FAILURE_UNHANDLED\n if (node.type === \"nexus_operation\" && node.backing?.backingGraph) {\n if (hasFailureEnd(node.backing.backingGraph) && !hasExceptionalEdge(edges, node.id)) {\n out.push({\n code: \"NEXUS_FAILURE_UNHANDLED\",\n severity: \"warning\",\n nodeId: node.id,\n message: `Nexus operation \"${node.label}\" backing graph can fail but parent has no error edge.`,\n });\n }\n collectDiagnostics(node.backing.backingGraph, out, depth + 1, maxDepth);\n }\n\n // UNREACHABLE_NODE \u2014 skip start nodes and graphs with no edges\n // (e.g. parallel branch lists where nodes are independent by design)\n if (node.type !== \"start\" && inEdges.length === 0 && edges.length > 0) {\n out.push({\n code: \"UNREACHABLE_NODE\",\n severity: \"error\",\n nodeId: node.id,\n message: `Node \"${node.label}\" has no incoming edges and is unreachable.`,\n });\n }\n\n // TERMINAL_NON_END \u2014 non-end node with no outgoing edges\n // (same edge-count guard for parallel branch lists)\n if (node.type !== \"end\" && outEdges.length === 0 && edges.length > 0) {\n out.push({\n code: \"TERMINAL_NON_END\",\n severity: \"error\",\n nodeId: node.id,\n message: `Non-terminal node \"${node.label}\" has no outgoing edges (dead end).`,\n });\n }\n }\n\n // TIMEOUT_ON_NON_WAIT \u2014 check edges globally\n for (const edge of edges) {\n if (edge.isTimeout) {\n const sourceNode = nodeMap.get(edge.from);\n if (sourceNode && sourceNode.type !== \"wait\") {\n out.push({\n code: \"TIMEOUT_ON_NON_WAIT\",\n severity: \"warning\",\n nodeId: edge.from,\n message: `Edge from \"${sourceNode.label}\" to \"${nodeMap.get(edge.to)?.label ?? edge.to}\" has isTimeout but source is a ${sourceNode.type} node, not a wait node.`,\n });\n }\n }\n }\n}\n", "import { applyWorkflowPatch } from \"./workflow-ir.js\";\nimport type { WorkflowIR, WorkflowPatch } from \"./workflow-ir.js\";\n\n/**\n * Tolerant patch application for a CLIENT-SIDE streaming sketch preview. Delegates to\n * the canonical `applyWorkflowPatch` (so scope/groups/all ops behave exactly as they\n * will on commit \u2014 no second implementation to keep in sync), but swallows the throws\n * that a partial/mid-stream patch produces (e.g. an edge whose target node hasn't\n * streamed in yet) by returning the IR unchanged. Non-authoritative: the server commit\n * overwrites the preview. `applyWorkflowPatch` clones internally, so the input is never mutated.\n */\nexport function applyPreviewPatch(ir: WorkflowIR, patch: WorkflowPatch): WorkflowIR {\n try {\n return applyWorkflowPatch(ir, patch);\n } catch {\n return ir;\n }\n}\n", "/**\n * Process Artifact \u2014 schema + parser\n *\n * A process artifact is a BA-authored JSON document describing the ordered\n * stages, business substeps, actors, and outcomes of a process, plus the\n * names it binds to in the as-built workflow (commands/activities/named\n * predicates). It is builder-shaped WorkflowIR (name, description, phase)\n * plus a `process` extension block \u2014 see\n * docs/plans/2026-07-05-process-artifact-design.md \u00A71 for the worked\n * example this schema accepts verbatim.\n *\n * Bindings point at *names*, not behavior: `commands`/`activities` reference\n * the extractor's inventory, `predicate` references the workflow package's\n * named predicate registry. Referential checks against an inventory/predicate\n * list belong to the P2 conformance lint, not here \u2014 this module only\n * enforces the artifact's own shape plus structural invariants that make no\n * sense without it (duplicate ids, an empty bind, an ambiguous outcome\n * trigger, an unsupported schema version).\n *\n * `parseProcessArtifact` never throws: all schema and structural violations\n * are converted into `Diagnostic`s carrying a JSON path so callers (lint,\n * loader, builder) can report them uniformly.\n */\n\nimport { z } from \"zod\";\nimport type { DiagnosticSeverity } from \"./workflow-ir-validate.js\";\n\n// \u2500\u2500 Diagnostics \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// Reuses the `DiagnosticSeverity` vocabulary from workflow-ir-validate.ts;\n// codes and path shape are specific to the process artifact (JSON paths,\n// not graph node ids).\n\n/**\n * Diagnostic codes across the process-artifact system. `Diagnostic` (below)\n * is the single closed vocabulary shared by the schema parser (this file)\n * and the P2 conformance lint (process-lint.ts) \u2014 one `code` union so both\n * modules' findings can flow through the same `Diagnostic[]` unmodified.\n */\nexport type ProcessArtifactDiagnosticCode =\n // Emitted by parseProcessArtifact (this file).\n | \"SCHEMA_INVALID\"\n | \"UNSUPPORTED_VERSION\"\n | \"DUPLICATE_STAGE_ID\"\n | \"DUPLICATE_SUBSTEP_ID\"\n | \"DUPLICATE_OUTCOME_ID\"\n | \"DUPLICATE_PROCESS_ID\"\n | \"EMPTY_SUBSTEP_BIND\"\n // Emitted by lintProcess (process-lint.ts) \u2014 referential/coverage checks\n // against a code-derived inventory and named-predicate registry.\n | \"BOUND_COMMAND_NOT_IN_INVENTORY\"\n | \"BOUND_ACTIVITY_NOT_IN_INVENTORY\"\n | \"UNKNOWN_PREDICATE\"\n | \"UNBOUND_INVENTORY_COMMAND\"\n | \"CONTRADICTORY_COMMAND_DECLARATION\"\n | \"STALE_INTERNAL_COMMAND\"\n | \"MISSING_SUCCESS_OUTCOME\"\n | \"MISSING_FAILURE_OUTCOME\"\n | \"MISSING_STAGE_PREDICATE\"\n | \"WORKFLOW_TYPE_MISMATCH\";\n\nexport interface Diagnostic {\n severity: DiagnosticSeverity;\n code: ProcessArtifactDiagnosticCode;\n message: string;\n /**\n * Dot/bracket JSON path into the parsed document, e.g.\n * \"process.stages[0].complete.predicate\". Root-level issues use \"(root)\".\n */\n path: string;\n}\n\n// \u2500\u2500 Schema \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// Everything under `process` is `.strict()` \u2014 the process block is ours to\n// version (an unrecognized field is almost certainly a typo or a field from\n// a future `process.version`, and should fail loudly). The top-level\n// artifact object is intentionally NOT strict: it carries builder-shaped IR\n// fields we don't re-validate here, and more may be added later.\n\nconst actorSchema = z\n .object({\n label: z.string(),\n })\n .strict();\n\nconst substepBindSchema = z\n .object({\n commands: z.array(z.string()).optional(),\n activities: z.array(z.string()).optional(),\n })\n .strict()\n .superRefine((bind, ctx) => {\n if (!bind.commands?.length && !bind.activities?.length) {\n ctx.addIssue({\n code: \"custom\",\n message: \"bind must include at least one of commands or activities\",\n params: { code: \"EMPTY_SUBSTEP_BIND\" satisfies ProcessArtifactDiagnosticCode },\n });\n }\n });\n\nconst substepSchema = z\n .object({\n id: z.string(),\n label: z.string(),\n actor: z.string().optional(),\n bind: substepBindSchema,\n })\n .strict();\n\n/** Exactly one of a named predicate or a named timeout fires this outcome. */\nconst outcomeWhenSchema = z.union([\n z.object({ predicate: z.string() }).strict(),\n z.object({ timeoutOf: z.string() }).strict(),\n]);\n\nconst outcomeSchema = z\n .object({\n id: z.string(),\n label: z.string(),\n kind: z.enum([\"success\", \"failure\"]),\n when: outcomeWhenSchema,\n description: z.string().optional(),\n })\n .strict();\n\nconst stageCompleteSchema = z\n .object({\n predicate: z.string(),\n })\n .strict();\n\nconst stageSchema = z\n .object({\n id: z.string(),\n label: z.string(),\n description: z.string().optional(),\n actor: z.string().optional(),\n substeps: z.array(substepSchema).optional(),\n complete: stageCompleteSchema,\n pointOfNoReturn: z.literal(true).optional(),\n })\n .strict();\n\nconst processBlockSchema = z\n .object({\n version: z.number(),\n workflowType: z.string(),\n actors: z.record(z.string(), actorSchema),\n stages: z.array(stageSchema),\n outcomes: z.array(outcomeSchema),\n internalCommands: z.array(z.string()).optional(),\n })\n .strict()\n .superRefine((process, ctx) => {\n if (process.version !== 1) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"version\"],\n message:\n `Unsupported process.version ${JSON.stringify(process.version)}; ` +\n \"this parser only understands version 1. Upgrade the parser or downgrade the artifact.\",\n params: { code: \"UNSUPPORTED_VERSION\" satisfies ProcessArtifactDiagnosticCode },\n });\n }\n\n // One shared id namespace across stages, substeps, AND outcomes: the\n // renderer flattens all three kinds into a single WorkflowIR.nodes array\n // keyed by one id space, so a cross-kind collision (e.g. a stage id equal\n // to an outcome id) would silently merge diagram nodes. Same-kind\n // duplicates keep their dedicated codes; cross-kind collisions get\n // DUPLICATE_PROCESS_ID. Every collision diagnostic names BOTH paths.\n type IdKind = \"stage\" | \"substep\" | \"outcome\";\n const SAME_KIND_CODE: Record<IdKind, ProcessArtifactDiagnosticCode> = {\n stage: \"DUPLICATE_STAGE_ID\",\n substep: \"DUPLICATE_SUBSTEP_ID\",\n outcome: \"DUPLICATE_OUTCOME_ID\",\n };\n const idFirstSeenAt = new Map<string, { kind: IdKind; path: (string | number)[] }>();\n const checkId = (id: string, kind: IdKind, path: (string | number)[]): void => {\n const first = idFirstSeenAt.get(id);\n if (first) {\n const kindLabel = kind === first.kind ? kind : \"process\";\n ctx.addIssue({\n code: \"custom\",\n path,\n message:\n `Duplicate ${kindLabel} id \"${id}\": ` +\n `${kind} at ${z.core.toDotPath(path)} collides with ${first.kind} at ${z.core.toDotPath(first.path)}.`,\n params: {\n code: (kind === first.kind\n ? SAME_KIND_CODE[kind]\n : \"DUPLICATE_PROCESS_ID\") satisfies ProcessArtifactDiagnosticCode,\n },\n });\n } else {\n idFirstSeenAt.set(id, { kind, path });\n }\n };\n process.stages.forEach((stage, stageIndex) => {\n checkId(stage.id, \"stage\", [\"stages\", stageIndex, \"id\"]);\n stage.substeps?.forEach((substep, substepIndex) => {\n checkId(substep.id, \"substep\", [\"stages\", stageIndex, \"substeps\", substepIndex, \"id\"]);\n });\n });\n process.outcomes.forEach((outcome, outcomeIndex) => {\n checkId(outcome.id, \"outcome\", [\"outcomes\", outcomeIndex, \"id\"]);\n });\n });\n\n/**\n * Top-level artifact: builder-shaped IR fields (name, description, phase?)\n * plus the `process` block. Unknown top-level fields pass through \u2014 the\n * artifact may carry more IR later and this module only cares about the\n * fields the process system needs.\n */\nexport const processArtifactSchema = z\n .object({\n name: z.string(),\n description: z.string(),\n phase: z.enum([\"draft\", \"workflow_review\"]).optional(),\n process: processBlockSchema,\n })\n .passthrough();\n\n// \u2500\u2500 Types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport type ProcessActor = z.infer<typeof actorSchema>;\nexport type ProcessSubstepBind = z.infer<typeof substepBindSchema>;\nexport type ProcessSubstep = z.infer<typeof substepSchema>;\nexport type ProcessOutcomeWhen = z.infer<typeof outcomeWhenSchema>;\nexport type ProcessOutcome = z.infer<typeof outcomeSchema>;\nexport type ProcessStageComplete = z.infer<typeof stageCompleteSchema>;\nexport type ProcessStage = z.infer<typeof stageSchema>;\n\n/**\n * The runtime schema accepts any `version` number so the forward-compat\n * UNSUPPORTED_VERSION diagnostic can fire; the exported type narrows it to\n * the literal `1` \u2014 the only version `parseProcessArtifact` will ever hand\n * back \u2014 so downstream consumers get compile-time narrowing.\n */\nexport type ProcessBlock = z.infer<typeof processBlockSchema> & { version: 1 };\nexport type ProcessArtifact = z.infer<typeof processArtifactSchema> & {\n process: ProcessBlock;\n};\n\n// \u2500\u2500 Parser \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction formatPath(path: ReadonlyArray<PropertyKey>): string {\n return path.length > 0 ? z.core.toDotPath(path) : \"(root)\";\n}\n\nfunction issueToDiagnostic(issue: z.core.$ZodIssue): Diagnostic {\n const path = formatPath(issue.path);\n let code: ProcessArtifactDiagnosticCode = \"SCHEMA_INVALID\";\n if (issue.code === \"custom\") {\n const paramCode = issue.params?.code;\n if (typeof paramCode === \"string\") {\n code = paramCode as ProcessArtifactDiagnosticCode;\n }\n }\n\n return {\n severity: \"error\",\n code,\n message: `${path}: ${issue.message}`,\n path,\n };\n}\n\n/**\n * Parse and validate a process artifact. Never throws \u2014 schema and\n * structural violations are returned as error diagnostics with JSON paths\n * instead. Referential checks against a code-derived inventory/predicate\n * list are NOT performed here; see the P2 conformance lint.\n */\nexport function parseProcessArtifact(json: unknown): {\n artifact?: ProcessArtifact;\n diagnostics: Diagnostic[];\n} {\n const result = processArtifactSchema.safeParse(json);\n if (result.success) {\n // Cast is sound: the schema's superRefine rejects any version !== 1, so\n // successful parses always satisfy the narrowed ProcessArtifact type.\n return { artifact: result.data as ProcessArtifact, diagnostics: [] };\n }\n return { diagnostics: result.error.issues.map(issueToDiagnostic) };\n}\n", "/**\n * Process conformance lint \u2014 \"evolution's teeth\".\n *\n * `parseProcessArtifact` (process-artifact.ts) only checks the artifact's\n * own shape: it has no notion of what commands/activities/predicates the\n * as-built workflow actually exposes. `lintProcess` closes that gap: given a\n * parsed artifact, the extractor's as-built `Inventory`, and the named\n * predicate registry the workflow package exports, it diffs as-designed\n * bindings against as-built reality.\n *\n * Pure, synchronous, no I/O \u2014 callers (worker test, CLI, Hub badge) own\n * producing the `Inventory`/`predicateNames` inputs and reporting the\n * output. See docs/plans/2026-07-05-process-artifact-design.md \u00A75.\n */\n\nimport type { Diagnostic, ProcessArtifact } from \"./process-artifact.js\";\n\n/** An inventory command's Temporal shape: a workflow update or a signal. */\nexport type InventoryCommandKind = \"update\" | \"signal\";\n\nexport interface InventoryCommand {\n name: string;\n kind: InventoryCommandKind;\n}\n\n/**\n * The as-built inventory extracted from a workflow's code (design doc \u00A72).\n * Produced by P3's extractor output; never hand-edited. `queries` is carried\n * for completeness but unused by the current lint rules (nothing in a\n * process artifact binds to a query today).\n */\nexport interface Inventory {\n workflowType: string;\n commands: InventoryCommand[];\n queries: string[];\n activities: string[];\n}\n\nfunction stagePath(stageIndex: number): string {\n return `process.stages[${stageIndex}]`;\n}\n\nfunction substepPath(stageIndex: number, substepIndex: number): string {\n return `${stagePath(stageIndex)}.substeps[${substepIndex}]`;\n}\n\n/**\n * Diff an artifact's as-designed bindings against the as-built inventory and\n * predicate registry. Never throws; returns one `Diagnostic` per finding\n * (empty array means fully conformant). Structural checks (schema validity,\n * id uniqueness) are `parseProcessArtifact`'s job and are NOT repeated here\n * \u2014 this function assumes `artifact` already parsed clean, except for the\n * one defensive `complete.predicate` re-check called out below.\n */\nexport function lintProcess(\n artifact: ProcessArtifact,\n inventory: Inventory,\n predicateNames: string[],\n): Diagnostic[] {\n const diagnostics: Diagnostic[] = [];\n const process = artifact.process;\n\n const commandNames = new Set(inventory.commands.map((c) => c.name));\n const activityNames = new Set(inventory.activities);\n const predicateSet = new Set(predicateNames);\n const internalCommands = process.internalCommands ?? [];\n const internalSet = new Set(internalCommands);\n\n /** command name -> path of its first binding site (substeps may rebind the same command). */\n const boundCommandPaths = new Map<string, string>();\n\n const checkPredicate = (predicate: string, path: string): void => {\n if (!predicateSet.has(predicate)) {\n diagnostics.push({\n severity: \"error\",\n code: \"UNKNOWN_PREDICATE\",\n message: `Predicate \"${predicate}\" referenced at ${path} is not in the predicate registry.`,\n path,\n });\n }\n };\n\n process.stages.forEach((stage, stageIndex) => {\n const predicatePath = `${stagePath(stageIndex)}.complete.predicate`;\n\n // Defensive re-check: the schema requires `complete.predicate`, so this\n // only fires if that guarantee was bypassed (e.g. a hand-built artifact\n // that never went through parseProcessArtifact).\n const predicate = (stage.complete as Partial<{ predicate: string }> | undefined)?.predicate;\n if (typeof predicate !== \"string\" || predicate.length === 0) {\n diagnostics.push({\n severity: \"error\",\n code: \"MISSING_STAGE_PREDICATE\",\n message: `Stage \"${stage.id}\" (${stagePath(stageIndex)}) has no complete.predicate.`,\n path: predicatePath,\n });\n } else {\n checkPredicate(predicate, predicatePath);\n }\n\n stage.substeps?.forEach((substep, substepIndex) => {\n const bindPath = substepPath(stageIndex, substepIndex);\n substep.bind.commands?.forEach((commandName, commandIndex) => {\n if (!boundCommandPaths.has(commandName)) {\n boundCommandPaths.set(commandName, `${bindPath}.bind.commands[${commandIndex}]`);\n }\n if (!commandNames.has(commandName)) {\n diagnostics.push({\n severity: \"error\",\n code: \"BOUND_COMMAND_NOT_IN_INVENTORY\",\n message:\n `Command \"${commandName}\" bound by substep \"${substep.id}\" ` +\n `(${bindPath}.bind.commands[${commandIndex}]) does not exist in the inventory.`,\n path: `${bindPath}.bind.commands[${commandIndex}]`,\n });\n }\n });\n substep.bind.activities?.forEach((activityName, activityIndex) => {\n if (!activityNames.has(activityName)) {\n diagnostics.push({\n severity: \"error\",\n code: \"BOUND_ACTIVITY_NOT_IN_INVENTORY\",\n message:\n `Activity \"${activityName}\" bound by substep \"${substep.id}\" ` +\n `(${bindPath}.bind.activities[${activityIndex}]) does not exist in the inventory.`,\n path: `${bindPath}.bind.activities[${activityIndex}]`,\n });\n }\n });\n });\n });\n\n process.outcomes.forEach((outcome, outcomeIndex) => {\n if (\"predicate\" in outcome.when) {\n checkPredicate(outcome.when.predicate, `process.outcomes[${outcomeIndex}].when.predicate`);\n }\n });\n\n const hasSuccessOutcome = process.outcomes.some((o) => o.kind === \"success\");\n const hasFailureOutcome = process.outcomes.some((o) => o.kind === \"failure\");\n if (!hasSuccessOutcome) {\n diagnostics.push({\n severity: \"error\",\n code: \"MISSING_SUCCESS_OUTCOME\",\n message: \"process.outcomes has no outcome with kind \\\"success\\\"; every process needs at least one.\",\n path: \"process.outcomes\",\n });\n }\n if (!hasFailureOutcome) {\n diagnostics.push({\n severity: \"error\",\n code: \"MISSING_FAILURE_OUTCOME\",\n message: \"process.outcomes has no outcome with kind \\\"failure\\\"; every process needs at least one.\",\n path: \"process.outcomes\",\n });\n }\n\n // internalCommands entries must themselves exist in the inventory \u2014 a\n // stale marker (the code path it once named is gone) is a warning, not an\n // error: it's inert, not a lie about current behavior.\n internalCommands.forEach((commandName, index) => {\n if (!commandNames.has(commandName)) {\n diagnostics.push({\n severity: \"warning\",\n code: \"STALE_INTERNAL_COMMAND\",\n message:\n `internalCommands entry \"${commandName}\" (process.internalCommands[${index}]) ` +\n \"does not exist in the inventory; this looks like a stale marker.\",\n path: `process.internalCommands[${index}]`,\n });\n }\n });\n\n // Every inventory command must be bound by some substep OR listed in\n // internalCommands \u2014 no third state. Being in BOTH camps is also a\n // finding (contradictory declaration): the artifact claims the command is\n // deliberately unbound machinery while simultaneously binding it.\n inventory.commands.forEach((command) => {\n const boundPath = boundCommandPaths.get(command.name);\n const isBound = boundPath !== undefined;\n const isInternal = internalSet.has(command.name);\n if (isBound && isInternal) {\n diagnostics.push({\n severity: \"warning\",\n code: \"CONTRADICTORY_COMMAND_DECLARATION\",\n message:\n `Inventory command \"${command.name}\" is both bound (at ${boundPath}) and listed in ` +\n \"internalCommands \u2014 contradictory declaration.\",\n path: boundPath,\n });\n } else if (!isBound && !isInternal) {\n diagnostics.push({\n severity: \"error\",\n code: \"UNBOUND_INVENTORY_COMMAND\",\n message:\n `Inventory command \"${command.name}\" is neither bound by any substep nor listed in ` +\n \"process.internalCommands.\",\n path: \"process.internalCommands\",\n });\n }\n });\n\n if (process.workflowType !== inventory.workflowType) {\n diagnostics.push({\n severity: \"error\",\n code: \"WORKFLOW_TYPE_MISMATCH\",\n message:\n `process.workflowType \"${process.workflowType}\" does not match inventory.workflowType ` +\n `\"${inventory.workflowType}\"; this artifact is bound to the wrong workflow.`,\n path: \"process.workflowType\",\n });\n }\n\n return diagnostics;\n}\n", "export * from \"./workflow-ir.js\";\nexport * from \"./workflow-ir-validate.js\";\nexport { applyPreviewPatch } from \"./apply-preview-patch.js\";\nexport * from \"./process-artifact.js\";\nexport * from \"./process-lint.js\";\n", "/**\n * mesh workflow \u2014 workflow tooling commands\n *\n * Commands:\n * mesh workflow extract-ir <path> Extract WorkflowIR from Temporal workflow source\n * mesh workflow inventory <path> Extract the as-built command/query/activity inventory\n * mesh workflow lint-process <path> Lint a process artifact's bindings against the code inventory\n *\n * Examples:\n * # Extract and print to stdout\n * mesh workflow extract-ir apps/ops/worker/src/workflows/\n *\n * # Extract and upload to S3\n * mesh workflow extract-ir apps/ops/worker/src/workflows/ --app ops --upload mesh-trabian-dev-artifacts\n *\n * # Print the as-built inventory (lint's code-side input)\n * mesh workflow inventory apps/ops/worker/src/workflows/workflows.ts\n *\n * # Lint a process artifact (conformance) \u2014 sibling process/*.process.json auto-discovered\n * mesh workflow lint-process apps/ops/worker/src/workflows.ts --predicates engagementComplete,accountNumbersComplete\n */\n\nimport { Command } from \"commander\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport { createRequire } from \"module\";\nimport { execFileSync } from \"child_process\";\n// workflow-model's RUNTIME exports (parseProcessArtifact / lintProcess) are imported\n// LAZILY inside the lint-process action, not here: @mesh-tech/workflow-model is not in\n// the published CLI's dependency set (build-for-publish strips it), so a top-level static\n// value import crashes `mesh` bootstrap for EVERY command. Type-only imports are erased\n// and safe. (MESH-2003 \u2014 same class as the workflow-viz extractor resolution.)\nimport type { Inventory } from \"@mesh-tech/workflow-model/process-lint\";\nimport type { Diagnostic } from \"@mesh-tech/workflow-model/process-artifact\";\nimport { logError, logInfo, logSuccess, logWarn } from \"../utils/log.js\";\n\ninterface ExtractedWorkflow {\n workflowType: string;\n ir: { name: string; nodes: unknown[]; edges: unknown[] };\n sourceFile: string;\n}\n\n/**\n * Shared subprocess-script helpers: discover auxiliary source files (shared\n * helpers/child workflows) and activity definition files referenced by a\n * workflow file's imports, so the extractor can resolve calls/signatures\n * across files. Emitted verbatim into both the extract-ir and inventory\n * tsx scripts below (they run as plain functions inside the subprocess, not\n * in this process, so they can't be imported/shared as normal TS).\n */\nconst DISCOVERY_HELPERS_SRC = `\nfunction discoverAux(filePath, source) {\n const dir = dirname(filePath);\n const aux = {};\n const re = /import\\\\s+(?:type\\\\s+)?(?:(?:\\\\{[^}]*\\\\}|\\\\*\\\\s+as\\\\s+\\\\w+)(?:\\\\s*,\\\\s*)?)+\\\\s+from\\\\s+[\"'](\\\\.[^\"']+)[\"']/g;\n let m;\n while ((m = re.exec(source)) !== null) {\n const spec = m[1];\n if (!spec.startsWith(\"./\") && !spec.startsWith(\"../\")) continue;\n for (const c of [join(dir, spec.replace(/\\\\.js$/, \".ts\")), join(dir, spec + \".ts\")]) {\n if (existsSync(c) && statSync(c).isFile()) {\n const s = readFileSync(c, \"utf-8\");\n if (s.includes(\"proxyActivities\") || s.includes(\"@temporalio/workflow\") || s.includes(\"wf.\")) {\n aux[spec] = s;\n }\n break;\n }\n }\n }\n return aux;\n}\n\nfunction discoverActivities(filePath, source) {\n const dir = dirname(filePath);\n const acts = {};\n const re = /import\\\\s+type\\\\s+\\\\{[^}]*createActivities[^}]*\\\\}\\\\s+from\\\\s+[\"'](\\\\.[^\"']+)[\"']/g;\n let m;\n while ((m = re.exec(source)) !== null) {\n const spec = m[1];\n for (const c of [join(dir, spec.replace(/\\\\.js$/, \".ts\")), join(dir, spec + \".ts\")]) {\n if (existsSync(c) && statSync(c).isFile()) {\n acts[spec] = readFileSync(c, \"utf-8\");\n const actDir = dirname(c);\n try {\n for (const sib of readdirSync(actDir)) {\n if (!sib.endsWith(\".ts\") || sib === basename(c)) continue;\n const sp = join(actDir, sib);\n if (statSync(sp).isFile()) {\n acts[spec.replace(/\\\\/[^/]+$/, \"/\" + sib.replace(\".ts\", \".js\"))] = readFileSync(sp, \"utf-8\");\n }\n }\n } catch {}\n break;\n }\n }\n }\n return acts;\n}\n\n/**\n * Discover a sibling process artifact for a workflow file: a \"process/\"\n * directory containing \"*.process.json\" files, checked both next to the\n * workflow file itself AND next to its parent directory (worker packages\n * typically nest the workflow file under \"src/\", with \"process/\" a sibling\n * of \"src/\" at the package root, not of the file directly \u2014 e.g.\n * \"worker/src/workflows.ts\" + \"worker/process/*.process.json\"). Since\n * extractWorkflowIR itself validates the artifact (schema errors and a\n * workflowType mismatch both fall back with a warning, never throw \u2014 P6),\n * this only needs a best-effort guess at the workflow's name to avoid\n * bothering with an OBVIOUSLY unrelated file in a multi-workflow directory \u2014\n * a quick regex for the first exported async function, same derivation\n * extractWorkflowIR falls back to absent an explicit \\`name\\` override.\n * Returns the parsed JSON (unknown to this script) or undefined.\n */\nfunction discoverProcessArtifact(filePath, source) {\n const fileDir = dirname(filePath);\n const candidateDirs = [join(fileDir, \"process\"), join(fileDir, \"..\", \"process\")];\n\n const nameMatch = source.match(/export\\\\s+async\\\\s+function\\\\s+(\\\\w+)/);\n const guessedName = nameMatch ? nameMatch[1] : undefined;\n\n for (const procDir of candidateDirs) {\n if (!existsSync(procDir) || !statSync(procDir).isDirectory()) continue;\n for (const entry of readdirSync(procDir)) {\n if (!entry.endsWith(\".process.json\")) continue;\n const entryPath = join(procDir, entry);\n if (!statSync(entryPath).isFile()) continue;\n try {\n const parsed = JSON.parse(readFileSync(entryPath, \"utf-8\"));\n if (!guessedName || parsed?.process?.workflowType === guessedName) {\n return parsed;\n }\n } catch {\n // Not valid JSON \u2014 skip; extractWorkflowIR would reject it anyway.\n }\n }\n }\n return undefined;\n}\n`;\n\n/**\n * Resolve the path to @mesh-tech/workflow-viz/ast-extractor source file.\n * Uses createRequire from the CLI's own location so workspace links resolve.\n */\nfunction resolveExtractorPath(): string | null {\n try {\n const require = createRequire(import.meta.url);\n const resolved = require.resolve(\"@mesh-tech/workflow-viz/ast-extractor\");\n return resolved;\n } catch {\n return null;\n }\n}\n\n/**\n * Run the extraction in a tsx subprocess. The extractor depends on ts-morph\n * and workflow-viz exports TypeScript source (no dist build), so we need tsx\n * rather than plain Node.\n *\n * `explicitProcessPath`, when given, is read here (parent process) and baked\n * into the script verbatim, applied to EVERY discovered workflow file\n * (extractWorkflowIR's own workflowType check drops it wherever it doesn't\n * match \u2014 P6). Absent that, each file gets a sibling `process/*.process.json`\n * lookup (see `discoverProcessArtifact` in DISCOVERY_HELPERS_SRC).\n *\n * Returns parsed ExtractedWorkflow[] or null on failure.\n */\nfunction runExtraction(\n targetPath: string,\n extractorPath: string,\n explicitProcessPath?: string,\n): ExtractedWorkflow[] | null {\n let explicitProcessArtifact: unknown;\n if (explicitProcessPath) {\n try {\n explicitProcessArtifact = JSON.parse(fs.readFileSync(explicitProcessPath, \"utf-8\"));\n } catch (err) {\n logError(\n `Could not read/parse --process ${explicitProcessPath}: ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n return null;\n }\n }\n\n // Build an inline script that does the extraction and writes JSON to stdout.\n // Stderr is used for progress messages.\n const script = `\nimport { extractWorkflowIR } from \"${extractorPath.replace(/\\\\/g, \"/\")}\";\nimport { readFileSync, readdirSync, statSync, existsSync } from \"node:fs\";\nimport { basename, dirname, join } from \"node:path\";\n${DISCOVERY_HELPERS_SRC}\nconst target = ${JSON.stringify(targetPath)};\nconst explicitProcessArtifact = ${JSON.stringify(explicitProcessArtifact ?? null)};\nconst stat = statSync(target);\nconst files = stat.isDirectory()\n ? readdirSync(target).filter(f => f.endsWith(\".ts\") && f !== \"index.ts\").map(f => join(target, f))\n : [target];\n\nconst results = [];\nfor (const file of files) {\n const source = readFileSync(file, \"utf-8\");\n if (!source.includes(\"proxyActivities\") && !source.includes(\"@temporalio/workflow\")) continue;\n try {\n const aux = discoverAux(file, source);\n const acts = discoverActivities(file, source);\n const processArtifact = explicitProcessArtifact ?? discoverProcessArtifact(file, source);\n const extractOptions = { auxiliarySources: aux, activitySources: acts };\n if (processArtifact) extractOptions.processArtifact = processArtifact;\n const ir = extractWorkflowIR(source, extractOptions);\n const name = ir.name || basename(file, \".ts\");\n results.push({ workflowType: name, ir, sourceFile: file });\n process.stderr.write(\" \" + name + \" (\" + ir.nodes.length + \" nodes, \" + ir.edges.length + \" edges)\\\\n\");\n } catch (err) {\n process.stderr.write(\" skip \" + file + \": \" + err.message + \"\\\\n\");\n }\n}\nprocess.stdout.write(JSON.stringify(results));\n`;\n\n try {\n const result = execFileSync(\"npx\", [\"tsx\", \"--eval\", script], {\n encoding: \"utf-8\",\n stdio: [\"pipe\", \"pipe\", \"inherit\"],\n maxBuffer: 10 * 1024 * 1024,\n });\n return JSON.parse(result);\n } catch (err) {\n logError(\n `Extraction subprocess failed: ${err instanceof Error ? err.message : String(err)}`,\n );\n return null;\n }\n}\n\n/**\n * Run inventory extraction in a tsx subprocess \u2014 same aux-discovery pattern\n * as {@link runExtraction}, but calls `extractInventory` instead of\n * `extractWorkflowIR` and returns the as-built {@link Inventory} per\n * discovered workflow file.\n *\n * Returns parsed Inventory[] or null on failure.\n */\nfunction runInventoryExtraction(\n targetPath: string,\n extractorPath: string,\n): Inventory[] | null {\n const script = `\nimport { extractInventory } from \"${extractorPath.replace(/\\\\/g, \"/\")}\";\nimport { readFileSync, readdirSync, statSync, existsSync } from \"node:fs\";\nimport { basename, dirname, join } from \"node:path\";\n${DISCOVERY_HELPERS_SRC}\nconst target = ${JSON.stringify(targetPath)};\nconst stat = statSync(target);\nconst files = stat.isDirectory()\n ? readdirSync(target).filter(f => f.endsWith(\".ts\") && f !== \"index.ts\").map(f => join(target, f))\n : [target];\n\nconst results = [];\nfor (const file of files) {\n const source = readFileSync(file, \"utf-8\");\n if (!source.includes(\"proxyActivities\") && !source.includes(\"@temporalio/workflow\")) continue;\n try {\n const aux = discoverAux(file, source);\n const acts = discoverActivities(file, source);\n const inventory = extractInventory(source, { auxiliarySources: aux, activitySources: acts });\n results.push(inventory);\n process.stderr.write(\" \" + inventory.workflowType + \" (\" + inventory.commands.length + \" commands, \" + inventory.queries.length + \" queries, \" + inventory.activities.length + \" activities)\\\\n\");\n } catch (err) {\n process.stderr.write(\" skip \" + file + \": \" + err.message + \"\\\\n\");\n }\n}\nprocess.stdout.write(JSON.stringify(results));\n`;\n\n try {\n const result = execFileSync(\"npx\", [\"tsx\", \"--eval\", script], {\n encoding: \"utf-8\",\n stdio: [\"pipe\", \"pipe\", \"inherit\"],\n maxBuffer: 10 * 1024 * 1024,\n });\n return JSON.parse(result);\n } catch (err) {\n logError(\n `Inventory extraction subprocess failed: ${err instanceof Error ? err.message : String(err)}`,\n );\n return null;\n }\n}\n\n/** One workflow file's lint-process inputs, as produced by the subprocess. */\ninterface LintExtractionResult {\n inventory: Inventory;\n processArtifact: unknown;\n sourceFile: string;\n}\n\n/**\n * Run inventory + process-artifact discovery in a tsx subprocess, for\n * `lint-process`. Same aux/activity discovery as {@link runInventoryExtraction};\n * additionally resolves each file's process artifact the same way\n * {@link runExtraction} does \u2014 `explicitProcessPath` (baked in, applied to\n * every discovered file) if given, else the sibling `process/*.process.json`\n * lookup (`discoverProcessArtifact` in DISCOVERY_HELPERS_SRC).\n *\n * Parsing/linting the artifact happens back in the parent process (not\n * here) since `parseProcessArtifact`/`lintProcess` are plain TS this file\n * can import directly \u2014 no need to duplicate them into the subprocess script.\n *\n * Returns parsed LintExtractionResult[] or null on failure.\n */\nfunction runLintExtraction(\n targetPath: string,\n extractorPath: string,\n explicitProcessPath?: string,\n): LintExtractionResult[] | null {\n let explicitProcessArtifact: unknown;\n if (explicitProcessPath) {\n try {\n explicitProcessArtifact = JSON.parse(fs.readFileSync(explicitProcessPath, \"utf-8\"));\n } catch (err) {\n logError(\n `Could not read/parse --process ${explicitProcessPath}: ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n return null;\n }\n }\n\n const script = `\nimport { extractInventory } from \"${extractorPath.replace(/\\\\/g, \"/\")}\";\nimport { readFileSync, readdirSync, statSync, existsSync } from \"node:fs\";\nimport { basename, dirname, join } from \"node:path\";\n${DISCOVERY_HELPERS_SRC}\nconst target = ${JSON.stringify(targetPath)};\nconst explicitProcessArtifact = ${JSON.stringify(explicitProcessArtifact ?? null)};\nconst stat = statSync(target);\nconst files = stat.isDirectory()\n ? readdirSync(target).filter(f => f.endsWith(\".ts\") && f !== \"index.ts\").map(f => join(target, f))\n : [target];\n\nconst results = [];\nfor (const file of files) {\n const source = readFileSync(file, \"utf-8\");\n if (!source.includes(\"proxyActivities\") && !source.includes(\"@temporalio/workflow\")) continue;\n try {\n const aux = discoverAux(file, source);\n const acts = discoverActivities(file, source);\n const inventory = extractInventory(source, { auxiliarySources: aux, activitySources: acts });\n const processArtifact = explicitProcessArtifact ?? discoverProcessArtifact(file, source) ?? null;\n results.push({ inventory, processArtifact, sourceFile: file });\n process.stderr.write(\" \" + inventory.workflowType + \" (\" + inventory.commands.length + \" commands, \" + inventory.queries.length + \" queries, \" + inventory.activities.length + \" activities)\\\\n\");\n } catch (err) {\n process.stderr.write(\" skip \" + file + \": \" + err.message + \"\\\\n\");\n }\n}\nprocess.stdout.write(JSON.stringify(results));\n`;\n\n try {\n const result = execFileSync(\"npx\", [\"tsx\", \"--eval\", script], {\n encoding: \"utf-8\",\n stdio: [\"pipe\", \"pipe\", \"inherit\"],\n maxBuffer: 10 * 1024 * 1024,\n });\n return JSON.parse(result);\n } catch (err) {\n logError(\n `Lint extraction subprocess failed: ${err instanceof Error ? err.message : String(err)}`,\n );\n return null;\n }\n}\n\nasync function uploadToS3(\n bucket: string,\n appName: string,\n workflows: ExtractedWorkflow[],\n): Promise<void> {\n const { S3Client, PutObjectCommand } = await import(\"@aws-sdk/client-s3\");\n const s3 = new S3Client({ region: process.env.AWS_REGION ?? \"us-east-2\" });\n\n for (const wf of workflows) {\n const key = `workflow-ir/${appName}/${wf.workflowType}.json`;\n const body = JSON.stringify(wf.ir, null, 2);\n logInfo(` Uploading s3://${bucket}/${key} (${body.length} bytes)`);\n await s3.send(\n new PutObjectCommand({\n Bucket: bucket,\n Key: key,\n Body: body,\n ContentType: \"application/json\",\n }),\n );\n }\n\n const manifest = {\n extractedAt: new Date().toISOString(),\n app: appName,\n workflows: Object.fromEntries(\n workflows.map((wf) => [\n wf.workflowType,\n {\n sourceFile: wf.sourceFile,\n nodeCount: (wf.ir.nodes as unknown[]).length,\n edgeCount: (wf.ir.edges as unknown[]).length,\n },\n ]),\n ),\n };\n const manifestKey = `workflow-ir/${appName}/_manifest.json`;\n logInfo(` Uploading s3://${bucket}/${manifestKey}`);\n await s3.send(\n new PutObjectCommand({\n Bucket: bucket,\n Key: manifestKey,\n Body: JSON.stringify(manifest, null, 2),\n ContentType: \"application/json\",\n }),\n );\n}\n\nexport function registerWorkflowCommands(program: Command): void {\n const workflow = program\n .command(\"workflow\")\n .description(\"Workflow tooling \u2014 IR extraction, visualization\");\n\n workflow\n .command(\"extract-ir <path>\")\n .description(\n \"Extract WorkflowIR from Temporal workflow source files\\n\\n\" +\n \"Parses TypeScript workflow code into a graph (nodes + edges) for visualization.\\n\" +\n \"Supports single files or directories.\",\n )\n .option(\"--app <name>\", \"Application name (used as S3 key prefix)\")\n .option(\n \"--upload <bucket>\",\n \"S3 bucket to upload extracted IR (requires --app)\",\n )\n .option(\n \"--process <path>\",\n \"Path to a process artifact JSON file (docs/plans/2026-07-05-process-artifact-design.md \u00A71); \" +\n \"renders substeps/actors/outcomes in place of a BUSINESS_STAGES map. Absent this flag, a sibling \" +\n \"process/*.process.json is auto-discovered per workflow file.\",\n )\n .action(\n async (\n targetPath: string,\n opts: { app?: string; upload?: string; process?: string },\n ) => {\n try {\n const resolvedPath = path.resolve(targetPath);\n if (!fs.existsSync(resolvedPath)) {\n logError(`Path does not exist: ${resolvedPath}`);\n process.exitCode = 1;\n return;\n }\n\n let resolvedProcessPath: string | undefined;\n if (opts.process) {\n resolvedProcessPath = path.resolve(opts.process);\n if (!fs.existsSync(resolvedProcessPath)) {\n logError(`--process path does not exist: ${resolvedProcessPath}`);\n process.exitCode = 1;\n return;\n }\n }\n\n const extractorPath = resolveExtractorPath();\n if (!extractorPath) {\n logError(\n \"Cannot resolve @mesh-tech/workflow-viz/ast-extractor.\\n\" +\n \"Workflow viz is an OPTIONAL peer of the CLI. In the monorepo it is already linked;\\n\" +\n \"from a registry install, add it: npm i -g @mesh-tech/workflow-viz\",\n );\n process.exitCode = 1;\n return;\n }\n\n logInfo(`Extracting WorkflowIR from ${resolvedPath}`);\n const results = runExtraction(resolvedPath, extractorPath, resolvedProcessPath);\n\n if (!results || results.length === 0) {\n if (results) logWarn(\"No workflows found\");\n process.exitCode = results ? 0 : 1;\n return;\n }\n\n for (const wf of results) {\n logSuccess(\n ` ${wf.workflowType} (${(wf.ir.nodes as unknown[]).length} nodes, ${(wf.ir.edges as unknown[]).length} edges)`,\n );\n }\n\n if (opts.upload && opts.app) {\n logInfo(\n `Uploading ${results.length} workflow IR(s) to s3://${opts.upload}/workflow-ir/${opts.app}/`,\n );\n await uploadToS3(opts.upload, opts.app, results);\n logSuccess(\"Upload complete\");\n } else if (opts.upload || opts.app) {\n logWarn(\"Both --app and --upload required for S3 upload\");\n } else {\n console.log(JSON.stringify(results.map((r) => r.ir), null, 2));\n }\n } catch (error) {\n logError(\n `Extraction failed: ${error instanceof Error ? error.message : String(error)}`,\n );\n process.exitCode = 1;\n }\n },\n );\n\n workflow\n .command(\"inventory <path>\")\n .description(\n \"Extract the as-built command/query/activity inventory from Temporal workflow source\\n\\n\" +\n \"The inventory ({ workflowType, commands, queries, activities }) is the process-\\n\" +\n \"conformance lint's code-side input \u2014 it is never hand-edited. Supports single\\n\" +\n \"files or directories.\",\n )\n .action(async (targetPath: string) => {\n try {\n const resolvedPath = path.resolve(targetPath);\n if (!fs.existsSync(resolvedPath)) {\n logError(`Path does not exist: ${resolvedPath}`);\n process.exitCode = 1;\n return;\n }\n\n const extractorPath = resolveExtractorPath();\n if (!extractorPath) {\n logError(\n \"Cannot resolve @mesh-tech/workflow-viz/ast-extractor.\\n\" +\n \"Workflow viz is an OPTIONAL peer of the CLI. In the monorepo it is already linked;\\n\" +\n \"from a registry install, add it: npm i -g @mesh-tech/workflow-viz\",\n );\n process.exitCode = 1;\n return;\n }\n\n logInfo(`Extracting inventory from ${resolvedPath}`);\n const results = runInventoryExtraction(resolvedPath, extractorPath);\n\n if (!results || results.length === 0) {\n if (results) logWarn(\"No workflows found\");\n process.exitCode = results ? 0 : 1;\n return;\n }\n\n for (const inv of results) {\n logSuccess(\n ` ${inv.workflowType} (${inv.commands.length} commands, ${inv.queries.length} queries, ${inv.activities.length} activities)`,\n );\n }\n\n console.log(JSON.stringify(results.length === 1 ? results[0] : results, null, 2));\n } catch (error) {\n logError(\n `Inventory extraction failed: ${error instanceof Error ? error.message : String(error)}`,\n );\n process.exitCode = 1;\n }\n });\n\n workflow\n .command(\"lint-process <path>\")\n .description(\n \"Lint a process artifact's bindings against the as-built code inventory\\n\\n\" +\n \"Reuses the inventory extraction's aux/activity discovery, resolves the process\\n\" +\n \"artifact (--process, or the same sibling process/*.process.json discovery\\n\" +\n \"extract-ir uses), then runs parseProcessArtifact + lintProcess against it.\\n\\n\" +\n \"Without --predicates, the CLI cannot verify predicate names against the worker's\\n\" +\n \"registry (it has no way to execute it) \u2014 predicate-existence findings are skipped\\n\" +\n \"and a note is printed; every other rule (bindings, coverage, ids, outcomes,\\n\" +\n \"workflowType) still runs. Pass --predicates for full conformance, or rely on the\\n\" +\n \"worker's own process-conformance test which has the registry in-process.\",\n )\n .option(\n \"--process <path>\",\n \"Path to a process artifact JSON file. Absent this flag, a sibling \" +\n \"process/*.process.json is auto-discovered per workflow file.\",\n )\n .option(\n \"--predicates <names>\",\n \"Comma-separated named-predicate registry (enables UNKNOWN_PREDICATE checks)\",\n )\n .action(async (targetPath: string, opts: { process?: string; predicates?: string }) => {\n try {\n const resolvedPath = path.resolve(targetPath);\n if (!fs.existsSync(resolvedPath)) {\n logError(`Path does not exist: ${resolvedPath}`);\n process.exitCode = 1;\n return;\n }\n\n let resolvedProcessPath: string | undefined;\n if (opts.process) {\n resolvedProcessPath = path.resolve(opts.process);\n if (!fs.existsSync(resolvedProcessPath)) {\n logError(`--process path does not exist: ${resolvedProcessPath}`);\n process.exitCode = 1;\n return;\n }\n }\n\n const extractorPath = resolveExtractorPath();\n if (!extractorPath) {\n logError(\n \"Cannot resolve @mesh-tech/workflow-viz/ast-extractor.\\n\" +\n \"Workflow viz is an OPTIONAL peer of the CLI. In the monorepo it is already linked;\\n\" +\n \"from a registry install, add it: npm i -g @mesh-tech/workflow-viz\",\n );\n process.exitCode = 1;\n return;\n }\n\n // Lazy-load workflow-model's runtime exports (see the import note at top): a\n // static import would take down `mesh` bootstrap in the published CLI. Fail\n // gracefully here, exactly like the extractor resolution above.\n let parseProcessArtifact: typeof import(\"@mesh-tech/workflow-model\").parseProcessArtifact;\n let lintProcess: typeof import(\"@mesh-tech/workflow-model\").lintProcess;\n try {\n ({ parseProcessArtifact } = await import(\"@mesh-tech/workflow-model\"));\n ({ lintProcess } = await import(\"@mesh-tech/workflow-model\"));\n } catch {\n logError(\n \"Cannot resolve @mesh-tech/workflow-model (parseProcessArtifact / lintProcess).\\n\" +\n \"It is bundled into the published CLI \u2014 on a registry install this means a broken install; reinstall the CLI. In the monorepo, run the scoped install (pnpm bootstrap:worktree @mesh-tech/mesh-cli).\",\n );\n process.exitCode = 1;\n return;\n }\n\n const predicateNames = opts.predicates\n ? opts.predicates.split(\",\").map((s) => s.trim()).filter((s) => s.length > 0)\n : undefined;\n\n if (!predicateNames) {\n logWarn(\n \"predicate checks skipped \u2014 pass --predicates or run the worker conformance test\",\n );\n }\n\n logInfo(`Linting process artifact(s) against ${resolvedPath}`);\n const results = runLintExtraction(resolvedPath, extractorPath, resolvedProcessPath);\n\n if (!results || results.length === 0) {\n if (results) logWarn(\"No workflows found\");\n process.exitCode = results ? 0 : 1;\n return;\n }\n\n let hasError = false;\n\n for (const { inventory, processArtifact, sourceFile } of results) {\n console.log(`\\n${inventory.workflowType} (${sourceFile})`);\n\n if (!processArtifact) {\n logError(\n \" No process artifact found (checked --process and sibling process/*.process.json).\",\n );\n hasError = true;\n continue;\n }\n\n const { artifact, diagnostics: parseDiagnostics } = parseProcessArtifact(processArtifact);\n let diagnostics: Diagnostic[] = parseDiagnostics;\n\n if (artifact) {\n const lintDiagnostics = lintProcess(artifact, inventory, predicateNames ?? []);\n const reportable = predicateNames\n ? lintDiagnostics\n : lintDiagnostics.filter((d) => d.code !== \"UNKNOWN_PREDICATE\");\n diagnostics = diagnostics.concat(reportable);\n }\n\n if (diagnostics.length === 0) {\n logSuccess(\" clean\");\n } else {\n for (const d of diagnostics) {\n const line = ` [${d.severity}] ${d.code} ${d.path}: ${d.message}`;\n if (d.severity === \"error\") {\n logError(line);\n hasError = true;\n } else {\n logWarn(line);\n }\n }\n }\n }\n\n process.exitCode = hasError ? 1 : 0;\n } catch (error) {\n logError(`Lint failed: ${error instanceof Error ? error.message : String(error)}`);\n process.exitCode = 1;\n }\n });\n}\n", "/**\n * The `mesh` command tree, as data.\n *\n * `bin/mesh.ts` used to build the commander program inline and immediately\n * parse it, which meant the tree only existed inside a running CLI process.\n * The docs generator needs to *walk* the tree without executing anything, so\n * construction lives here and the bin is a thin runner.\n *\n * Nothing in this module may perform I/O or read credentials at import time \u2014\n * `mesh docs cli-reference` imports it in a plain node process with no AWS\n * config, no Docker, and no TTY.\n */\n\nimport { Command } from \"commander\";\n\nimport { registerArtifactsCommands } from \"./commands/artifacts.js\";\nimport { registerClusterCommands } from \"./commands/cluster.js\";\nimport { registerConversationsCommands } from \"./commands/conversations.js\";\nimport { registerCreateAppCommand } from \"./commands/create-app.js\";\nimport { registerDbCommands } from \"./commands/db/index.js\";\nimport { registerDeployCommand } from \"./commands/deploy.js\";\nimport { registerDevCommand } from \"./commands/dev.js\";\nimport { registerDocsCommand } from \"./commands/docs.js\";\nimport { registerHubCommands } from \"./commands/hub/index.js\";\nimport { registerInitCommands } from \"./commands/init.js\";\nimport { registerInstallShimCommand } from \"./commands/install-shim.js\";\nimport { registerLocalCommands } from \"./commands/local/index.js\";\nimport { registerLoginCommand } from \"./commands/login.js\";\nimport { registerRegistryCommands } from \"./commands/registry.js\";\nimport { registerSecretsCommands } from \"./commands/secrets/index.js\";\nimport { registerSkillsCommands } from \"./commands/skills.js\";\nimport { registerStackCommand } from \"./commands/stack.js\";\nimport { registerTemporalCommands } from \"./commands/temporal.js\";\nimport { registerTenantCommands } from \"./commands/tenant.js\";\nimport { registerTunnelCommands } from \"./commands/tunnel/index.js\";\nimport { registerVcsCommands } from \"./commands/vcs/index.js\";\nimport { registerVpnCommands } from \"./commands/vpn/index.js\";\nimport { registerWorkflowCommands } from \"./commands/workflow.js\";\n\nexport const CLI_NAME = \"mesh\";\nexport const CLI_DESCRIPTION = \"CLI for Mesh Lab development utilities\";\n\n/**\n * Build a fresh `mesh` program.\n *\n * @param options.version version string for `--version`. Resolving the real\n * one costs git spawns, so callers that don't need it (the docs generator)\n * pass nothing and get a placeholder that never reaches generated output.\n */\nexport function createProgram(options: { version?: string } = {}): Command {\n const program = new Command();\n\n program.name(CLI_NAME).description(CLI_DESCRIPTION);\n if (options.version !== undefined) program.version(options.version);\n\n registerLoginCommand(program);\n registerRegistryCommands(program);\n registerDbCommands(program);\n registerDeployCommand(program);\n registerDevCommand(program);\n registerCreateAppCommand(program);\n registerDocsCommand(program);\n registerStackCommand(program);\n registerTunnelCommands(program);\n registerSecretsCommands(program);\n registerArtifactsCommands(program);\n registerConversationsCommands(program);\n registerVpnCommands(program);\n registerWorkflowCommands(program);\n registerTemporalCommands(program);\n registerClusterCommands(program);\n registerVcsCommands(program);\n registerLocalCommands(program);\n registerHubCommands(program);\n registerSkillsCommands(program);\n registerInitCommands(program);\n registerTenantCommands(program);\n registerInstallShimCommand(program);\n\n return program;\n}\n", "#!/usr/bin/env node\n/**\n * mesh - CLI for Mesh Lab development utilities\n *\n * The command tree itself lives in `src/program.ts` so `mesh docs\n * cli-reference` can walk it without running the CLI. This file is only the\n * runner: resolve the version, build the program, parse.\n *\n * For the command list, run `mesh --help` or read the generated reference\n * (`docs/portal/generated/cli-reference.md`) \u2014 a hand-maintained list in this\n * header is exactly the kind of prose that goes stale.\n */\n\nimport { createProgram } from \"../src/program.js\";\nimport { handleCliError } from \"../src/utils/errors.js\";\n// Version + provenance (source vs published dist, commit, build date) so a\n// stale shim or stale global install is diagnosable from `mesh --version`\n// alone (MESH-2479). Resolution lives in src/utils/build-info.ts.\nimport { formatVersionLine, resolveCliRuntime } from \"../src/utils/build-info.js\";\n\n// Full provenance (two git spawns in source mode, ~16ms) is only paid when\n// --version will actually print it; every other invocation resolves the\n// cheap fs-only version string.\nconst wantsVersion = process.argv.includes(\"--version\") || process.argv.includes(\"-V\");\n\nconst program = createProgram({\n version: wantsVersion\n ? formatVersionLine(resolveCliRuntime())\n : resolveCliRuntime({ vcs: false }).version,\n});\n\nprogram.parseAsync().catch(handleCliError);\n"],
5
+ "mappings": "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",
6
+ "names": ["prefix", "join", "path", "init_pull", "init_pull", "path", "npmrcPath", "fs", "path", "sep", "creds", "chalk", "fs", "path", "path", "fs", "execFile", "execFileSync", "existsSync", "socketPath", "resolve", "fs", "os", "path", "SSMClient", "GetParameterCommand", "execFileSync", "SSMClient", "GetParameterCommand", "resolve", "existsSync", "readFileSync", "readdirSync", "dirname", "join", "repoRoot", "fs", "path", "resolve", "resolve", "SSMClient", "GetParameterCommand", "GetParametersByPathCommand", "net", "SecretsManagerClient", "CreateSecretCommand", "PutSecretValueCommand", "resolve", "execFileSync", "fs", "os", "path", "logPath", "resolve", "execFileSync", "fs", "path", "input", "waitForPort", "SecretsManagerClient", "GetSecretValueCommand", "SSMClient", "z", "init_src", "fs", "os", "path", "SSMClient", "init_src", "SecretsManagerClient", "GetSecretValueCommand", "SSMClient", "put", "GetParameterCommand", "fs", "path", "prefix", "execFileSync", "fs", "os", "path", "execFileSync", "fs", "net", "path", "repoRoot", "resolve", "execFileSync", "path", "decodeJwtPayload", "resolve", "execFileSync", "spawn", "spawnSync", "fs", "net", "os", "path", "SecretsManagerClient", "GetSecretValueCommand", "resolve", "findAppRoot", "hostname", "program", "startTokenServer", "sessionName", "devOutput", "stack", "rawDevOutput", "finalDevOutput", "SSMClient", "GetParameterCommand", "GetParametersByPathCommand", "execFileSync", "fs", "path", "net", "crypto", "fs", "net", "path", "execFileSync", "resolve", "fs", "net", "os", "path", "spawn", "execFileSync", "resolve", "hostname", "net", "deriveLoginServer", "findFreePort", "resolve", "canConnect", "execFileSync", "net", "findFreePort", "resolve", "program", "init_vpn", "body", "execFileSync", "fs", "path", "execFileSync", "fs", "path", "SSMClient", "GetParameterCommand", "assumeRole", "assumeRoleWithWebIdentity", "npmrcPath", "program", "decodeJwtPayload", "http", "crypto", "fs", "path", "execFileSync", "parseTenantEnv", "SSMClient", "GetParameterCommand", "resolve", "showStatus", "program", "runRegistryLogin", "init_vpn", "fs", "path", "program", "DEFAULT_AUTH_CONTEXT", "spawnSync", "program", "program", "pullConversation", "writeBundle", "fs", "path", "execFileSync", "fence", "program", "fs", "os", "path", "fileURLToPath", "input", "program", "spawn", "init_credentials", "spawn", "net", "sleep", "resolve", "password", "spawn", "net", "fs", "path", "SecretsManagerClient", "GetSecretValueCommand", "checkPort", "resolve", "sleep", "startTunnelBackground", "program", "init_credentials", "existsSync", "readFileSync", "dirname", "join", "relative", "parseYaml", "execFileSync", "program", "z", "slugify", "init_schema", "existsSync", "readdirSync", "readFileSync", "statSync", "path", "slugify", "repoRoot", "init_schema", "execFileSync", "mkdirSync", "readFileSync", "rmSync", "writeFileSync", "path", "parseYaml", "pageRoute", "prefix", "repoRoot", "init_schema", "os", "prefix", "path", "program", "spawn", "existsSync", "mkdirSync", "mkdtempSync", "readFileSync", "writeFileSync", "tmpdir", "path", "repoRoot", "resolve", "createProgram", "extractCliReference", "renderCliReferenceMarkdown", "execFileSync", "fs", "path", "fileURLToPath", "createServer", "join", "sep", "resolve", "execFileSync", "existsSync", "mkdirSync", "readFileSync", "renameSync", "rmSync", "writeFileSync", "tmpdir", "path", "npmrcPath", "parse", "execFileSync", "appendFileSync", "existsSync", "writeFileSync", "path", "resolve", "result", "spawn", "fs", "path", "findProjectRoot", "readConfig", "createProgram", "extractCliReference", "renderCliReferenceMarkdown", "repoRoot", "program", "runDocsStart", "runDocsStop", "runDocsServeStatic", "runDocsList", "execFileSync", "fs", "net", "os", "path", "chalk", "findFreePort", "resolve", "isPortListening", "program", "chalk", "fs", "path", "login", "runRegistryLogin", "runChecks", "program", "copyTemplate", "findPackageRoot", "execFileSync", "fs", "os", "path", "program", "execFile", "execFileSync", "fs", "os", "path", "promisify", "execFileAsync", "chalk", "resolve", "program", "spawn", "SecretsManagerClient", "GetSecretValueCommand", "logInfo", "logSuccess", "logError", "execCommand", "init_exec", "SSMClient", "SecretsManagerClient", "GetSecretValueCommand", "existingVal", "svc", "values", "merged", "SSMClient", "GetParametersByPathCommand", "SecretsManagerClient", "GetSecretValueCommand", "PutSecretValueCommand", "CreateSecretCommand", "normalizeEntry", "normalizeFields", "discoverExternalServices", "extractNonSecretFields", "isResourceNotFound", "writeSecret", "prefix", "Option", "program", "execCommand", "init_exec", "execFileSync", "path", "fs", "parseYaml", "login", "program", "init_stack", "execFileSync", "crypto", "spawnSync", "writeFileSync", "mkdirSync", "homedir", "dirname", "join", "resolve", "namespace", "connect", "input", "output", "serializeHistoryToFixture", "program", "chalk", "fs", "path", "program", "spawn", "fs", "os", "path", "SecretsManagerClient", "GetSecretValueCommand", "input", "resolve", "program", "init_tunnel", "execFile", "promisify", "resolveTarget", "execFileAsync", "getValidToken", "path", "execFileAsync", "writeFile", "mkdir", "join", "dirname", "path", "path", "resolveTarget", "readFile", "join", "resolveTarget", "execFileAsync", "path", "call", "path", "resolveTarget", "program", "path", "z", "path", "process", "process", "path", "src_exports", "init_src", "fs", "path", "createRequire", "execFileSync", "require", "program", "parseProcessArtifact", "lintProcess", "Command", "program", "init_stack", "init_tunnel", "init_vpn"]
7
+ }