@mesh-tech/mesh-cli 0.1.1 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (504) hide show
  1. package/assets/intent/agents-fence.md +10 -0
  2. package/assets/intent/intent-claude-gate.mjs +255 -0
  3. package/assets/log-shipper.mjs +94 -0
  4. package/bin/mesh.mjs +80 -0
  5. package/dist/bin/mesh.d.ts +7 -9
  6. package/dist/bin/mesh.d.ts.map +1 -1
  7. package/dist/bin/mesh.js +20826 -37
  8. package/dist/bin/mesh.js.map +7 -1
  9. package/dist/build-info.json +4 -0
  10. package/dist/src/commands/agent-api-client.d.ts +79 -0
  11. package/dist/src/commands/agent-api-client.d.ts.map +1 -0
  12. package/dist/src/commands/agent-api-client.js +170 -0
  13. package/dist/src/commands/agent-api-client.js.map +1 -0
  14. package/dist/src/commands/artifacts.d.ts +13 -0
  15. package/dist/src/commands/artifacts.d.ts.map +1 -0
  16. package/dist/src/commands/artifacts.js +140 -0
  17. package/dist/src/commands/artifacts.js.map +1 -0
  18. package/dist/src/commands/cluster.d.ts +45 -0
  19. package/dist/src/commands/cluster.d.ts.map +1 -0
  20. package/dist/src/commands/cluster.js +259 -0
  21. package/dist/src/commands/cluster.js.map +1 -0
  22. package/dist/src/commands/conversations.d.ts +61 -0
  23. package/dist/src/commands/conversations.d.ts.map +1 -0
  24. package/dist/src/commands/conversations.js +239 -0
  25. package/dist/src/commands/conversations.js.map +1 -0
  26. package/dist/src/commands/create-app.d.ts +26 -3
  27. package/dist/src/commands/create-app.d.ts.map +1 -1
  28. package/dist/src/commands/create-app.js +465 -107
  29. package/dist/src/commands/create-app.js.map +1 -1
  30. package/dist/src/commands/deploy.d.ts +19 -0
  31. package/dist/src/commands/deploy.d.ts.map +1 -1
  32. package/dist/src/commands/deploy.js +83 -142
  33. package/dist/src/commands/deploy.js.map +1 -1
  34. package/dist/src/commands/dev-doctor.d.ts +137 -0
  35. package/dist/src/commands/dev-doctor.d.ts.map +1 -0
  36. package/dist/src/commands/dev-doctor.js +671 -0
  37. package/dist/src/commands/dev-doctor.js.map +1 -0
  38. package/dist/src/commands/dev-launch.d.ts +59 -0
  39. package/dist/src/commands/dev-launch.d.ts.map +1 -0
  40. package/dist/src/commands/dev-launch.js +118 -0
  41. package/dist/src/commands/dev-launch.js.map +1 -0
  42. package/dist/src/commands/dev-token-server.d.ts +32 -0
  43. package/dist/src/commands/dev-token-server.d.ts.map +1 -0
  44. package/dist/src/commands/dev-token-server.js +68 -0
  45. package/dist/src/commands/dev-token-server.js.map +1 -0
  46. package/dist/src/commands/dev.d.ts +289 -2
  47. package/dist/src/commands/dev.d.ts.map +1 -1
  48. package/dist/src/commands/dev.js +2501 -574
  49. package/dist/src/commands/dev.js.map +1 -1
  50. package/dist/src/commands/docs.d.ts +3 -0
  51. package/dist/src/commands/docs.d.ts.map +1 -0
  52. package/dist/src/commands/docs.js +262 -0
  53. package/dist/src/commands/docs.js.map +1 -0
  54. package/dist/src/commands/hub/index.d.ts +99 -0
  55. package/dist/src/commands/hub/index.d.ts.map +1 -0
  56. package/dist/src/commands/hub/index.js +452 -0
  57. package/dist/src/commands/hub/index.js.map +1 -0
  58. package/dist/src/commands/init.d.ts +65 -0
  59. package/dist/src/commands/init.d.ts.map +1 -0
  60. package/dist/src/commands/init.js +370 -0
  61. package/dist/src/commands/init.js.map +1 -0
  62. package/dist/src/commands/install-shim.d.ts +21 -0
  63. package/dist/src/commands/install-shim.d.ts.map +1 -0
  64. package/dist/src/commands/install-shim.js +132 -0
  65. package/dist/src/commands/install-shim.js.map +1 -0
  66. package/dist/src/commands/local/auth-provision.d.ts +71 -0
  67. package/dist/src/commands/local/auth-provision.d.ts.map +1 -0
  68. package/dist/src/commands/local/auth-provision.js +286 -0
  69. package/dist/src/commands/local/auth-provision.js.map +1 -0
  70. package/dist/src/commands/local/dev-local.d.ts +97 -0
  71. package/dist/src/commands/local/dev-local.d.ts.map +1 -0
  72. package/dist/src/commands/local/dev-local.js +306 -0
  73. package/dist/src/commands/local/dev-local.js.map +1 -0
  74. package/dist/src/commands/local/docker-runner.d.ts +37 -0
  75. package/dist/src/commands/local/docker-runner.d.ts.map +1 -0
  76. package/dist/src/commands/local/docker-runner.js +104 -0
  77. package/dist/src/commands/local/docker-runner.js.map +1 -0
  78. package/dist/src/commands/local/helpers.d.ts +22 -0
  79. package/dist/src/commands/local/helpers.d.ts.map +1 -0
  80. package/dist/src/commands/local/helpers.js +46 -0
  81. package/dist/src/commands/local/helpers.js.map +1 -0
  82. package/dist/src/commands/local/hub-local.d.ts +51 -0
  83. package/dist/src/commands/local/hub-local.d.ts.map +1 -0
  84. package/dist/src/commands/local/hub-local.js +197 -0
  85. package/dist/src/commands/local/hub-local.js.map +1 -0
  86. package/dist/src/commands/local/index.d.ts +23 -0
  87. package/dist/src/commands/local/index.d.ts.map +1 -0
  88. package/dist/src/commands/local/index.js +386 -0
  89. package/dist/src/commands/local/index.js.map +1 -0
  90. package/dist/src/commands/local/mocks.d.ts +361 -0
  91. package/dist/src/commands/local/mocks.d.ts.map +1 -0
  92. package/dist/src/commands/local/mocks.js +756 -0
  93. package/dist/src/commands/local/mocks.js.map +1 -0
  94. package/dist/src/commands/local/seed-zitadel.d.ts +151 -0
  95. package/dist/src/commands/local/seed-zitadel.d.ts.map +1 -0
  96. package/dist/src/commands/local/seed-zitadel.js +408 -0
  97. package/dist/src/commands/local/seed-zitadel.js.map +1 -0
  98. package/dist/src/commands/local/seed.d.ts +106 -0
  99. package/dist/src/commands/local/seed.d.ts.map +1 -0
  100. package/dist/src/commands/local/seed.js +252 -0
  101. package/dist/src/commands/local/seed.js.map +1 -0
  102. package/dist/src/commands/local/stack.d.ts +173 -0
  103. package/dist/src/commands/local/stack.d.ts.map +1 -0
  104. package/dist/src/commands/local/stack.js +499 -0
  105. package/dist/src/commands/local/stack.js.map +1 -0
  106. package/dist/src/commands/login.d.ts +256 -12
  107. package/dist/src/commands/login.d.ts.map +1 -1
  108. package/dist/src/commands/login.js +978 -50
  109. package/dist/src/commands/login.js.map +1 -1
  110. package/dist/src/commands/peer-addressing.d.ts +51 -0
  111. package/dist/src/commands/peer-addressing.d.ts.map +1 -0
  112. package/dist/src/commands/peer-addressing.js +64 -0
  113. package/dist/src/commands/peer-addressing.js.map +1 -0
  114. package/dist/src/commands/port-ownership.d.ts +69 -0
  115. package/dist/src/commands/port-ownership.d.ts.map +1 -0
  116. package/dist/src/commands/port-ownership.js +161 -0
  117. package/dist/src/commands/port-ownership.js.map +1 -0
  118. package/dist/src/commands/registry-publish.d.ts +3 -0
  119. package/dist/src/commands/registry-publish.d.ts.map +1 -0
  120. package/dist/src/commands/registry-publish.js +161 -0
  121. package/dist/src/commands/registry-publish.js.map +1 -0
  122. package/dist/src/commands/registry.d.ts +146 -2
  123. package/dist/src/commands/registry.d.ts.map +1 -1
  124. package/dist/src/commands/registry.js +541 -85
  125. package/dist/src/commands/registry.js.map +1 -1
  126. package/dist/src/commands/secrets/index.d.ts.map +1 -1
  127. package/dist/src/commands/secrets/index.js +15 -1
  128. package/dist/src/commands/secrets/index.js.map +1 -1
  129. package/dist/src/commands/secrets/migrate-config.d.ts +24 -0
  130. package/dist/src/commands/secrets/migrate-config.d.ts.map +1 -0
  131. package/dist/src/commands/secrets/migrate-config.js +277 -0
  132. package/dist/src/commands/secrets/migrate-config.js.map +1 -0
  133. package/dist/src/commands/secrets/set.d.ts +1 -0
  134. package/dist/src/commands/secrets/set.d.ts.map +1 -1
  135. package/dist/src/commands/secrets/set.js +96 -2
  136. package/dist/src/commands/secrets/set.js.map +1 -1
  137. package/dist/src/commands/skills.d.ts +34 -0
  138. package/dist/src/commands/skills.d.ts.map +1 -0
  139. package/dist/src/commands/skills.js +207 -0
  140. package/dist/src/commands/skills.js.map +1 -0
  141. package/dist/src/commands/stack.d.ts.map +1 -1
  142. package/dist/src/commands/stack.js +361 -23
  143. package/dist/src/commands/stack.js.map +1 -1
  144. package/dist/src/commands/temporal.d.ts +15 -0
  145. package/dist/src/commands/temporal.d.ts.map +1 -0
  146. package/dist/src/commands/temporal.js +781 -0
  147. package/dist/src/commands/temporal.js.map +1 -0
  148. package/dist/src/commands/tenant.d.ts +56 -0
  149. package/dist/src/commands/tenant.d.ts.map +1 -0
  150. package/dist/src/commands/tenant.js +233 -0
  151. package/dist/src/commands/tenant.js.map +1 -0
  152. package/dist/src/commands/tunnel/index.d.ts +49 -3
  153. package/dist/src/commands/tunnel/index.d.ts.map +1 -1
  154. package/dist/src/commands/tunnel/index.js +331 -8
  155. package/dist/src/commands/tunnel/index.js.map +1 -1
  156. package/dist/src/commands/vcs/clone.d.ts +3 -0
  157. package/dist/src/commands/vcs/clone.d.ts.map +1 -0
  158. package/dist/src/commands/vcs/clone.js +20 -0
  159. package/dist/src/commands/vcs/clone.js.map +1 -0
  160. package/dist/src/commands/vcs/common.d.ts +21 -0
  161. package/dist/src/commands/vcs/common.d.ts.map +1 -0
  162. package/dist/src/commands/vcs/common.js +62 -0
  163. package/dist/src/commands/vcs/common.js.map +1 -0
  164. package/dist/src/commands/vcs/drafts.d.ts +13 -0
  165. package/dist/src/commands/vcs/drafts.d.ts.map +1 -0
  166. package/dist/src/commands/vcs/drafts.js +45 -0
  167. package/dist/src/commands/vcs/drafts.js.map +1 -0
  168. package/dist/src/commands/vcs/get.d.ts +8 -0
  169. package/dist/src/commands/vcs/get.d.ts.map +1 -0
  170. package/dist/src/commands/vcs/get.js +61 -0
  171. package/dist/src/commands/vcs/get.js.map +1 -0
  172. package/dist/src/commands/vcs/index.d.ts +3 -0
  173. package/dist/src/commands/vcs/index.d.ts.map +1 -0
  174. package/dist/src/commands/vcs/index.js +58 -0
  175. package/dist/src/commands/vcs/index.js.map +1 -0
  176. package/dist/src/commands/vcs/propose.d.ts +23 -0
  177. package/dist/src/commands/vcs/propose.d.ts.map +1 -0
  178. package/dist/src/commands/vcs/propose.js +94 -0
  179. package/dist/src/commands/vcs/propose.js.map +1 -0
  180. package/dist/src/commands/vcs/review.d.ts +15 -0
  181. package/dist/src/commands/vcs/review.d.ts.map +1 -0
  182. package/dist/src/commands/vcs/review.js +35 -0
  183. package/dist/src/commands/vcs/review.js.map +1 -0
  184. package/dist/src/commands/vcs-enrich.d.ts +15 -0
  185. package/dist/src/commands/vcs-enrich.d.ts.map +1 -0
  186. package/dist/src/commands/vcs-enrich.js +28 -0
  187. package/dist/src/commands/vcs-enrich.js.map +1 -0
  188. package/dist/src/commands/vpn/index.d.ts +24 -0
  189. package/dist/src/commands/vpn/index.d.ts.map +1 -0
  190. package/dist/src/commands/vpn/index.js +543 -0
  191. package/dist/src/commands/vpn/index.js.map +1 -0
  192. package/dist/src/commands/vpn/tunnel.d.ts +11 -0
  193. package/dist/src/commands/vpn/tunnel.d.ts.map +1 -0
  194. package/dist/src/commands/vpn/tunnel.js +188 -0
  195. package/dist/src/commands/vpn/tunnel.js.map +1 -0
  196. package/dist/src/commands/workflow.d.ts +24 -0
  197. package/dist/src/commands/workflow.d.ts.map +1 -0
  198. package/dist/src/commands/workflow.js +577 -0
  199. package/dist/src/commands/workflow.js.map +1 -0
  200. package/dist/src/docs/assemble.d.ts +217 -0
  201. package/dist/src/docs/assemble.d.ts.map +1 -0
  202. package/dist/src/docs/assemble.js +739 -0
  203. package/dist/src/docs/assemble.js.map +1 -0
  204. package/dist/src/docs/cli-reference.d.ts +93 -0
  205. package/dist/src/docs/cli-reference.d.ts.map +1 -0
  206. package/dist/src/docs/cli-reference.js +256 -0
  207. package/dist/src/docs/cli-reference.js.map +1 -0
  208. package/dist/src/docs/discover.d.ts +60 -0
  209. package/dist/src/docs/discover.d.ts.map +1 -0
  210. package/dist/src/docs/discover.js +233 -0
  211. package/dist/src/docs/discover.js.map +1 -0
  212. package/dist/src/docs/portal.d.ts +79 -0
  213. package/dist/src/docs/portal.d.ts.map +1 -0
  214. package/dist/src/docs/portal.js +242 -0
  215. package/dist/src/docs/portal.js.map +1 -0
  216. package/dist/src/docs/registry-docs.d.ts +43 -0
  217. package/dist/src/docs/registry-docs.d.ts.map +1 -0
  218. package/dist/src/docs/registry-docs.js +138 -0
  219. package/dist/src/docs/registry-docs.js.map +1 -0
  220. package/dist/src/docs/schema.d.ts +48 -0
  221. package/dist/src/docs/schema.d.ts.map +1 -0
  222. package/dist/src/docs/schema.js +96 -0
  223. package/dist/src/docs/schema.js.map +1 -0
  224. package/dist/src/docs/serve.d.ts +27 -0
  225. package/dist/src/docs/serve.d.ts.map +1 -0
  226. package/dist/src/docs/serve.js +102 -0
  227. package/dist/src/docs/serve.js.map +1 -0
  228. package/dist/src/docs/start.d.ts +80 -0
  229. package/dist/src/docs/start.d.ts.map +1 -0
  230. package/dist/src/docs/start.js +313 -0
  231. package/dist/src/docs/start.js.map +1 -0
  232. package/dist/src/eval/agent-eval.d.mts +14 -0
  233. package/dist/src/eval/agent-eval.d.mts.map +1 -0
  234. package/dist/src/eval/agent-eval.mjs +273 -0
  235. package/dist/src/eval/agent-eval.mjs.map +1 -0
  236. package/dist/src/index.js +624 -7
  237. package/dist/src/index.js.map +7 -1
  238. package/dist/src/program.d.ts +26 -0
  239. package/dist/src/program.d.ts.map +1 -0
  240. package/dist/src/program.js +76 -0
  241. package/dist/src/program.js.map +1 -0
  242. package/dist/src/utils/auth-preflight.d.ts +159 -0
  243. package/dist/src/utils/auth-preflight.d.ts.map +1 -0
  244. package/dist/src/utils/auth-preflight.js +298 -0
  245. package/dist/src/utils/auth-preflight.js.map +1 -0
  246. package/dist/src/utils/aws-auth.d.ts +181 -0
  247. package/dist/src/utils/aws-auth.d.ts.map +1 -0
  248. package/dist/src/utils/aws-auth.js +527 -0
  249. package/dist/src/utils/aws-auth.js.map +1 -0
  250. package/dist/src/utils/bastion.d.ts +1 -1
  251. package/dist/src/utils/bastion.d.ts.map +1 -1
  252. package/dist/src/utils/bastion.js +29 -8
  253. package/dist/src/utils/bastion.js.map +1 -1
  254. package/dist/src/utils/build-info.d.ts +33 -0
  255. package/dist/src/utils/build-info.d.ts.map +1 -0
  256. package/dist/src/utils/build-info.js +102 -0
  257. package/dist/src/utils/build-info.js.map +1 -0
  258. package/dist/src/utils/capture-history.d.ts +62 -0
  259. package/dist/src/utils/capture-history.d.ts.map +1 -0
  260. package/dist/src/utils/capture-history.js +94 -0
  261. package/dist/src/utils/capture-history.js.map +1 -0
  262. package/dist/src/utils/deploy-preflight.d.ts +52 -0
  263. package/dist/src/utils/deploy-preflight.d.ts.map +1 -0
  264. package/dist/src/utils/deploy-preflight.js +183 -0
  265. package/dist/src/utils/deploy-preflight.js.map +1 -0
  266. package/dist/src/utils/errors.d.ts +75 -0
  267. package/dist/src/utils/errors.d.ts.map +1 -0
  268. package/dist/src/utils/errors.js +106 -0
  269. package/dist/src/utils/errors.js.map +1 -0
  270. package/dist/src/utils/first-party-contexts.d.ts +40 -0
  271. package/dist/src/utils/first-party-contexts.d.ts.map +1 -0
  272. package/dist/src/utils/first-party-contexts.js +53 -0
  273. package/dist/src/utils/first-party-contexts.js.map +1 -0
  274. package/dist/src/utils/index.d.ts +2 -0
  275. package/dist/src/utils/index.d.ts.map +1 -1
  276. package/dist/src/utils/index.js +2 -0
  277. package/dist/src/utils/index.js.map +1 -1
  278. package/dist/src/utils/kubeconfig.d.ts +62 -0
  279. package/dist/src/utils/kubeconfig.d.ts.map +1 -0
  280. package/dist/src/utils/kubeconfig.js +118 -0
  281. package/dist/src/utils/kubeconfig.js.map +1 -0
  282. package/dist/src/utils/log.d.ts +27 -1
  283. package/dist/src/utils/log.d.ts.map +1 -1
  284. package/dist/src/utils/log.js +59 -5
  285. package/dist/src/utils/log.js.map +1 -1
  286. package/dist/src/utils/pid.d.ts +47 -0
  287. package/dist/src/utils/pid.d.ts.map +1 -0
  288. package/dist/src/utils/pid.js +83 -0
  289. package/dist/src/utils/pid.js.map +1 -0
  290. package/dist/src/utils/pulumi-run.d.ts +23 -0
  291. package/dist/src/utils/pulumi-run.d.ts.map +1 -0
  292. package/dist/src/utils/pulumi-run.js +112 -0
  293. package/dist/src/utils/pulumi-run.js.map +1 -0
  294. package/dist/src/utils/pulumi.d.ts +15 -0
  295. package/dist/src/utils/pulumi.d.ts.map +1 -1
  296. package/dist/src/utils/pulumi.js +35 -0
  297. package/dist/src/utils/pulumi.js.map +1 -1
  298. package/dist/src/utils/reachability.d.ts +29 -0
  299. package/dist/src/utils/reachability.d.ts.map +1 -0
  300. package/dist/src/utils/reachability.js +81 -0
  301. package/dist/src/utils/reachability.js.map +1 -0
  302. package/dist/src/utils/recover-conversation.d.ts +154 -0
  303. package/dist/src/utils/recover-conversation.d.ts.map +1 -0
  304. package/dist/src/utils/recover-conversation.js +314 -0
  305. package/dist/src/utils/recover-conversation.js.map +1 -0
  306. package/dist/src/utils/registry-broker.d.ts +148 -0
  307. package/dist/src/utils/registry-broker.d.ts.map +1 -0
  308. package/dist/src/utils/registry-broker.js +180 -0
  309. package/dist/src/utils/registry-broker.js.map +1 -0
  310. package/dist/src/utils/socks-forward.d.ts +40 -0
  311. package/dist/src/utils/socks-forward.d.ts.map +1 -0
  312. package/dist/src/utils/socks-forward.js +97 -0
  313. package/dist/src/utils/socks-forward.js.map +1 -0
  314. package/dist/src/utils/stack-flag.d.ts +23 -0
  315. package/dist/src/utils/stack-flag.d.ts.map +1 -0
  316. package/dist/src/utils/stack-flag.js +41 -0
  317. package/dist/src/utils/stack-flag.js.map +1 -0
  318. package/dist/src/utils/tailscale-targets.d.ts +52 -0
  319. package/dist/src/utils/tailscale-targets.d.ts.map +1 -0
  320. package/dist/src/utils/tailscale-targets.js +93 -0
  321. package/dist/src/utils/tailscale-targets.js.map +1 -0
  322. package/dist/src/utils/tailscale.d.ts +277 -0
  323. package/dist/src/utils/tailscale.d.ts.map +1 -0
  324. package/dist/src/utils/tailscale.js +1007 -0
  325. package/dist/src/utils/tailscale.js.map +1 -0
  326. package/dist/src/utils/temporal-auth.d.ts +43 -0
  327. package/dist/src/utils/temporal-auth.d.ts.map +1 -0
  328. package/dist/src/utils/temporal-auth.js +176 -0
  329. package/dist/src/utils/temporal-auth.js.map +1 -0
  330. package/dist/src/utils/temporal-codec.d.ts +101 -0
  331. package/dist/src/utils/temporal-codec.d.ts.map +1 -0
  332. package/dist/src/utils/temporal-codec.js +319 -0
  333. package/dist/src/utils/temporal-codec.js.map +1 -0
  334. package/dist/src/utils/tunnel-ownership.d.ts +130 -0
  335. package/dist/src/utils/tunnel-ownership.d.ts.map +1 -0
  336. package/dist/src/utils/tunnel-ownership.js +274 -0
  337. package/dist/src/utils/tunnel-ownership.js.map +1 -0
  338. package/dist/src/utils/vpn-join.d.ts +32 -0
  339. package/dist/src/utils/vpn-join.d.ts.map +1 -0
  340. package/dist/src/utils/vpn-join.js +62 -0
  341. package/dist/src/utils/vpn-join.js.map +1 -0
  342. package/dist/src/utils/vpn.d.ts +62 -0
  343. package/dist/src/utils/vpn.d.ts.map +1 -0
  344. package/dist/src/utils/vpn.js +183 -0
  345. package/dist/src/utils/vpn.js.map +1 -0
  346. package/dist/src/utils/workflow-fingerprint.d.ts +49 -0
  347. package/dist/src/utils/workflow-fingerprint.d.ts.map +1 -0
  348. package/dist/src/utils/workflow-fingerprint.js +135 -0
  349. package/dist/src/utils/workflow-fingerprint.js.map +1 -0
  350. package/dist/src/utils/worktree-identity.d.ts +86 -0
  351. package/dist/src/utils/worktree-identity.d.ts.map +1 -0
  352. package/dist/src/utils/worktree-identity.js +164 -0
  353. package/dist/src/utils/worktree-identity.js.map +1 -0
  354. package/fragments/agents/AGENTS.md.hbs +92 -0
  355. package/fragments/agents/CLAUDE.md.hbs +8 -0
  356. package/fragments/base/Pulumi.dev.yaml.hbs +10 -0
  357. package/fragments/base/Pulumi.yaml.hbs +9 -0
  358. package/fragments/base/index.ts.hbs +107 -0
  359. package/fragments/base/package.json.hbs +22 -0
  360. package/{templates/api-web-db/api → fragments/base}/tsconfig.json +3 -4
  361. package/fragments/bucket/api/src/storage.ts.hbs +81 -0
  362. package/fragments/database/api/src/db.ts.hbs +23 -0
  363. package/fragments/database/prisma/schema.prisma.hbs +18 -0
  364. package/{templates/api-web-db → fragments/service}/api/.dockerignore +2 -0
  365. package/fragments/service/api/package.json.hbs +40 -0
  366. package/fragments/service/api/src/index.ts.hbs +58 -0
  367. package/{templates/api-web-db → fragments/service/api}/tsconfig.json +5 -3
  368. package/fragments/temporal/worker/.dockerignore +4 -0
  369. package/fragments/temporal/worker/Dockerfile +15 -0
  370. package/{templates/temporal-api-worker → fragments/temporal}/worker/package.json.hbs +3 -2
  371. package/fragments/temporal/worker/src/activities.ts.hbs +14 -0
  372. package/fragments/temporal/worker/src/worker.ts.hbs +27 -0
  373. package/fragments/temporal/worker/src/workflows.ts.hbs +24 -0
  374. package/fragments/temporal/worker/tsconfig.json +13 -0
  375. package/package.json +36 -22
  376. package/skills/core/SKILL.md +365 -0
  377. package/skills/pull-remote-agent-context/SKILL.md +194 -0
  378. package/stack/docker-compose.hub.yml +134 -0
  379. package/stack/docker-compose.yml +447 -0
  380. package/stack/hub/Dockerfile.api +18 -0
  381. package/stack/hub/Dockerfile.auth +10 -0
  382. package/stack/hub/Dockerfile.ui +10 -0
  383. package/stack/init/01-databases.sql +12 -0
  384. package/stack/observability/blackbox.yml +20 -0
  385. package/stack/observability/otel-collector.yaml +73 -0
  386. package/stack/observability/prometheus.yml +36 -0
  387. package/stack/observability/tempo.yaml +25 -0
  388. package/stack/temporal/local.yaml +44 -0
  389. package/templates/api-auth/AGENTS.md.hbs +16 -0
  390. package/templates/api-auth/Pulumi.dev.yaml.hbs +8 -0
  391. package/templates/api-auth/Pulumi.yaml.hbs +8 -0
  392. package/templates/api-auth/README.md.hbs +67 -0
  393. package/templates/api-auth/api/package.json.hbs +28 -0
  394. package/templates/api-auth/api/src/index.ts.hbs +96 -0
  395. package/templates/api-auth/api/src/schema.ts.hbs +35 -0
  396. package/templates/api-auth/api/src/seed-authz.ts.hbs +48 -0
  397. package/templates/api-auth/api/src/spicedb-http-provider.ts.hbs +89 -0
  398. package/templates/api-auth/index.ts.hbs +65 -0
  399. package/templates/api-auth/package.json.hbs +20 -0
  400. package/templates/api-auth/skills/develop/SKILL.md.hbs +32 -0
  401. package/templates/api-role-gating/AGENTS.md.hbs +20 -0
  402. package/templates/api-role-gating/Pulumi.dev.yaml.hbs +8 -0
  403. package/templates/api-role-gating/Pulumi.yaml.hbs +8 -0
  404. package/templates/api-role-gating/README.md.hbs +64 -0
  405. package/templates/api-role-gating/api/Dockerfile +17 -0
  406. package/templates/api-role-gating/api/package.json.hbs +28 -0
  407. package/templates/api-role-gating/api/src/authn.ts.hbs +29 -0
  408. package/templates/api-role-gating/api/src/authz.ts.hbs +12 -0
  409. package/templates/api-role-gating/api/src/main.ts.hbs +58 -0
  410. package/templates/api-role-gating/api/src/schema.ts.hbs +22 -0
  411. package/templates/api-role-gating/api/tsconfig.json +13 -0
  412. package/templates/api-role-gating/index.ts.hbs +107 -0
  413. package/templates/api-role-gating/package.json.hbs +21 -0
  414. package/templates/api-role-gating/skills/develop/SKILL.md.hbs +60 -0
  415. package/templates/api-role-gating/tsconfig.json +10 -0
  416. package/templates/apps-repo/README.md.hbs +24 -0
  417. package/templates/apps-repo/gitignore +41 -0
  418. package/templates/apps-repo/npmrc.hbs +7 -0
  419. package/templates/apps-repo/package.json.hbs +15 -0
  420. package/templates/apps-repo/pnpm-workspace.yaml +3 -0
  421. package/templates/apps-repo/tsconfig.json +18 -0
  422. package/templates/external-service/AGENTS.md.hbs +20 -0
  423. package/templates/external-service/Pulumi.dev.yaml.hbs +8 -0
  424. package/templates/external-service/Pulumi.yaml.hbs +8 -0
  425. package/templates/external-service/README.md.hbs +56 -0
  426. package/templates/external-service/api/Dockerfile +15 -0
  427. package/templates/external-service/api/package.json.hbs +25 -0
  428. package/templates/external-service/api/src/index.ts.hbs +81 -0
  429. package/templates/external-service/index.ts.hbs +82 -0
  430. package/templates/external-service/mocks/vendorpay/package.json.hbs +9 -0
  431. package/templates/external-service/mocks/vendorpay/server.mjs.hbs +61 -0
  432. package/templates/external-service/package.json.hbs +34 -0
  433. package/templates/external-service/skills/develop/SKILL.md.hbs +55 -0
  434. package/templates/external-service/tsconfig.json +10 -0
  435. package/templates/platform-repo/AGENTS.md.hbs +18 -0
  436. package/templates/platform-repo/README.md.hbs +38 -0
  437. package/templates/platform-repo/core/Pulumi.yaml.hbs +12 -0
  438. package/templates/platform-repo/core/Pulumi.{{tenant}}-{{env}}.yaml.hbs +57 -0
  439. package/templates/platform-repo/core/index.ts +62 -0
  440. package/templates/platform-repo/core/package.json.hbs +22 -0
  441. package/templates/platform-repo/core/tsconfig.json +8 -0
  442. package/templates/platform-repo/package.json.hbs +15 -0
  443. package/templates/platform-repo/platform/Pulumi.yaml.hbs +12 -0
  444. package/templates/platform-repo/platform/Pulumi.{{tenant}}-{{env}}.yaml.hbs +59 -0
  445. package/templates/platform-repo/platform/index.ts +95 -0
  446. package/templates/platform-repo/platform/package.json.hbs +26 -0
  447. package/templates/platform-repo/platform/tsconfig.json +8 -0
  448. package/templates/platform-repo/pnpm-workspace.yaml +3 -0
  449. package/templates/workflow/AGENTS.md.hbs +15 -0
  450. package/templates/workflow/Pulumi.dev.yaml.hbs +8 -0
  451. package/templates/workflow/Pulumi.yaml.hbs +8 -0
  452. package/templates/workflow/README.md.hbs +45 -0
  453. package/templates/workflow/api/.dockerignore +4 -0
  454. package/templates/workflow/api/Dockerfile +15 -0
  455. package/templates/{temporal-api-worker → workflow}/api/package.json.hbs +8 -6
  456. package/templates/workflow/api/src/index.ts.hbs +130 -0
  457. package/templates/workflow/api/tsconfig.json +14 -0
  458. package/templates/workflow/index.ts.hbs +67 -0
  459. package/templates/workflow/package.json.hbs +20 -0
  460. package/templates/workflow/skills/develop/SKILL.md.hbs +32 -0
  461. package/templates/workflow/tsconfig.json +10 -0
  462. package/templates/workflow/worker/.dockerignore +4 -0
  463. package/templates/workflow/worker/Dockerfile +13 -0
  464. package/templates/workflow/worker/package.json.hbs +25 -0
  465. package/templates/workflow/worker/src/worker.ts.hbs +24 -0
  466. package/templates/workflow/worker/tsconfig.json +14 -0
  467. package/dist/src/commands/devbox.d.ts +0 -22
  468. package/dist/src/commands/devbox.d.ts.map +0 -1
  469. package/dist/src/commands/devbox.js +0 -463
  470. package/dist/src/commands/devbox.js.map +0 -1
  471. package/templates/api-web-db/api/Dockerfile +0 -16
  472. package/templates/api-web-db/api/package.json.hbs +0 -21
  473. package/templates/api-web-db/api/src/index.ts.hbs +0 -123
  474. package/templates/api-web-db/package.json.hbs +0 -27
  475. package/templates/api-web-db/sst.config.ts.hbs +0 -151
  476. package/templates/api-web-db/web/.dockerignore +0 -3
  477. package/templates/api-web-db/web/Dockerfile +0 -17
  478. package/templates/api-web-db/web/app/lib/db.server.ts +0 -36
  479. package/templates/api-web-db/web/app/root.tsx +0 -29
  480. package/templates/api-web-db/web/app/routes/home.tsx.hbs +0 -114
  481. package/templates/api-web-db/web/app/routes.ts +0 -3
  482. package/templates/api-web-db/web/package.json.hbs +0 -30
  483. package/templates/api-web-db/web/prisma/schema.prisma +0 -25
  484. package/templates/api-web-db/web/prisma.config.ts +0 -18
  485. package/templates/api-web-db/web/react-router.config.ts +0 -5
  486. package/templates/api-web-db/web/tsconfig.json +0 -19
  487. package/templates/api-web-db/web/vite.config.ts +0 -9
  488. package/templates/temporal-api-worker/README.md.hbs +0 -133
  489. package/templates/temporal-api-worker/api/src/index.ts.hbs +0 -145
  490. package/templates/temporal-api-worker/package.json.hbs +0 -29
  491. package/templates/temporal-api-worker/sst.config.ts.hbs +0 -161
  492. package/templates/temporal-api-worker/worker/Dockerfile +0 -11
  493. package/templates/temporal-api-worker/worker/src/bundle-workflows.ts +0 -38
  494. package/templates/temporal-api-worker/worker/src/worker.ts.hbs +0 -93
  495. /package/templates/{temporal-api-worker → api-auth}/api/.dockerignore +0 -0
  496. /package/templates/{temporal-api-worker → api-auth}/api/Dockerfile +0 -0
  497. /package/templates/{temporal-api-worker → api-auth}/api/tsconfig.json +0 -0
  498. /package/templates/{temporal-api-worker → api-auth}/tsconfig.json +0 -0
  499. /package/templates/{temporal-api-worker/worker → api-role-gating/api}/.dockerignore +0 -0
  500. /package/templates/{temporal-api-worker/worker → external-service/api}/tsconfig.json +0 -0
  501. /package/templates/{temporal-api-worker → workflow}/api/src/encryption-codec.ts +0 -0
  502. /package/templates/{temporal-api-worker → workflow}/worker/src/activities.ts.hbs +0 -0
  503. /package/templates/{temporal-api-worker → workflow}/worker/src/encryption-codec.ts +0 -0
  504. /package/templates/{temporal-api-worker → workflow}/worker/src/workflows.ts.hbs +0 -0
@@ -0,0 +1,73 @@
1
+ # Local OTel Collector — the SAME ingestion topology the hosted platform runs
2
+ # (OpenTelemetryStack: collector → Loki via OTLP, → Tempo via OTLP gRPC,
3
+ # metrics scraped by Prometheus). Locally the k8sattributes processor's job —
4
+ # stamping k8s.namespace.name / k8s.deployment.name / k8s.container.name on
5
+ # every record — is done at the edges instead:
6
+ # - filelog: derives them from the log path
7
+ # /var/log/mesh-apps/{namespace}/{service}.log (written by
8
+ # `mesh dev --local`, namespace = {tenant}-{env}-{app})
9
+ # - otlp: apps send OTEL_RESOURCE_ATTRIBUTES injected by `mesh dev --local`
10
+ # so hub-api's LogQL/TraceQL queries run UNCHANGED against local data.
11
+ receivers:
12
+ otlp:
13
+ protocols:
14
+ grpc:
15
+ endpoint: 0.0.0.0:4317
16
+ http:
17
+ endpoint: 0.0.0.0:4318
18
+ filelog:
19
+ include:
20
+ - /var/log/mesh-apps/*/*.log
21
+ start_at: beginning
22
+ include_file_path: true
23
+ operators:
24
+ - type: regex_parser
25
+ parse_from: attributes["log.file.path"]
26
+ regex: '^/var/log/mesh-apps/(?P<mesh_namespace>[^/]+)/(?P<mesh_service>[^/]+)\.log$'
27
+ - type: move
28
+ from: attributes.mesh_namespace
29
+ to: resource["k8s.namespace.name"]
30
+ - type: move
31
+ from: attributes.mesh_service
32
+ to: resource["k8s.deployment.name"]
33
+ - type: copy
34
+ from: resource["k8s.deployment.name"]
35
+ to: resource["k8s.container.name"]
36
+
37
+ processors:
38
+ batch: {}
39
+
40
+ exporters:
41
+ # Same exporter shape as the hosted collector: Loki's native OTLP endpoint.
42
+ # Loki promotes k8s.namespace.name / k8s.deployment.name /
43
+ # k8s.container.name to index labels (k8s_namespace_name, …) by default.
44
+ otlphttp/loki:
45
+ endpoint: http://loki:3100/otlp
46
+ otlp/tempo:
47
+ endpoint: tempo:4317
48
+ tls:
49
+ insecure: true
50
+ prometheus:
51
+ endpoint: 0.0.0.0:8889
52
+ resource_to_telemetry_conversion:
53
+ enabled: true
54
+
55
+ extensions:
56
+ health_check:
57
+ endpoint: 0.0.0.0:13133
58
+
59
+ service:
60
+ extensions: [health_check]
61
+ pipelines:
62
+ logs:
63
+ receivers: [otlp, filelog]
64
+ processors: [batch]
65
+ exporters: [otlphttp/loki]
66
+ traces:
67
+ receivers: [otlp]
68
+ processors: [batch]
69
+ exporters: [otlp/tempo]
70
+ metrics:
71
+ receivers: [otlp]
72
+ processors: [batch]
73
+ exporters: [prometheus]
@@ -0,0 +1,36 @@
1
+ # Local Prometheus — scrapes the OTel collector's exporter so app metrics
2
+ # sent via OTLP land where hub-api's PROMETHEUS_URL queries expect them.
3
+ global:
4
+ scrape_interval: 15s
5
+
6
+ scrape_configs:
7
+ - job_name: otel-collector
8
+ static_configs:
9
+ - targets: ['otel-collector:8889']
10
+
11
+ # External-service health probes (blackbox exporter) — the hosted Probe-CR
12
+ # topology: targets + labels come from file_sd JSON written by the CLI
13
+ # (mesh dev --externals / ExternalService wiring); probe_success/probe_duration
14
+ # land with type/tenant/env/app/external_service labels, exactly what
15
+ # hub-api's health enrichment and uptime views query.
16
+ - job_name: external-services
17
+ metrics_path: /probe
18
+ params:
19
+ module: [http_2xx]
20
+ scrape_interval: 30s
21
+ file_sd_configs:
22
+ - files: ['/etc/prometheus/probes/*.json']
23
+ refresh_interval: 15s
24
+ relabel_configs:
25
+ - source_labels: [__address__]
26
+ target_label: __param_target
27
+ - source_labels: [__param_target]
28
+ target_label: instance
29
+ # Per-target module override: file_sd entries may carry a
30
+ # __probe_module label (e.g. tcp_connect for databases/SFTP, where an
31
+ # HTTP GET can never succeed); default stays http_2xx from params.
32
+ - source_labels: [__probe_module]
33
+ regex: (.+)
34
+ target_label: __param_module
35
+ - target_label: __address__
36
+ replacement: blackbox-exporter:9115
@@ -0,0 +1,25 @@
1
+ # Local Tempo — trace store behind the OTel collector, same backend the
2
+ # hosted platform runs. hub-api queries it via TEMPO_URL (http://tempo:3200).
3
+ server:
4
+ http_listen_port: 3200
5
+
6
+ distributor:
7
+ receivers:
8
+ otlp:
9
+ protocols:
10
+ grpc:
11
+ endpoint: 0.0.0.0:4317
12
+ http:
13
+ endpoint: 0.0.0.0:4318
14
+
15
+ storage:
16
+ trace:
17
+ backend: local
18
+ local:
19
+ path: /var/tempo/blocks
20
+ wal:
21
+ path: /var/tempo/wal
22
+
23
+ compactor:
24
+ compaction:
25
+ block_retention: 48h
@@ -0,0 +1,44 @@
1
+ # Local Development Temporal Dynamic Configuration
2
+ # Environment-specific settings for local development.
3
+ # NO authorization block here: the local stack runs Temporal open
4
+ # (TEMPORAL_AUTH_ENABLED=false in compose) and the seeder connects
5
+ # without a token — auth is exercised on deployed platforms only.
6
+ system.forceSearchAttributesCacheRefreshOnRead:
7
+ - value: true
8
+ constraints: {}
9
+
10
+ frontend.enableUpdateWorkflowExecution:
11
+ - value: true
12
+ constraints: {}
13
+
14
+ frontend.enableUpdateWorkflowExecutionAsyncAccepted:
15
+ - value: true
16
+ constraints: {}
17
+
18
+ system.enableEagerWorkflowStart:
19
+ - value: true
20
+ constraints: {}
21
+
22
+ system.enableActivityEagerExecution:
23
+ - value: true
24
+ constraints: {}
25
+
26
+ frontend.enableWorkerVersioningDataAPIs:
27
+ - value: true
28
+ constraints: {}
29
+
30
+ frontend.enableWorkerVersioningWorkflowAPIs:
31
+ - value: true
32
+ constraints: {}
33
+
34
+ frontend.enableWorkerVersioningRuleAPIs:
35
+ - value: true
36
+ constraints: {}
37
+
38
+ worker.buildIdScavengerEnabled:
39
+ - value: true
40
+ constraints: {}
41
+
42
+ frontend.enableExecuteMultiOperation:
43
+ - value: true
44
+ constraints: {}
@@ -0,0 +1,16 @@
1
+ # Agent guidance — {{name}}
2
+
3
+ - Invoke the CLI as `pnpm mesh <cmd>` or (cwd-independent) `pnpm exec mesh <cmd>` —
4
+ a `"mesh"` script + the bundled `@mesh-tech/*` dep make both work after
5
+ `pnpm install`. For a bare `mesh` on PATH, run once: `pnpm exec mesh install-shim`.
6
+ - Operations are `mesh` commands, never raw `aws`/`pulumi`/`kubectl`:
7
+ `mesh start`, `mesh login local`, `mesh dev`, `mesh deploy`.
8
+ - The full local proof is in the README: 401 (no token) → 200 (`mesh login
9
+ local` token) → 403 (no grant) → `pnpm seed:authz` → 200.
10
+ - Authorization rules live ONLY in `api/src/schema.ts` (`defineSchema`);
11
+ routes enforce them with `m.require(resource, action)`. Never hand-roll
12
+ permission checks in route handlers.
13
+ - `spicedb-http-provider.ts` is a starter — swap for the first-party
14
+ provider when @mesh-tech/authz ships it.
15
+ - Pattern skills for authn/authz ship inside those packages (TanStack
16
+ Intent discovers them after `pnpm install`).
@@ -0,0 +1,8 @@
1
+ config:
2
+ aws:region: us-east-2
3
+ mesh:tenant: {{tenant}}
4
+ mesh:platform:
5
+ name: mesh
6
+ env: dev
7
+ mesh:deploy: false
8
+ mesh:deployerRole: arn:aws:iam::123456789012:role/{{tenant}}-dev-apps-deployer
@@ -0,0 +1,8 @@
1
+ name: {{name}}
2
+ runtime:
3
+ name: nodejs
4
+ options:
5
+ packagemanager: pnpm
6
+ nodeargs: "--import tsx"
7
+ backend:
8
+ url: s3://mesh-platform-pulumi-state
@@ -0,0 +1,67 @@
1
+ # {{titleCase name}}
2
+
3
+ Platform-authenticated API: `@mesh-tech/authn` (Zitadel JWT) + `@mesh-tech/authz`
4
+ (schema-driven SpiceDB permissions). Three routes: open, authenticated,
5
+ permission-gated.
6
+
7
+ ## Run it locally (no AWS, no VPN)
8
+
9
+ ```bash
10
+ mesh start # local platform (seeded Zitadel + SpiceDB)
11
+ mesh login local # sign in as dev@local.mesh / LocalDev1!
12
+ pnpm install
13
+ mesh dev # wires the api to the local platform
14
+ ```
15
+
16
+ ## Prove the auth planes (401 → 200 → 403 → 200)
17
+
18
+ ```bash
19
+ # open route — no token
20
+ curl -s http://localhost:3000/health
21
+ # → {"status":"ok"}
22
+
23
+ # authenticated route without a token → 401
24
+ curl -s -o /dev/null -w '%{http_code}\n' http://localhost:3000/api/me
25
+ # → 401
26
+
27
+ # with your mesh login token → 200
28
+ TOKEN=$(jq -r '.local.accessToken' ~/.config/mesh/credentials.json)
29
+ curl -s http://localhost:3000/api/me -H "Authorization: Bearer $TOKEN"
30
+ # → {"sub":"…","email":"dev@local.mesh"}
31
+
32
+ # permission-gated route before any grant → 403
33
+ curl -s -o /dev/null -w '%{http_code}\n' http://localhost:3000/api/report -H "Authorization: Bearer $TOKEN"
34
+ # → 403
35
+
36
+ # grant yourself report:view (writes the SpiceDB schema + relation) …
37
+ SUB=$(jq -r '.local.sub' ~/.config/mesh/credentials.json)
38
+ cd api && pnpm seed:authz -- "$SUB" && cd ..
39
+
40
+ # … now 200
41
+ curl -s http://localhost:3000/api/report -H "Authorization: Bearer $TOKEN"
42
+ # → {"id":"quarterly","title":"Quarterly Report",…}
43
+ ```
44
+
45
+ Log in as `ops@local.mesh` instead and `/api/report` stays 403 — the grant
46
+ is per-subject, in SpiceDB, exactly like the deployed platform.
47
+
48
+ ## Deploy to a tenant environment
49
+
50
+ The deployed Service runs behind the platform's oauth2-proxy sidecar
51
+ (`auth: { provider: "mesh", … }` in `index.ts`), which needs its own OIDC
52
+ client in the platform Zitadel:
53
+
54
+ ```bash
55
+ mesh login {{tenant}}.dev
56
+ pulumi config set {{name}}:authClientId <clientId>
57
+ pulumi config set --secret {{name}}:authClientSecret <clientSecret>
58
+ mesh deploy up --yes
59
+ ```
60
+
61
+ ## Layout
62
+
63
+ - `index.ts` — Pulumi program (`Service` with platform auth + `/health` open)
64
+ - `api/src/index.ts` — Hono app: authn middleware + authz `require()`
65
+ - `api/src/schema.ts` — the authorization schema (single source of truth)
66
+ - `api/src/spicedb-http-provider.ts` — starter `AuthzProvider` (HTTP API)
67
+ - `api/src/seed-authz.ts` — local schema write + grant
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "{{name}}-api",
3
+ "version": "0.0.1",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "tsx watch src/index.ts",
8
+ "start": "node dist/index.js",
9
+ "build": "esm-bundle src/index.ts --outfile dist/index.js",
10
+ "check-types": "tsc --noEmit",
11
+ "seed:authz": "tsx src/seed-authz.ts"
12
+ },
13
+ "dependencies": {
14
+ "@mesh-tech/authn": "latest",
15
+ "@mesh-tech/authz": "latest",
16
+ "@opentelemetry/auto-instrumentations-node": "^0.78.0",
17
+ "@mesh-tech/sinks": "latest",
18
+ "hono": "^4.0.0",
19
+ "@hono/node-server": "^1.0.0",
20
+ "zod": "^4.0.0"
21
+ },
22
+ "devDependencies": {
23
+ "@mesh-tech/esm-bundle": "latest",
24
+ "@types/node": "^20.0.0",
25
+ "tsx": "^4.0.0",
26
+ "typescript": "^5.0.0"
27
+ }
28
+ }
@@ -0,0 +1,96 @@
1
+ /**
2
+ * {{titleCase name}} API — platform auth on both planes.
3
+ *
4
+ * authn (@mesh-tech/authn): verifies Zitadel JWTs (zitadel-jwt scheme).
5
+ * authz (@mesh-tech/authz): schema-driven permission checks via SpiceDB.
6
+ *
7
+ * Routes:
8
+ * GET /health public (no token)
9
+ * GET /api/me authenticated (valid JWT → 200, none → 401)
10
+ * GET /api/report permission-gated (needs report:view via SpiceDB → else 403)
11
+ *
12
+ * Environment (mesh dev injects all of these — local or tethered):
13
+ * PORT, ZITADEL_ISSUER, SPICEDB_ENDPOINT, SPICEDB_PRESHARED_KEY
14
+ */
15
+
16
+ import { Hono } from "hono";
17
+ import { serve } from "@hono/node-server";
18
+ import { createAuthn } from "@mesh-tech/authn";
19
+ import { zitadelJwtScheme } from "@mesh-tech/authn/schemes/zitadel-jwt";
20
+ import { createAuthnMiddleware, type AuthnVariables } from "@mesh-tech/authn/hono";
21
+ import { createAuthz } from "@mesh-tech/authz/runtime";
22
+ import { createAuthzMiddleware, type AuthzVariables } from "@mesh-tech/authz/hono";
23
+ import { schema } from "./schema.js";
24
+ import { spiceDbHttpProvider } from "./spicedb-http-provider.js";
25
+
26
+ const PORT = parseInt(process.env.PORT ?? "3000", 10);
27
+ const ZITADEL_ISSUER = process.env.ZITADEL_ISSUER ?? "http://localhost:8080";
28
+
29
+ // --- authn: who is calling ---
30
+
31
+ // Audience: locally, mesh dev injects the seeded CLI app's clientId
32
+ // (tokens come from `mesh login local`); in the cloud this is the app's own
33
+ // audience and consumers request its project-audience scope.
34
+ const AUTH_AUDIENCE = process.env.AUTH_AUDIENCE ?? "{{name}}";
35
+
36
+ const authn = createAuthn({
37
+ schemes: {
38
+ "zitadel-jwt": zitadelJwtScheme({ issuer: ZITADEL_ISSUER, audience: AUTH_AUDIENCE }),
39
+ },
40
+ });
41
+ const { middleware: requireAuth, public: publicRoute } = createAuthnMiddleware(authn);
42
+
43
+ // --- authz: what they may do ---
44
+
45
+ const authz = createAuthz({
46
+ schemas: {
47
+ "{{name}}": {
48
+ schema,
49
+ provider: spiceDbHttpProvider({
50
+ endpoint: process.env.SPICEDB_HTTP_ENDPOINT ?? "http://localhost:8443",
51
+ // "local-dev-key" is the `mesh start` stack's key — local ONLY. In
52
+ // any deployed env the platform injects SPICEDB_PRESHARED_KEY; fail
53
+ // loudly rather than silently authing with the public default.
54
+ presharedKey:
55
+ process.env.SPICEDB_PRESHARED_KEY ??
56
+ (process.env.NODE_ENV === "production"
57
+ ? (() => {
58
+ throw new Error("SPICEDB_PRESHARED_KEY is required in production");
59
+ })()
60
+ : "local-dev-key"),
61
+ }),
62
+ },
63
+ },
64
+ });
65
+ // Explicit subject mapping: authenticated humans are the schema's `user`
66
+ // subject. Required, not optional — the default resolver types EVERY caller as
67
+ // `api_key` (MESH-2472), and a relation cannot target `api_key`, so this app's
68
+ // `viewer: { subject: "user" }` relation would never match without this.
69
+ const m = createAuthzMiddleware(authz, {
70
+ resolveSubject: (c) => ({ type: "user", id: (c as { get(key: "auth"): { subjectSub: string } }).get("auth").subjectSub }),
71
+ });
72
+
73
+ // --- routes ---
74
+
75
+ const app = new Hono<{ Variables: AuthnVariables & AuthzVariables }>();
76
+
77
+ // Open: no token needed (also excluded from the oauth2-proxy in the cloud)
78
+ app.get("/health", publicRoute(), (c) => c.json({ status: "ok" }));
79
+
80
+ // Everything under /api requires a valid Zitadel JWT…
81
+ app.use("/api/*", requireAuth());
82
+ app.use("/api/*", m.authContextMiddleware());
83
+
84
+ // …authenticated is enough here:
85
+ app.get("/api/me", (c) =>
86
+ c.json({ sub: c.var.auth.subjectSub, email: c.var.auth.claims?.email }),
87
+ );
88
+
89
+ // …and this one additionally needs the report:view permission (SpiceDB):
90
+ app.get("/api/report", m.require("report", "view", { id: () => "quarterly" }), (c) =>
91
+ c.json({ id: "quarterly", title: "Quarterly Report", classification: "internal" }),
92
+ );
93
+
94
+ serve({ fetch: app.fetch, port: PORT }, () => {
95
+ console.log(`{{name}} api listening on :${PORT} (issuer: ${ZITADEL_ISSUER})`);
96
+ });
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Authorization schema — the single source of truth (@mesh-tech/authz).
3
+ *
4
+ * One resource (`report`) with one gated action (`view`), grantable via the
5
+ * `viewer` relation. `pnpm seed:authz` compiles this to SpiceDB and grants
6
+ * the local dev test user; in the cloud the compiled schema ships through
7
+ * the platform's authz pipeline.
8
+ */
9
+
10
+ import { defineSchema } from "@mesh-tech/authz/schema";
11
+ import { z } from "zod";
12
+
13
+ const Report = z.object({
14
+ id: z.string(),
15
+ title: z.string(),
16
+ });
17
+
18
+ export const schema = defineSchema({
19
+ namespace: "{{name}}",
20
+ version: "1.0.0",
21
+ subjects: {
22
+ user: { coarseRoles: ["user"], identity: { claim: "sub" } },
23
+ },
24
+ resources: {
25
+ report: {
26
+ schema: Report,
27
+ actions: ["view"] as const,
28
+ relations: {
29
+ viewer: { subject: "user", grants: ["view"], writeAuthority: "app" },
30
+ },
31
+ },
32
+ },
33
+ coarseRoles: ["user"] as const,
34
+ zitadelSync: "coarse",
35
+ });
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Local authz seed: compile the schema to SpiceDB and grant the dev test
3
+ * user the report `viewer` relation — the 403→200 half of the README proof.
4
+ *
5
+ * pnpm seed:authz # after `mesh start`
6
+ *
7
+ * dev@local.mesh gets report:view; ops@local.mesh does not (stays 403).
8
+ */
9
+
10
+ import { compileSpiceDBSchema } from "@mesh-tech/authz/compilers";
11
+ import { schema } from "./schema.js";
12
+ import { spiceDbHttpProvider } from "./spicedb-http-provider.js";
13
+
14
+ const ENDPOINT = process.env.SPICEDB_HTTP_ENDPOINT ?? "http://localhost:8443";
15
+ const KEY = process.env.SPICEDB_PRESHARED_KEY ?? "local-dev-key";
16
+
17
+ // The Zitadel subject (`sub` claim) of the user to grant. Find it after
18
+ // `mesh login local`: the CLI caches it in ~/.config/mesh/credentials.json,
19
+ // or pass it explicitly: pnpm seed:authz -- <sub>
20
+ // pnpm may forward a literal "--" — ignore it
21
+ const sub = process.argv.slice(2).filter((a) => a !== "--")[0] ?? process.env.SEED_USER_SUB;
22
+ if (!sub) {
23
+ console.error("Usage: pnpm seed:authz <zitadel-user-sub>");
24
+ console.error("(the `sub` from your mesh login local session — see README)");
25
+ process.exit(1);
26
+ }
27
+
28
+ const { zed } = compileSpiceDBSchema(schema);
29
+
30
+ const res = await fetch(`${ENDPOINT}/v1/schema/write`, {
31
+ method: "POST",
32
+ headers: { Authorization: `Bearer ${KEY}`, "Content-Type": "application/json" },
33
+ body: JSON.stringify({ schema: zed }),
34
+ });
35
+ if (!res.ok) {
36
+ console.error(`schema write failed: ${res.status} ${await res.text()}`);
37
+ process.exit(1);
38
+ }
39
+ console.log("✓ SpiceDB schema written");
40
+
41
+ const provider = spiceDbHttpProvider({ endpoint: ENDPOINT, presharedKey: KEY });
42
+ await provider.writeRelationship({
43
+ subject: { type: "user", id: sub },
44
+ relation: "viewer",
45
+ resource: { type: "report", id: "quarterly" },
46
+ op: "touch",
47
+ });
48
+ console.log(`✓ Granted report:view on 'quarterly' to user ${sub}`);
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Minimal AuthzProvider over SpiceDB's HTTP API.
3
+ *
4
+ * The `mesh start` local platform exposes SpiceDB HTTP on :8443 (preshared
5
+ * key `local-dev-key`); deployed SpiceDB exposes the same API. When the
6
+ * platform ships a first-party gRPC provider in @mesh-tech/authz (tracked
7
+ * under MESH-1823-adjacent runtime work), swap this file for it — the
8
+ * AuthzProvider seam is the whole point.
9
+ */
10
+
11
+ import type { AuthzProvider } from "@mesh-tech/authz/runtime";
12
+
13
+ export interface SpiceDbHttpConfig {
14
+ /** e.g. http://localhost:8443 */
15
+ endpoint: string;
16
+ presharedKey: string;
17
+ }
18
+
19
+ async function call(cfg: SpiceDbHttpConfig, path: string, body: unknown): Promise<any> {
20
+ const res = await fetch(`${cfg.endpoint}${path}`, {
21
+ method: "POST",
22
+ headers: {
23
+ Authorization: `Bearer ${cfg.presharedKey}`,
24
+ "Content-Type": "application/json",
25
+ },
26
+ body: JSON.stringify(body),
27
+ });
28
+ const data: any = await res.json().catch(() => ({}));
29
+ if (!res.ok) {
30
+ throw new Error(`SpiceDB ${path} → ${res.status}: ${data?.message ?? "error"}`);
31
+ }
32
+ return data;
33
+ }
34
+
35
+ export function spiceDbHttpProvider(cfg: SpiceDbHttpConfig): AuthzProvider {
36
+ // compileSpiceDBSchema emits unprefixed definitions (`definition report`),
37
+ // so object types pass through as-is.
38
+ const objectType = (type: string) => type;
39
+ return {
40
+ name: "spicedb-http",
41
+
42
+ async checkPermission({ subject, action, resource, consistency }) {
43
+ // An id-less m.require() would silently check the wildcard resource —
44
+ // fail-closed in practice, but it hides the caller's bug. Fail loud.
45
+ if (!resource.id) {
46
+ throw new Error(
47
+ `checkPermission: resource.id is required (got type '${resource.type}' with no id) — pass the object id being authorized.`,
48
+ );
49
+ }
50
+ // Default to fully-consistent: the hello-world flow grants then checks
51
+ // immediately, and SpiceDB's minimize-latency default can serve a stale
52
+ // denial. Tune per-call via the runtime's consistency hint in real apps.
53
+ const data = await call(cfg, "/v1/permissions/check", {
54
+ consistency:
55
+ consistency === "minimize-latency" ? { minimizeLatency: true } : { fullyConsistent: true },
56
+ resource: { objectType: objectType(resource.type), objectId: resource.id },
57
+ permission: action,
58
+ subject: { object: { objectType: objectType(subject.type), objectId: subject.id } },
59
+ });
60
+ return { allowed: data.permissionship === "PERMISSIONSHIP_HAS_PERMISSION" };
61
+ },
62
+
63
+ async writeRelationship({ subject, relation, resource, op }) {
64
+ const operation =
65
+ op === "delete" ? "OPERATION_DELETE" : op === "create" ? "OPERATION_CREATE" : "OPERATION_TOUCH";
66
+ await call(cfg, "/v1/relationships/write", {
67
+ updates: [
68
+ {
69
+ operation,
70
+ relationship: {
71
+ resource: { objectType: objectType(resource.type), objectId: resource.id },
72
+ relation,
73
+ subject: { object: { objectType: objectType(subject.type), objectId: subject.id } },
74
+ },
75
+ },
76
+ ],
77
+ });
78
+ return {};
79
+ },
80
+
81
+ async lookupResources() {
82
+ throw new Error("lookupResources not implemented by the HTTP starter provider");
83
+ },
84
+
85
+ async lookupSubjects() {
86
+ throw new Error("lookupSubjects not implemented by the HTTP starter provider");
87
+ },
88
+ };
89
+ }
@@ -0,0 +1,65 @@
1
+ /**
2
+ * {{titleCase name}} — Platform-authenticated API
3
+ *
4
+ * Infrastructure: AppEnvironment + API Service behind platform auth
5
+ * (oauth2-proxy sidecar against the platform Zitadel).
6
+ *
7
+ * Local: mesh start && mesh dev (runtime auth only — no proxy sidecar)
8
+ * Deploy: mesh deploy up
9
+ */
10
+
11
+ import * as pulumi from "@pulumi/pulumi";
12
+ import * as path from "node:path";
13
+ import { fileURLToPath } from "node:url";
14
+ import { mesh } from "@mesh-tech/app-kit";
15
+
16
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
17
+ const { tenant, platform, stack, deploy } = mesh.apps.getConfig(pulumi);
18
+
19
+ // --- Environment ---
20
+
21
+ const env = new mesh.apps.AppEnvironment("env", {
22
+ tenant,
23
+ platform,
24
+ stack,
25
+ deploy,
26
+ appName: "{{name}}",
27
+ namespace: true,
28
+ rootDir: __dirname,
29
+ });
30
+
31
+ // --- Services ---
32
+
33
+ // The oauth2-proxy sidecar needs its own OIDC client in the platform
34
+ // Zitadel. Approved tenant-auth pattern: one Zitadel PROJECT per app (in
35
+ // your app tenant's org), one APPLICATION per service — create the app's
36
+ // project if it doesn't exist, add a web application for this service, and
37
+ // set both values on the stack:
38
+ // pulumi config set {{name}}:authClientId <clientId>
39
+ // pulumi config set --secret {{name}}:authClientSecret <clientSecret>
40
+ const appConfig = new pulumi.Config("{{name}}");
41
+
42
+ const api = new mesh.apps.Service("api", {
43
+ env,
44
+ runtime: "node",
45
+ src: "./api",
46
+ port: 3000,
47
+ auth: {
48
+ provider: "mesh", // issuer auto-derived from the platform Zitadel
49
+ clientId: appConfig.require("authClientId"),
50
+ clientSecret: appConfig.requireSecret("authClientSecret"),
51
+ allowUnauthenticated: ["/health"],
52
+ },
53
+ ingress: env.buildIngress({
54
+ subdomain: "{{name}}-api",
55
+ healthCheckPath: "/health",
56
+ }),
57
+ replicas: 1,
58
+ resources: { cpu: "100m", memory: "128Mi" },
59
+ });
60
+
61
+ // --- Outputs ---
62
+
63
+ export const app = env.register({
64
+ description: "{{titleCase name}} — platform-authenticated API (authn + authz)",
65
+ });
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "{{name}}",
3
+ "version": "0.0.1",
4
+ "private": true,
5
+ "type": "module",
6
+ "packageManager": "pnpm@10.29.2",
7
+ "keywords": ["tanstack-intent"],
8
+ "scripts": {
9
+ "mesh": "mesh",
10
+ "typecheck": "tsc --noEmit"
11
+ },
12
+ "dependencies": {
13
+ "@mesh-tech/app-kit": "latest",
14
+ "@pulumi/pulumi": "^3.214.1"
15
+ },
16
+ "devDependencies": {
17
+ "tsx": "^4.20.4",
18
+ "typescript": "^5.7.2"
19
+ }
20
+ }