@mesh-tech/mesh-cli 0.1.1 → 0.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/intent/agents-fence.md +10 -0
- package/assets/intent/intent-claude-gate.mjs +255 -0
- package/assets/log-shipper.mjs +94 -0
- package/bin/mesh.mjs +80 -0
- package/dist/bin/mesh.d.ts +7 -9
- package/dist/bin/mesh.d.ts.map +1 -1
- package/dist/bin/mesh.js +20878 -37
- package/dist/bin/mesh.js.map +7 -1
- package/dist/build-info.json +4 -0
- package/dist/src/commands/agent-api-client.d.ts +79 -0
- package/dist/src/commands/agent-api-client.d.ts.map +1 -0
- package/dist/src/commands/agent-api-client.js +170 -0
- package/dist/src/commands/agent-api-client.js.map +1 -0
- package/dist/src/commands/artifacts.d.ts +13 -0
- package/dist/src/commands/artifacts.d.ts.map +1 -0
- package/dist/src/commands/artifacts.js +140 -0
- package/dist/src/commands/artifacts.js.map +1 -0
- package/dist/src/commands/cluster.d.ts +45 -0
- package/dist/src/commands/cluster.d.ts.map +1 -0
- package/dist/src/commands/cluster.js +259 -0
- package/dist/src/commands/cluster.js.map +1 -0
- package/dist/src/commands/conversations.d.ts +61 -0
- package/dist/src/commands/conversations.d.ts.map +1 -0
- package/dist/src/commands/conversations.js +239 -0
- package/dist/src/commands/conversations.js.map +1 -0
- package/dist/src/commands/create-app.d.ts +26 -3
- package/dist/src/commands/create-app.d.ts.map +1 -1
- package/dist/src/commands/create-app.js +465 -107
- package/dist/src/commands/create-app.js.map +1 -1
- package/dist/src/commands/deploy.d.ts +19 -0
- package/dist/src/commands/deploy.d.ts.map +1 -1
- package/dist/src/commands/deploy.js +83 -142
- package/dist/src/commands/deploy.js.map +1 -1
- package/dist/src/commands/dev-doctor.d.ts +137 -0
- package/dist/src/commands/dev-doctor.d.ts.map +1 -0
- package/dist/src/commands/dev-doctor.js +671 -0
- package/dist/src/commands/dev-doctor.js.map +1 -0
- package/dist/src/commands/dev-launch.d.ts +59 -0
- package/dist/src/commands/dev-launch.d.ts.map +1 -0
- package/dist/src/commands/dev-launch.js +118 -0
- package/dist/src/commands/dev-launch.js.map +1 -0
- package/dist/src/commands/dev-token-server.d.ts +32 -0
- package/dist/src/commands/dev-token-server.d.ts.map +1 -0
- package/dist/src/commands/dev-token-server.js +68 -0
- package/dist/src/commands/dev-token-server.js.map +1 -0
- package/dist/src/commands/dev.d.ts +289 -2
- package/dist/src/commands/dev.d.ts.map +1 -1
- package/dist/src/commands/dev.js +2501 -574
- package/dist/src/commands/dev.js.map +1 -1
- package/dist/src/commands/docs.d.ts +3 -0
- package/dist/src/commands/docs.d.ts.map +1 -0
- package/dist/src/commands/docs.js +262 -0
- package/dist/src/commands/docs.js.map +1 -0
- package/dist/src/commands/hub/index.d.ts +99 -0
- package/dist/src/commands/hub/index.d.ts.map +1 -0
- package/dist/src/commands/hub/index.js +452 -0
- package/dist/src/commands/hub/index.js.map +1 -0
- package/dist/src/commands/init.d.ts +65 -0
- package/dist/src/commands/init.d.ts.map +1 -0
- package/dist/src/commands/init.js +370 -0
- package/dist/src/commands/init.js.map +1 -0
- package/dist/src/commands/install-shim.d.ts +28 -0
- package/dist/src/commands/install-shim.d.ts.map +1 -0
- package/dist/src/commands/install-shim.js +191 -0
- package/dist/src/commands/install-shim.js.map +1 -0
- package/dist/src/commands/local/auth-provision.d.ts +71 -0
- package/dist/src/commands/local/auth-provision.d.ts.map +1 -0
- package/dist/src/commands/local/auth-provision.js +286 -0
- package/dist/src/commands/local/auth-provision.js.map +1 -0
- package/dist/src/commands/local/dev-local.d.ts +97 -0
- package/dist/src/commands/local/dev-local.d.ts.map +1 -0
- package/dist/src/commands/local/dev-local.js +306 -0
- package/dist/src/commands/local/dev-local.js.map +1 -0
- package/dist/src/commands/local/docker-runner.d.ts +37 -0
- package/dist/src/commands/local/docker-runner.d.ts.map +1 -0
- package/dist/src/commands/local/docker-runner.js +104 -0
- package/dist/src/commands/local/docker-runner.js.map +1 -0
- package/dist/src/commands/local/helpers.d.ts +22 -0
- package/dist/src/commands/local/helpers.d.ts.map +1 -0
- package/dist/src/commands/local/helpers.js +46 -0
- package/dist/src/commands/local/helpers.js.map +1 -0
- package/dist/src/commands/local/hub-local.d.ts +51 -0
- package/dist/src/commands/local/hub-local.d.ts.map +1 -0
- package/dist/src/commands/local/hub-local.js +197 -0
- package/dist/src/commands/local/hub-local.js.map +1 -0
- package/dist/src/commands/local/index.d.ts +23 -0
- package/dist/src/commands/local/index.d.ts.map +1 -0
- package/dist/src/commands/local/index.js +386 -0
- package/dist/src/commands/local/index.js.map +1 -0
- package/dist/src/commands/local/mocks.d.ts +361 -0
- package/dist/src/commands/local/mocks.d.ts.map +1 -0
- package/dist/src/commands/local/mocks.js +756 -0
- package/dist/src/commands/local/mocks.js.map +1 -0
- package/dist/src/commands/local/seed-zitadel.d.ts +151 -0
- package/dist/src/commands/local/seed-zitadel.d.ts.map +1 -0
- package/dist/src/commands/local/seed-zitadel.js +408 -0
- package/dist/src/commands/local/seed-zitadel.js.map +1 -0
- package/dist/src/commands/local/seed.d.ts +106 -0
- package/dist/src/commands/local/seed.d.ts.map +1 -0
- package/dist/src/commands/local/seed.js +252 -0
- package/dist/src/commands/local/seed.js.map +1 -0
- package/dist/src/commands/local/stack.d.ts +173 -0
- package/dist/src/commands/local/stack.d.ts.map +1 -0
- package/dist/src/commands/local/stack.js +499 -0
- package/dist/src/commands/local/stack.js.map +1 -0
- package/dist/src/commands/login.d.ts +256 -12
- package/dist/src/commands/login.d.ts.map +1 -1
- package/dist/src/commands/login.js +978 -50
- package/dist/src/commands/login.js.map +1 -1
- package/dist/src/commands/peer-addressing.d.ts +51 -0
- package/dist/src/commands/peer-addressing.d.ts.map +1 -0
- package/dist/src/commands/peer-addressing.js +64 -0
- package/dist/src/commands/peer-addressing.js.map +1 -0
- package/dist/src/commands/port-ownership.d.ts +69 -0
- package/dist/src/commands/port-ownership.d.ts.map +1 -0
- package/dist/src/commands/port-ownership.js +161 -0
- package/dist/src/commands/port-ownership.js.map +1 -0
- package/dist/src/commands/registry-publish.d.ts +3 -0
- package/dist/src/commands/registry-publish.d.ts.map +1 -0
- package/dist/src/commands/registry-publish.js +161 -0
- package/dist/src/commands/registry-publish.js.map +1 -0
- package/dist/src/commands/registry.d.ts +146 -2
- package/dist/src/commands/registry.d.ts.map +1 -1
- package/dist/src/commands/registry.js +541 -85
- package/dist/src/commands/registry.js.map +1 -1
- package/dist/src/commands/secrets/index.d.ts.map +1 -1
- package/dist/src/commands/secrets/index.js +15 -1
- package/dist/src/commands/secrets/index.js.map +1 -1
- package/dist/src/commands/secrets/migrate-config.d.ts +24 -0
- package/dist/src/commands/secrets/migrate-config.d.ts.map +1 -0
- package/dist/src/commands/secrets/migrate-config.js +277 -0
- package/dist/src/commands/secrets/migrate-config.js.map +1 -0
- package/dist/src/commands/secrets/set.d.ts +1 -0
- package/dist/src/commands/secrets/set.d.ts.map +1 -1
- package/dist/src/commands/secrets/set.js +96 -2
- package/dist/src/commands/secrets/set.js.map +1 -1
- package/dist/src/commands/skills.d.ts +34 -0
- package/dist/src/commands/skills.d.ts.map +1 -0
- package/dist/src/commands/skills.js +207 -0
- package/dist/src/commands/skills.js.map +1 -0
- package/dist/src/commands/stack.d.ts.map +1 -1
- package/dist/src/commands/stack.js +361 -23
- package/dist/src/commands/stack.js.map +1 -1
- package/dist/src/commands/temporal.d.ts +15 -0
- package/dist/src/commands/temporal.d.ts.map +1 -0
- package/dist/src/commands/temporal.js +781 -0
- package/dist/src/commands/temporal.js.map +1 -0
- package/dist/src/commands/tenant.d.ts +56 -0
- package/dist/src/commands/tenant.d.ts.map +1 -0
- package/dist/src/commands/tenant.js +233 -0
- package/dist/src/commands/tenant.js.map +1 -0
- package/dist/src/commands/tunnel/index.d.ts +49 -3
- package/dist/src/commands/tunnel/index.d.ts.map +1 -1
- package/dist/src/commands/tunnel/index.js +331 -8
- package/dist/src/commands/tunnel/index.js.map +1 -1
- package/dist/src/commands/vcs/clone.d.ts +3 -0
- package/dist/src/commands/vcs/clone.d.ts.map +1 -0
- package/dist/src/commands/vcs/clone.js +20 -0
- package/dist/src/commands/vcs/clone.js.map +1 -0
- package/dist/src/commands/vcs/common.d.ts +21 -0
- package/dist/src/commands/vcs/common.d.ts.map +1 -0
- package/dist/src/commands/vcs/common.js +62 -0
- package/dist/src/commands/vcs/common.js.map +1 -0
- package/dist/src/commands/vcs/drafts.d.ts +13 -0
- package/dist/src/commands/vcs/drafts.d.ts.map +1 -0
- package/dist/src/commands/vcs/drafts.js +45 -0
- package/dist/src/commands/vcs/drafts.js.map +1 -0
- package/dist/src/commands/vcs/get.d.ts +8 -0
- package/dist/src/commands/vcs/get.d.ts.map +1 -0
- package/dist/src/commands/vcs/get.js +61 -0
- package/dist/src/commands/vcs/get.js.map +1 -0
- package/dist/src/commands/vcs/index.d.ts +3 -0
- package/dist/src/commands/vcs/index.d.ts.map +1 -0
- package/dist/src/commands/vcs/index.js +58 -0
- package/dist/src/commands/vcs/index.js.map +1 -0
- package/dist/src/commands/vcs/propose.d.ts +23 -0
- package/dist/src/commands/vcs/propose.d.ts.map +1 -0
- package/dist/src/commands/vcs/propose.js +94 -0
- package/dist/src/commands/vcs/propose.js.map +1 -0
- package/dist/src/commands/vcs/review.d.ts +15 -0
- package/dist/src/commands/vcs/review.d.ts.map +1 -0
- package/dist/src/commands/vcs/review.js +35 -0
- package/dist/src/commands/vcs/review.js.map +1 -0
- package/dist/src/commands/vcs-enrich.d.ts +15 -0
- package/dist/src/commands/vcs-enrich.d.ts.map +1 -0
- package/dist/src/commands/vcs-enrich.js +28 -0
- package/dist/src/commands/vcs-enrich.js.map +1 -0
- package/dist/src/commands/vpn/index.d.ts +24 -0
- package/dist/src/commands/vpn/index.d.ts.map +1 -0
- package/dist/src/commands/vpn/index.js +543 -0
- package/dist/src/commands/vpn/index.js.map +1 -0
- package/dist/src/commands/vpn/tunnel.d.ts +11 -0
- package/dist/src/commands/vpn/tunnel.d.ts.map +1 -0
- package/dist/src/commands/vpn/tunnel.js +188 -0
- package/dist/src/commands/vpn/tunnel.js.map +1 -0
- package/dist/src/commands/workflow.d.ts +24 -0
- package/dist/src/commands/workflow.d.ts.map +1 -0
- package/dist/src/commands/workflow.js +577 -0
- package/dist/src/commands/workflow.js.map +1 -0
- package/dist/src/docs/assemble.d.ts +217 -0
- package/dist/src/docs/assemble.d.ts.map +1 -0
- package/dist/src/docs/assemble.js +739 -0
- package/dist/src/docs/assemble.js.map +1 -0
- package/dist/src/docs/cli-reference.d.ts +93 -0
- package/dist/src/docs/cli-reference.d.ts.map +1 -0
- package/dist/src/docs/cli-reference.js +256 -0
- package/dist/src/docs/cli-reference.js.map +1 -0
- package/dist/src/docs/discover.d.ts +60 -0
- package/dist/src/docs/discover.d.ts.map +1 -0
- package/dist/src/docs/discover.js +233 -0
- package/dist/src/docs/discover.js.map +1 -0
- package/dist/src/docs/portal.d.ts +79 -0
- package/dist/src/docs/portal.d.ts.map +1 -0
- package/dist/src/docs/portal.js +242 -0
- package/dist/src/docs/portal.js.map +1 -0
- package/dist/src/docs/registry-docs.d.ts +43 -0
- package/dist/src/docs/registry-docs.d.ts.map +1 -0
- package/dist/src/docs/registry-docs.js +138 -0
- package/dist/src/docs/registry-docs.js.map +1 -0
- package/dist/src/docs/schema.d.ts +48 -0
- package/dist/src/docs/schema.d.ts.map +1 -0
- package/dist/src/docs/schema.js +96 -0
- package/dist/src/docs/schema.js.map +1 -0
- package/dist/src/docs/serve.d.ts +27 -0
- package/dist/src/docs/serve.d.ts.map +1 -0
- package/dist/src/docs/serve.js +102 -0
- package/dist/src/docs/serve.js.map +1 -0
- package/dist/src/docs/start.d.ts +80 -0
- package/dist/src/docs/start.d.ts.map +1 -0
- package/dist/src/docs/start.js +313 -0
- package/dist/src/docs/start.js.map +1 -0
- package/dist/src/eval/agent-eval.d.mts +14 -0
- package/dist/src/eval/agent-eval.d.mts.map +1 -0
- package/dist/src/eval/agent-eval.mjs +273 -0
- package/dist/src/eval/agent-eval.mjs.map +1 -0
- package/dist/src/index.js +624 -7
- package/dist/src/index.js.map +7 -1
- package/dist/src/program.d.ts +26 -0
- package/dist/src/program.d.ts.map +1 -0
- package/dist/src/program.js +76 -0
- package/dist/src/program.js.map +1 -0
- package/dist/src/utils/auth-preflight.d.ts +159 -0
- package/dist/src/utils/auth-preflight.d.ts.map +1 -0
- package/dist/src/utils/auth-preflight.js +298 -0
- package/dist/src/utils/auth-preflight.js.map +1 -0
- package/dist/src/utils/aws-auth.d.ts +181 -0
- package/dist/src/utils/aws-auth.d.ts.map +1 -0
- package/dist/src/utils/aws-auth.js +527 -0
- package/dist/src/utils/aws-auth.js.map +1 -0
- package/dist/src/utils/bastion.d.ts +1 -1
- package/dist/src/utils/bastion.d.ts.map +1 -1
- package/dist/src/utils/bastion.js +29 -8
- package/dist/src/utils/bastion.js.map +1 -1
- package/dist/src/utils/build-info.d.ts +33 -0
- package/dist/src/utils/build-info.d.ts.map +1 -0
- package/dist/src/utils/build-info.js +102 -0
- package/dist/src/utils/build-info.js.map +1 -0
- package/dist/src/utils/capture-history.d.ts +62 -0
- package/dist/src/utils/capture-history.d.ts.map +1 -0
- package/dist/src/utils/capture-history.js +94 -0
- package/dist/src/utils/capture-history.js.map +1 -0
- package/dist/src/utils/deploy-preflight.d.ts +52 -0
- package/dist/src/utils/deploy-preflight.d.ts.map +1 -0
- package/dist/src/utils/deploy-preflight.js +183 -0
- package/dist/src/utils/deploy-preflight.js.map +1 -0
- package/dist/src/utils/errors.d.ts +75 -0
- package/dist/src/utils/errors.d.ts.map +1 -0
- package/dist/src/utils/errors.js +106 -0
- package/dist/src/utils/errors.js.map +1 -0
- package/dist/src/utils/first-party-contexts.d.ts +40 -0
- package/dist/src/utils/first-party-contexts.d.ts.map +1 -0
- package/dist/src/utils/first-party-contexts.js +53 -0
- package/dist/src/utils/first-party-contexts.js.map +1 -0
- package/dist/src/utils/index.d.ts +2 -0
- package/dist/src/utils/index.d.ts.map +1 -1
- package/dist/src/utils/index.js +2 -0
- package/dist/src/utils/index.js.map +1 -1
- package/dist/src/utils/kubeconfig.d.ts +62 -0
- package/dist/src/utils/kubeconfig.d.ts.map +1 -0
- package/dist/src/utils/kubeconfig.js +118 -0
- package/dist/src/utils/kubeconfig.js.map +1 -0
- package/dist/src/utils/log.d.ts +27 -1
- package/dist/src/utils/log.d.ts.map +1 -1
- package/dist/src/utils/log.js +59 -5
- package/dist/src/utils/log.js.map +1 -1
- package/dist/src/utils/pid.d.ts +47 -0
- package/dist/src/utils/pid.d.ts.map +1 -0
- package/dist/src/utils/pid.js +83 -0
- package/dist/src/utils/pid.js.map +1 -0
- package/dist/src/utils/pulumi-run.d.ts +23 -0
- package/dist/src/utils/pulumi-run.d.ts.map +1 -0
- package/dist/src/utils/pulumi-run.js +112 -0
- package/dist/src/utils/pulumi-run.js.map +1 -0
- package/dist/src/utils/pulumi.d.ts +15 -0
- package/dist/src/utils/pulumi.d.ts.map +1 -1
- package/dist/src/utils/pulumi.js +35 -0
- package/dist/src/utils/pulumi.js.map +1 -1
- package/dist/src/utils/reachability.d.ts +29 -0
- package/dist/src/utils/reachability.d.ts.map +1 -0
- package/dist/src/utils/reachability.js +81 -0
- package/dist/src/utils/reachability.js.map +1 -0
- package/dist/src/utils/recover-conversation.d.ts +154 -0
- package/dist/src/utils/recover-conversation.d.ts.map +1 -0
- package/dist/src/utils/recover-conversation.js +314 -0
- package/dist/src/utils/recover-conversation.js.map +1 -0
- package/dist/src/utils/registry-broker.d.ts +148 -0
- package/dist/src/utils/registry-broker.d.ts.map +1 -0
- package/dist/src/utils/registry-broker.js +180 -0
- package/dist/src/utils/registry-broker.js.map +1 -0
- package/dist/src/utils/socks-forward.d.ts +40 -0
- package/dist/src/utils/socks-forward.d.ts.map +1 -0
- package/dist/src/utils/socks-forward.js +97 -0
- package/dist/src/utils/socks-forward.js.map +1 -0
- package/dist/src/utils/stack-flag.d.ts +23 -0
- package/dist/src/utils/stack-flag.d.ts.map +1 -0
- package/dist/src/utils/stack-flag.js +41 -0
- package/dist/src/utils/stack-flag.js.map +1 -0
- package/dist/src/utils/tailscale-targets.d.ts +52 -0
- package/dist/src/utils/tailscale-targets.d.ts.map +1 -0
- package/dist/src/utils/tailscale-targets.js +93 -0
- package/dist/src/utils/tailscale-targets.js.map +1 -0
- package/dist/src/utils/tailscale.d.ts +277 -0
- package/dist/src/utils/tailscale.d.ts.map +1 -0
- package/dist/src/utils/tailscale.js +1007 -0
- package/dist/src/utils/tailscale.js.map +1 -0
- package/dist/src/utils/temporal-auth.d.ts +43 -0
- package/dist/src/utils/temporal-auth.d.ts.map +1 -0
- package/dist/src/utils/temporal-auth.js +176 -0
- package/dist/src/utils/temporal-auth.js.map +1 -0
- package/dist/src/utils/temporal-codec.d.ts +101 -0
- package/dist/src/utils/temporal-codec.d.ts.map +1 -0
- package/dist/src/utils/temporal-codec.js +319 -0
- package/dist/src/utils/temporal-codec.js.map +1 -0
- package/dist/src/utils/tunnel-ownership.d.ts +130 -0
- package/dist/src/utils/tunnel-ownership.d.ts.map +1 -0
- package/dist/src/utils/tunnel-ownership.js +274 -0
- package/dist/src/utils/tunnel-ownership.js.map +1 -0
- package/dist/src/utils/vpn-join.d.ts +32 -0
- package/dist/src/utils/vpn-join.d.ts.map +1 -0
- package/dist/src/utils/vpn-join.js +62 -0
- package/dist/src/utils/vpn-join.js.map +1 -0
- package/dist/src/utils/vpn.d.ts +62 -0
- package/dist/src/utils/vpn.d.ts.map +1 -0
- package/dist/src/utils/vpn.js +183 -0
- package/dist/src/utils/vpn.js.map +1 -0
- package/dist/src/utils/workflow-fingerprint.d.ts +49 -0
- package/dist/src/utils/workflow-fingerprint.d.ts.map +1 -0
- package/dist/src/utils/workflow-fingerprint.js +135 -0
- package/dist/src/utils/workflow-fingerprint.js.map +1 -0
- package/dist/src/utils/worktree-identity.d.ts +86 -0
- package/dist/src/utils/worktree-identity.d.ts.map +1 -0
- package/dist/src/utils/worktree-identity.js +164 -0
- package/dist/src/utils/worktree-identity.js.map +1 -0
- package/fragments/agents/AGENTS.md.hbs +92 -0
- package/fragments/agents/CLAUDE.md.hbs +8 -0
- package/fragments/base/Pulumi.dev.yaml.hbs +10 -0
- package/fragments/base/Pulumi.yaml.hbs +9 -0
- package/fragments/base/index.ts.hbs +107 -0
- package/fragments/base/package.json.hbs +22 -0
- package/{templates/api-web-db/api → fragments/base}/tsconfig.json +3 -4
- package/fragments/bucket/api/src/storage.ts.hbs +81 -0
- package/fragments/database/api/src/db.ts.hbs +23 -0
- package/fragments/database/prisma/schema.prisma.hbs +18 -0
- package/{templates/api-web-db → fragments/service}/api/.dockerignore +2 -0
- package/fragments/service/api/package.json.hbs +40 -0
- package/fragments/service/api/src/index.ts.hbs +58 -0
- package/{templates/api-web-db → fragments/service/api}/tsconfig.json +5 -3
- package/fragments/temporal/worker/.dockerignore +4 -0
- package/fragments/temporal/worker/Dockerfile +15 -0
- package/{templates/temporal-api-worker → fragments/temporal}/worker/package.json.hbs +3 -2
- package/fragments/temporal/worker/src/activities.ts.hbs +14 -0
- package/fragments/temporal/worker/src/worker.ts.hbs +27 -0
- package/fragments/temporal/worker/src/workflows.ts.hbs +24 -0
- package/fragments/temporal/worker/tsconfig.json +13 -0
- package/package.json +36 -22
- package/skills/core/SKILL.md +365 -0
- package/skills/pull-remote-agent-context/SKILL.md +194 -0
- package/stack/docker-compose.hub.yml +134 -0
- package/stack/docker-compose.yml +447 -0
- package/stack/hub/Dockerfile.api +18 -0
- package/stack/hub/Dockerfile.auth +10 -0
- package/stack/hub/Dockerfile.ui +10 -0
- package/stack/init/01-databases.sql +12 -0
- package/stack/observability/blackbox.yml +20 -0
- package/stack/observability/otel-collector.yaml +73 -0
- package/stack/observability/prometheus.yml +36 -0
- package/stack/observability/tempo.yaml +25 -0
- package/stack/temporal/local.yaml +44 -0
- package/templates/api-auth/AGENTS.md.hbs +16 -0
- package/templates/api-auth/Pulumi.dev.yaml.hbs +8 -0
- package/templates/api-auth/Pulumi.yaml.hbs +8 -0
- package/templates/api-auth/README.md.hbs +67 -0
- package/templates/api-auth/api/package.json.hbs +28 -0
- package/templates/api-auth/api/src/index.ts.hbs +96 -0
- package/templates/api-auth/api/src/schema.ts.hbs +35 -0
- package/templates/api-auth/api/src/seed-authz.ts.hbs +48 -0
- package/templates/api-auth/api/src/spicedb-http-provider.ts.hbs +89 -0
- package/templates/api-auth/index.ts.hbs +65 -0
- package/templates/api-auth/package.json.hbs +20 -0
- package/templates/api-auth/skills/develop/SKILL.md.hbs +32 -0
- package/templates/api-role-gating/AGENTS.md.hbs +20 -0
- package/templates/api-role-gating/Pulumi.dev.yaml.hbs +8 -0
- package/templates/api-role-gating/Pulumi.yaml.hbs +8 -0
- package/templates/api-role-gating/README.md.hbs +64 -0
- package/templates/api-role-gating/api/Dockerfile +17 -0
- package/templates/api-role-gating/api/package.json.hbs +28 -0
- package/templates/api-role-gating/api/src/authn.ts.hbs +29 -0
- package/templates/api-role-gating/api/src/authz.ts.hbs +12 -0
- package/templates/api-role-gating/api/src/main.ts.hbs +58 -0
- package/templates/api-role-gating/api/src/schema.ts.hbs +22 -0
- package/templates/api-role-gating/api/tsconfig.json +13 -0
- package/templates/api-role-gating/index.ts.hbs +107 -0
- package/templates/api-role-gating/package.json.hbs +21 -0
- package/templates/api-role-gating/skills/develop/SKILL.md.hbs +60 -0
- package/templates/api-role-gating/tsconfig.json +10 -0
- package/templates/apps-repo/README.md.hbs +24 -0
- package/templates/apps-repo/gitignore +41 -0
- package/templates/apps-repo/npmrc.hbs +7 -0
- package/templates/apps-repo/package.json.hbs +15 -0
- package/templates/apps-repo/pnpm-workspace.yaml +3 -0
- package/templates/apps-repo/tsconfig.json +18 -0
- package/templates/external-service/AGENTS.md.hbs +20 -0
- package/templates/external-service/Pulumi.dev.yaml.hbs +8 -0
- package/templates/external-service/Pulumi.yaml.hbs +8 -0
- package/templates/external-service/README.md.hbs +56 -0
- package/templates/external-service/api/Dockerfile +15 -0
- package/templates/external-service/api/package.json.hbs +25 -0
- package/templates/external-service/api/src/index.ts.hbs +81 -0
- package/templates/external-service/index.ts.hbs +82 -0
- package/templates/external-service/mocks/vendorpay/package.json.hbs +9 -0
- package/templates/external-service/mocks/vendorpay/server.mjs.hbs +61 -0
- package/templates/external-service/package.json.hbs +34 -0
- package/templates/external-service/skills/develop/SKILL.md.hbs +55 -0
- package/templates/external-service/tsconfig.json +10 -0
- package/templates/platform-repo/AGENTS.md.hbs +18 -0
- package/templates/platform-repo/README.md.hbs +38 -0
- package/templates/platform-repo/core/Pulumi.yaml.hbs +12 -0
- package/templates/platform-repo/core/Pulumi.{{tenant}}-{{env}}.yaml.hbs +57 -0
- package/templates/platform-repo/core/index.ts +62 -0
- package/templates/platform-repo/core/package.json.hbs +22 -0
- package/templates/platform-repo/core/tsconfig.json +8 -0
- package/templates/platform-repo/package.json.hbs +15 -0
- package/templates/platform-repo/platform/Pulumi.yaml.hbs +12 -0
- package/templates/platform-repo/platform/Pulumi.{{tenant}}-{{env}}.yaml.hbs +59 -0
- package/templates/platform-repo/platform/index.ts +95 -0
- package/templates/platform-repo/platform/package.json.hbs +26 -0
- package/templates/platform-repo/platform/tsconfig.json +8 -0
- package/templates/platform-repo/pnpm-workspace.yaml +3 -0
- package/templates/workflow/AGENTS.md.hbs +15 -0
- package/templates/workflow/Pulumi.dev.yaml.hbs +8 -0
- package/templates/workflow/Pulumi.yaml.hbs +8 -0
- package/templates/workflow/README.md.hbs +45 -0
- package/templates/workflow/api/.dockerignore +4 -0
- package/templates/workflow/api/Dockerfile +15 -0
- package/templates/{temporal-api-worker → workflow}/api/package.json.hbs +8 -6
- package/templates/workflow/api/src/index.ts.hbs +130 -0
- package/templates/workflow/api/tsconfig.json +14 -0
- package/templates/workflow/index.ts.hbs +67 -0
- package/templates/workflow/package.json.hbs +20 -0
- package/templates/workflow/skills/develop/SKILL.md.hbs +32 -0
- package/templates/workflow/tsconfig.json +10 -0
- package/templates/workflow/worker/.dockerignore +4 -0
- package/templates/workflow/worker/Dockerfile +13 -0
- package/templates/workflow/worker/package.json.hbs +25 -0
- package/templates/workflow/worker/src/worker.ts.hbs +24 -0
- package/templates/workflow/worker/tsconfig.json +14 -0
- package/dist/src/commands/devbox.d.ts +0 -22
- package/dist/src/commands/devbox.d.ts.map +0 -1
- package/dist/src/commands/devbox.js +0 -463
- package/dist/src/commands/devbox.js.map +0 -1
- package/templates/api-web-db/api/Dockerfile +0 -16
- package/templates/api-web-db/api/package.json.hbs +0 -21
- package/templates/api-web-db/api/src/index.ts.hbs +0 -123
- package/templates/api-web-db/package.json.hbs +0 -27
- package/templates/api-web-db/sst.config.ts.hbs +0 -151
- package/templates/api-web-db/web/.dockerignore +0 -3
- package/templates/api-web-db/web/Dockerfile +0 -17
- package/templates/api-web-db/web/app/lib/db.server.ts +0 -36
- package/templates/api-web-db/web/app/root.tsx +0 -29
- package/templates/api-web-db/web/app/routes/home.tsx.hbs +0 -114
- package/templates/api-web-db/web/app/routes.ts +0 -3
- package/templates/api-web-db/web/package.json.hbs +0 -30
- package/templates/api-web-db/web/prisma/schema.prisma +0 -25
- package/templates/api-web-db/web/prisma.config.ts +0 -18
- package/templates/api-web-db/web/react-router.config.ts +0 -5
- package/templates/api-web-db/web/tsconfig.json +0 -19
- package/templates/api-web-db/web/vite.config.ts +0 -9
- package/templates/temporal-api-worker/README.md.hbs +0 -133
- package/templates/temporal-api-worker/api/src/index.ts.hbs +0 -145
- package/templates/temporal-api-worker/package.json.hbs +0 -29
- package/templates/temporal-api-worker/sst.config.ts.hbs +0 -161
- package/templates/temporal-api-worker/worker/Dockerfile +0 -11
- package/templates/temporal-api-worker/worker/src/bundle-workflows.ts +0 -38
- package/templates/temporal-api-worker/worker/src/worker.ts.hbs +0 -93
- /package/templates/{temporal-api-worker → api-auth}/api/.dockerignore +0 -0
- /package/templates/{temporal-api-worker → api-auth}/api/Dockerfile +0 -0
- /package/templates/{temporal-api-worker → api-auth}/api/tsconfig.json +0 -0
- /package/templates/{temporal-api-worker → api-auth}/tsconfig.json +0 -0
- /package/templates/{temporal-api-worker/worker → api-role-gating/api}/.dockerignore +0 -0
- /package/templates/{temporal-api-worker/worker → external-service/api}/tsconfig.json +0 -0
- /package/templates/{temporal-api-worker → workflow}/api/src/encryption-codec.ts +0 -0
- /package/templates/{temporal-api-worker → workflow}/worker/src/activities.ts.hbs +0 -0
- /package/templates/{temporal-api-worker → workflow}/worker/src/encryption-codec.ts +0 -0
- /package/templates/{temporal-api-worker → workflow}/worker/src/workflows.ts.hbs +0 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# {{titleCase name}}
|
|
2
|
+
|
|
3
|
+
External-service pattern app: a Hono API that calls a third-party vendor
|
|
4
|
+
(`vendorpay`) through platform-managed credentials. The vendor is declared as
|
|
5
|
+
a first-class `ExternalService` — the platform owns the credential shell,
|
|
6
|
+
Hub registration, and health probe; credentials never live in code or config.
|
|
7
|
+
|
|
8
|
+
## Run it locally (no AWS, no VPN)
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
mesh start # local Mesh platform — the Hub is at http://localhost:9000
|
|
12
|
+
pnpm install
|
|
13
|
+
mesh dev --externals # starts api + the mocks/vendorpay stand-in, and points
|
|
14
|
+
# the vendorpay credential secret at it
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Prove the pattern end-to-end (the api resolves credentials from Secrets
|
|
18
|
+
Manager, then calls the vendor with them):
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
curl -s http://localhost:3000/health
|
|
22
|
+
# → {"status":"ok"}
|
|
23
|
+
|
|
24
|
+
curl -s -X POST http://localhost:3000/payments/quote \
|
|
25
|
+
-H 'content-type: application/json' -d '{"amount": 125.5}'
|
|
26
|
+
# → {"vendor":"vendorpay","amount":125.5,"quote":{"quoteId":"…","fee":3.64,"total":129.14,…}}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
The mock enforces the API key exactly like a real vendor — the call only
|
|
30
|
+
succeeds because the api read `baseUrl` + `apiKey` from the credential secret
|
|
31
|
+
at `mesh/{{tenant}}/dev/external/vendorpay`. Watch it in the **Hub**
|
|
32
|
+
(http://localhost:9000 → {{tenant}} → {{name}}): the app's services, the
|
|
33
|
+
`vendorpay` external service, and both services' logs.
|
|
34
|
+
|
|
35
|
+
`mesh dev --externals=vendorpay` starts a named subset; plain `mesh dev` starts
|
|
36
|
+
only the app services (calls to the vendor fail credential resolution —
|
|
37
|
+
by design, no silent fallbacks).
|
|
38
|
+
|
|
39
|
+
## Deploy to a tenant environment
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
mesh login {{tenant}}.dev
|
|
43
|
+
mesh deploy up
|
|
44
|
+
mesh secrets set external/vendorpay # set the REAL baseUrl + apiKey
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Deployed, the exact same code runs: `vendorpay.link()` injects
|
|
48
|
+
`VENDORPAY_SECRET_PREFIX` + IAM read permission, `resolveCredentials`
|
|
49
|
+
fetches the real values, and the Hub shows the vendor with its credential
|
|
50
|
+
schema and health probe.
|
|
51
|
+
|
|
52
|
+
## Layout
|
|
53
|
+
|
|
54
|
+
- `index.ts` — infra: `AppEnvironment` + `ExternalService("vendorpay")` + api `Service` with `vendorpay.link()`
|
|
55
|
+
- `api/` — the service; `resolveCredentials("vendorpay")` + `@mesh-tech/http-client`
|
|
56
|
+
- `mocks/vendorpay/` — the local vendor stand-in (declared in `package.json` → `mesh.externals`, mode `mock`)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
FROM node:20-slim
|
|
2
|
+
|
|
3
|
+
WORKDIR /app
|
|
4
|
+
|
|
5
|
+
COPY package*.json ./
|
|
6
|
+
# Full install (not --omit=dev): the build needs esm-bundle, a devDependency.
|
|
7
|
+
# npm install (not ci) — these scaffolds ship no lockfile.
|
|
8
|
+
RUN npm install
|
|
9
|
+
|
|
10
|
+
COPY . .
|
|
11
|
+
RUN npm run build
|
|
12
|
+
|
|
13
|
+
EXPOSE 3000
|
|
14
|
+
|
|
15
|
+
CMD ["node", "dist/index.js"]
|
|
@@ -0,0 +1,25 @@
|
|
|
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
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@mesh-tech/app-kit": "latest",
|
|
14
|
+
"@opentelemetry/auto-instrumentations-node": "^0.78.0",
|
|
15
|
+
"@mesh-tech/http-client": "latest",
|
|
16
|
+
"hono": "^4.0.0",
|
|
17
|
+
"@hono/node-server": "^1.0.0"
|
|
18
|
+
},
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"@mesh-tech/esm-bundle": "latest",
|
|
21
|
+
"@types/node": "^20.0.0",
|
|
22
|
+
"tsx": "^4.0.0",
|
|
23
|
+
"typescript": "^5.0.0"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* {{titleCase name}} API — calls the vendorpay external service.
|
|
3
|
+
*
|
|
4
|
+
* The external-service pattern, runtime side:
|
|
5
|
+
* 1. Infra links the ExternalService → this process gets
|
|
6
|
+
* VENDORPAY_SECRET_PREFIX (+ IAM to read that secret).
|
|
7
|
+
* 2. resolveCredentials("vendorpay") reads the credential JSON from
|
|
8
|
+
* Secrets Manager at runtime (cached 5 min) — never from env/config.
|
|
9
|
+
* 3. The vendor call goes through @mesh-tech/http-client's enhanceFetch
|
|
10
|
+
* (correlation-id propagation + structured request logs).
|
|
11
|
+
*
|
|
12
|
+
* Locally (`mesh dev --externals`), the SAME code runs: the credential secret in
|
|
13
|
+
* the local platform's Secrets Manager points baseUrl at the started
|
|
14
|
+
* mocks/vendorpay service. The app cannot tell the difference.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { serve } from "@hono/node-server";
|
|
18
|
+
import { Hono } from "hono";
|
|
19
|
+
import { resolveCredentials } from "@mesh-tech/app-kit/credentials";
|
|
20
|
+
import { traceExternalCall } from "@mesh-tech/app-kit/tracing";
|
|
21
|
+
import { enhanceFetch } from "@mesh-tech/http-client";
|
|
22
|
+
|
|
23
|
+
interface VendorpayCredentials extends Record<string, string> {
|
|
24
|
+
baseUrl: string;
|
|
25
|
+
apiKey: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const vendorFetch = enhanceFetch();
|
|
29
|
+
|
|
30
|
+
const app = new Hono();
|
|
31
|
+
|
|
32
|
+
app.get("/health", (c) => c.json({ status: "ok" }));
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Quote a payment through the vendor. Demonstrates the full pattern:
|
|
36
|
+
* resolve credentials → call the vendor → normalize the response.
|
|
37
|
+
*/
|
|
38
|
+
app.post("/payments/quote", async (c) => {
|
|
39
|
+
const body = await c.req.json().catch(() => ({}));
|
|
40
|
+
const amount = Number(body?.amount ?? 0);
|
|
41
|
+
if (!Number.isFinite(amount) || amount <= 0) {
|
|
42
|
+
return c.json({ error: "amount must be a positive number" }, 400);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const creds = await resolveCredentials<VendorpayCredentials>("vendorpay");
|
|
46
|
+
|
|
47
|
+
// traceExternalCall wraps the vendor call in an `external.vendorpay/…`
|
|
48
|
+
// span (span.external_service.name) — the Hub's Integrations → Traces
|
|
49
|
+
// view is built on exactly these spans. The auto-instrumented fetch
|
|
50
|
+
// appears as its child with the real network timing.
|
|
51
|
+
const response = await traceExternalCall("vendorpay", "quote.create", () =>
|
|
52
|
+
vendorFetch(`${creds.baseUrl.replace(/\/+$/, "")}/quote`, {
|
|
53
|
+
method: "POST",
|
|
54
|
+
headers: {
|
|
55
|
+
"content-type": "application/json",
|
|
56
|
+
"x-api-key": creds.apiKey,
|
|
57
|
+
},
|
|
58
|
+
body: JSON.stringify({ amount }),
|
|
59
|
+
}),
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
// Log vendor interactions with the service name — these lines are what
|
|
63
|
+
// the Hub's Integrations → Monitoring → Logs view surfaces (it searches
|
|
64
|
+
// consumer logs for mentions of the external service).
|
|
65
|
+
console.log(`[vendorpay] quote requested amount=${amount} → ${response.status}`);
|
|
66
|
+
|
|
67
|
+
if (!response.ok) {
|
|
68
|
+
return c.json(
|
|
69
|
+
{ error: `vendorpay quote failed (${response.status})` },
|
|
70
|
+
502,
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const quote = await response.json();
|
|
75
|
+
return c.json({ vendor: "vendorpay", amount, quote });
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
const port = Number(process.env.PORT ?? 3000);
|
|
79
|
+
serve({ fetch: app.fetch, port }, () => {
|
|
80
|
+
console.log(`[API] {{titleCase name}} API listening on port ${port}`);
|
|
81
|
+
});
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* {{titleCase name}} — External-Service Pattern Application
|
|
3
|
+
*
|
|
4
|
+
* Declares a third-party vendor as a first-class ExternalService: the
|
|
5
|
+
* platform owns the credential SHELL (Secrets Manager path + schema + Hub
|
|
6
|
+
* registration + health probe); real values are set out-of-band with
|
|
7
|
+
* `mesh secrets set external/vendorpay` (or the Hub UI) and the app resolves
|
|
8
|
+
* them at RUNTIME — credentials never touch code, config files, or Pulumi
|
|
9
|
+
* state.
|
|
10
|
+
*
|
|
11
|
+
* Dev mode: mesh dev --externals (starts mocks/vendorpay and points the
|
|
12
|
+
* credential secret at it — same runtime path)
|
|
13
|
+
* Deploy: mesh deploy up
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import * as pulumi from "@pulumi/pulumi";
|
|
17
|
+
import * as path from "node:path";
|
|
18
|
+
import { fileURLToPath } from "node:url";
|
|
19
|
+
import { mesh } from "@mesh-tech/app-kit";
|
|
20
|
+
|
|
21
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
22
|
+
const { tenant, platform, stack, deploy } = mesh.apps.getConfig(pulumi);
|
|
23
|
+
|
|
24
|
+
// --- Environment ---
|
|
25
|
+
|
|
26
|
+
const env = new mesh.apps.AppEnvironment("env", {
|
|
27
|
+
tenant,
|
|
28
|
+
platform,
|
|
29
|
+
stack,
|
|
30
|
+
deploy,
|
|
31
|
+
appName: "{{name}}",
|
|
32
|
+
namespace: true,
|
|
33
|
+
rootDir: __dirname,
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// --- External service (the vendor) ---
|
|
37
|
+
// Registers in the Hub's external-services view, creates the credential
|
|
38
|
+
// shell at mesh/{tenant}/{stage}/external/vendorpay, and (deployed) probes
|
|
39
|
+
// the vendor's health endpoint.
|
|
40
|
+
|
|
41
|
+
const vendorpay = new mesh.apps.ExternalService("vendorpay", {
|
|
42
|
+
env,
|
|
43
|
+
type: "payment",
|
|
44
|
+
kind: "connection",
|
|
45
|
+
description: "Example payments vendor (quotes API) — the external-service pattern",
|
|
46
|
+
credentials: {
|
|
47
|
+
fields: {
|
|
48
|
+
baseUrl: { name: "Base URL", description: "Vendor API endpoint" },
|
|
49
|
+
apiKey: { name: "API Key", description: "Vendor API key", secret: true },
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
healthCheck: {
|
|
53
|
+
// Replace with the vendor's real health/status URL.
|
|
54
|
+
url: "https://status.vendorpay.example.com/health",
|
|
55
|
+
intervalSeconds: 300,
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
// --- Services ---
|
|
60
|
+
|
|
61
|
+
const api = new mesh.apps.Service("api", {
|
|
62
|
+
env,
|
|
63
|
+
runtime: "node",
|
|
64
|
+
src: "./api",
|
|
65
|
+
port: 3000,
|
|
66
|
+
// link() injects VENDORPAY_SECRET_PREFIX + the IAM permission to read the
|
|
67
|
+
// credential secret; the api calls resolveCredentials("vendorpay") at
|
|
68
|
+
// runtime.
|
|
69
|
+
link: [vendorpay.link()],
|
|
70
|
+
ingress: env.buildIngress({
|
|
71
|
+
subdomain: "{{name}}-api",
|
|
72
|
+
healthCheckPath: "/health",
|
|
73
|
+
}),
|
|
74
|
+
replicas: 1,
|
|
75
|
+
resources: { cpu: "100m", memory: "128Mi" },
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// --- Outputs ---
|
|
79
|
+
|
|
80
|
+
export const app = env.register({
|
|
81
|
+
description: "{{titleCase name}} — external-service (vendor credentials) pattern",
|
|
82
|
+
});
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mock vendorpay — a stand-in for the real vendor API, started by
|
|
3
|
+
* `mesh dev --externals`. Enforces the API key exactly like the real vendor
|
|
4
|
+
* would, so the app's credential path is exercised end-to-end.
|
|
5
|
+
*
|
|
6
|
+
* Declared in the root package.json under `mesh.externals.vendorpay`
|
|
7
|
+
* (mode `mock`); the CLI
|
|
8
|
+
* allocates a port, seeds the external-service credential secret with this
|
|
9
|
+
* server's URL + key, and ships its logs to the platform pipeline like any
|
|
10
|
+
* other service.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import http from "node:http";
|
|
14
|
+
|
|
15
|
+
const PORT = Number(process.env.PORT ?? 4610);
|
|
16
|
+
const API_KEY = process.env.MOCK_API_KEY ?? "local-mock-key";
|
|
17
|
+
|
|
18
|
+
const server = http.createServer((req, res) => {
|
|
19
|
+
const send = (status, body) => {
|
|
20
|
+
res.writeHead(status, { "content-type": "application/json" });
|
|
21
|
+
res.end(JSON.stringify(body));
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
if (req.url === "/health") {
|
|
25
|
+
return send(200, { status: "ok", vendor: "vendorpay-mock" });
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (req.url === "/quote" && req.method === "POST") {
|
|
29
|
+
if (req.headers["x-api-key"] !== API_KEY) {
|
|
30
|
+
console.log(`[mock-vendorpay] 401 — bad or missing x-api-key`);
|
|
31
|
+
return send(401, { error: "invalid api key" });
|
|
32
|
+
}
|
|
33
|
+
let raw = "";
|
|
34
|
+
req.on("data", (chunk) => (raw += chunk));
|
|
35
|
+
req.on("end", () => {
|
|
36
|
+
let amount = 0;
|
|
37
|
+
try {
|
|
38
|
+
amount = Number(JSON.parse(raw || "{}").amount ?? 0);
|
|
39
|
+
} catch {
|
|
40
|
+
/* ignore malformed body */
|
|
41
|
+
}
|
|
42
|
+
const fee = Math.max(0.5, Math.round(amount * 2.9) / 100);
|
|
43
|
+
console.log(`[mock-vendorpay] quote amount=${amount} fee=${fee}`);
|
|
44
|
+
send(200, {
|
|
45
|
+
quoteId: `q-${Date.now()}`,
|
|
46
|
+
amount,
|
|
47
|
+
fee,
|
|
48
|
+
total: Math.round((amount + fee) * 100) / 100,
|
|
49
|
+
currency: "USD",
|
|
50
|
+
quotedAt: new Date().toISOString(),
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
send(404, { error: "not found" });
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
server.listen(PORT, () => {
|
|
60
|
+
console.log(`[mock-vendorpay] listening on port ${PORT} (api key: ${API_KEY})`);
|
|
61
|
+
});
|
|
@@ -0,0 +1,34 @@
|
|
|
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
|
+
"mesh": {
|
|
21
|
+
"externals": {
|
|
22
|
+
"vendorpay": {
|
|
23
|
+
"mode": "mock",
|
|
24
|
+
"src": "mocks/vendorpay",
|
|
25
|
+
"external": "vendorpay",
|
|
26
|
+
"env": { "MOCK_API_KEY": "local-mock-key" },
|
|
27
|
+
"credentials": {
|
|
28
|
+
"baseUrl": "\{{url}}",
|
|
29
|
+
"apiKey": "local-mock-key"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: develop-{{name}}
|
|
3
|
+
description: Run, extend, and deploy the {{name}} external-service app — vendor credentials via the platform, local vendor mock, and the deploy path.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Developing {{name}}
|
|
7
|
+
|
|
8
|
+
## Run locally (zero cloud access)
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
mesh start # local Mesh platform (Hub at http://localhost:9000)
|
|
12
|
+
pnpm install
|
|
13
|
+
mesh dev --externals # api + mocks/vendorpay, credential secret auto-seeded
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Prove it: `curl -s -X POST localhost:3000/payments/quote -H 'content-type: application/json' -d '{"amount":125.5}'` → a quote from the mock, obtained with credentials the api resolved from Secrets Manager. Inspect in the Hub (http://localhost:9000 → {{tenant}} → {{name}}): services, the `vendorpay` external service, logs.
|
|
17
|
+
|
|
18
|
+
**Reaching a sibling service.** With more than one service in the app, `mesh dev --local` injects `SERVICE_{NAME}_URL` into every service's env — `{NAME}` is the service's directory name upper-cased, with anything outside `A–Z0–9` becoming `_` (`token-manager` → `SERVICE_TOKEN_MANAGER_URL`). To read the *same* variable deployed and locally, name the link to match: `events.link({ environmentPrefix: "SERVICE_EVENTS" })` — then `process.env.SERVICE_EVENTS_URL` works everywhere, with no `isLocal` branch in your code.
|
|
19
|
+
|
|
20
|
+
## The pattern
|
|
21
|
+
|
|
22
|
+
1. **Declare** the vendor once in `index.ts`: `new mesh.apps.ExternalService("vendorpay", { credentials: { fields: … }, healthCheck: … })` — the platform owns the secret shell at `mesh/{tenant}/{stage}/external/vendorpay`, the Hub registration, and the health probe.
|
|
23
|
+
2. **Link** it into consumers: `link: [vendorpay.link()]` → injects `VENDORPAY_SECRET_PREFIX` + IAM read.
|
|
24
|
+
3. **Resolve at runtime**: `resolveCredentials("vendorpay")` (`@mesh-tech/app-kit/credentials`) — cached, never in env/config/state.
|
|
25
|
+
4. **Call** through `enhanceFetch()` (`@mesh-tech/http-client`) so requests carry correlation ids and structured logs.
|
|
26
|
+
|
|
27
|
+
Add a credential field: extend `credentials.fields` in `index.ts` AND the typed interface in `api/src/index.ts`. Add another vendor: repeat the declaration, link it, and (optionally) add a `mesh.externals` entry so `mesh dev --externals` can realize it locally.
|
|
28
|
+
|
|
29
|
+
## Externals
|
|
30
|
+
|
|
31
|
+
Declared in the root `package.json` → `mesh.externals.<name>`; `mesh dev --externals` realizes all of them (`--externals vendorpay` a subset). Each declaration runs in one of **three modes**:
|
|
32
|
+
|
|
33
|
+
| Mode | Meaning | Declare |
|
|
34
|
+
|---|---|---|
|
|
35
|
+
| `mock` | the service is **emulated** — no real instance exists | `{ mode: "mock", src: "mocks/vendorpay", … }` runs the dir's `dev` script as `mock-<name>` (this template), or `{ mode: "mock", openapi: "spec.json", … }` runs a Prism mock server generated from the spec |
|
|
36
|
+
| `local` | a **local version** of the real service runs on this machine | `{ mode: "local", compose: "vendor-db/docker-compose.yml", port, … }` → `docker compose up -d --wait` before your services (vendor-shaped DBs); if another checkout already realized it, it is **adopted** instead of failing (declared port served **by a service this compose file defines** → used as-is; an unrelated publisher on that port is a conflict, not an adoption; a stopped container holding the compose `container_name` → `docker start`); `mesh dev --kill` downs only externals this session created (volumes kept) and never touches adopted ones |
|
|
37
|
+
| `remote` | connect to the **actual** external service | `{ mode: "remote", credentials: { endpoint: "https://sandbox.vendor.com", … } }` (inline vendor credentials), or `{ mode: "remote", remote: { env: "dev" } }` to pull the credentials the app's `dev` environment is configured with |
|
|
38
|
+
|
|
39
|
+
A declaration may carry **several** realizations (e.g. `compose` *and* `remote.env`); `mode` picks the default and the CLI overrides it per run: `mesh dev --externals vendor-db=remote,vendorpay`. In every mode `credentials` seeds the external secret locally so `resolveCredentials()` runs the deployed code path; values support `\{{url}}`/`\{{host}}`/`\{{port}}` (the stand-in's endpoint) and `\{{env:VAR}}` (your shell — real secrets never land in package.json).
|
|
40
|
+
|
|
41
|
+
> Compat: the legacy key `mesh.mocks`, the `--mock` flag, and `sandbox: true` (an alias for `mode: "remote"`) are still read — new declarations should use `mesh.externals` / `--externals` / `mode`.
|
|
42
|
+
|
|
43
|
+
Every stand-in with a local endpoint also gets a blackbox probe, so the Hub's uptime works locally. By default that's an HTTP GET of `healthPath` (`/health`) expecting 2xx — **add `probe: "tcp"` for anything that doesn't speak HTTP** (databases, SFTP, message brokers): it checks only that the port accepts connections. Without it a TDS/SSH port is GETed as if it were HTTP, the probe can never succeed, and the external reads permanently down in the Hub — with no error anywhere.
|
|
44
|
+
|
|
45
|
+
```jsonc
|
|
46
|
+
"plaid-db": { "compose": "db/docker-compose.yml", "port": 1433, "probe": "tcp", "external": "plaid-db", "credentials": { … } }
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Deploy
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
mesh login {{tenant}}.dev
|
|
53
|
+
mesh deploy up
|
|
54
|
+
mesh secrets set external/vendorpay # real vendor values (never in git)
|
|
55
|
+
```
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Agent guidance — {{tenant}} platform repo
|
|
2
|
+
|
|
3
|
+
- Invoke the CLI as `pnpm mesh <cmd>` or (cwd-independent) `pnpm exec mesh <cmd>` —
|
|
4
|
+
a root `"mesh"` script + the `@mesh-tech/mesh-cli` devDependency make both work
|
|
5
|
+
after `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 login {{tenant}}.{{env}}`, `mesh deploy preview|up` (run inside
|
|
8
|
+
`core/` or `platform/`), `mesh init app-tenant` (doctor).
|
|
9
|
+
- Deploy order matters: `core/` before `platform/` (platform imports core
|
|
10
|
+
from the SSM registry).
|
|
11
|
+
- Capabilities are config, not code: enable/disable platform services in
|
|
12
|
+
`platform/Pulumi.{{tenant}}-{{env}}.yaml` (temporal/zitadel/hub/tenants/…);
|
|
13
|
+
the `index.ts` layer programs should rarely change.
|
|
14
|
+
- Registering a new app tenant = `mesh tenant add <name>` from `platform/`,
|
|
15
|
+
then `mesh deploy up` — never hand-edit `mesh:tenants`, never hand-write
|
|
16
|
+
registry entries. `mesh tenant list` shows what the stack declares.
|
|
17
|
+
- Pattern skills for `@mesh-tech/infra-components` ship inside the package
|
|
18
|
+
(TanStack Intent, after `pnpm install`).
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# {{tenant}} — Mesh platform tenant
|
|
2
|
+
|
|
3
|
+
Infrastructure repo for the **{{tenant}}** platform tenant: two Pulumi layers
|
|
4
|
+
built on `@mesh-tech/infra-components`, deployed with `mesh deploy`.
|
|
5
|
+
|
|
6
|
+
- `core/` — VPC, EKS, shared RDS, DNS (`mesh.layers.MeshCore`)
|
|
7
|
+
- `platform/` — Temporal, Zitadel, Hub, app-tenant environments (`mesh.layers.MeshPlatform`)
|
|
8
|
+
|
|
9
|
+
Everything self-registers in the SSM registry (`/mesh/{{tenant}}/{{env}}/…`);
|
|
10
|
+
apps and the Hub discover the platform from there — no hardcoded wiring.
|
|
11
|
+
|
|
12
|
+
## Deploy
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
mesh login {{tenant}}.{{env}} # or your platform context; registry auth runs automatically
|
|
16
|
+
pnpm install
|
|
17
|
+
|
|
18
|
+
cd core && mesh deploy up # ~20 min first run (VPC + EKS)
|
|
19
|
+
cd ../platform && mesh deploy up # Temporal + Zitadel + Hub + tenant envs
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
The stack configs (`Pulumi.{{tenant}}-{{env}}.yaml`) are annotated — every
|
|
23
|
+
platform capability is a config block; uncomment to enable.
|
|
24
|
+
|
|
25
|
+
## After deploy
|
|
26
|
+
|
|
27
|
+
- **Hub** (operations dashboard): `https://hub.{{env}}.{{domain}}`
|
|
28
|
+
- Temporal UI: `https://temporal.{{env}}.{{domain}}`
|
|
29
|
+
- Register more app tenants: `cd platform && mesh tenant add <name>` then `mesh deploy up` — `mesh tenant list` shows what's declared, and `mesh init app-tenant` in an apps repo verifies the result.
|
|
30
|
+
- Scaffold apps: `mesh create-app --tenant {{tenant}} --name <app> --template workflow|api-auth|api-role-gating|external-service`
|
|
31
|
+
|
|
32
|
+
## Day-2
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
mesh deploy preview # in core/ or platform/
|
|
36
|
+
mesh deploy stack output --json
|
|
37
|
+
mesh init app-tenant # doctor, from any apps repo
|
|
38
|
+
```
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
name: {{tenant}}-core
|
|
2
|
+
description: Core infrastructure for the {{tenant}} tenant (VPC, EKS, RDS)
|
|
3
|
+
runtime:
|
|
4
|
+
name: nodejs
|
|
5
|
+
options:
|
|
6
|
+
packagemanager: pnpm
|
|
7
|
+
nodeargs: "--import tsx"
|
|
8
|
+
backend:
|
|
9
|
+
url: s3://{{stateBucket}}
|
|
10
|
+
config:
|
|
11
|
+
aws:region: {{region}}
|
|
12
|
+
mesh:tenant: {{tenant}}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Core layer stack config — {{tenant}}/{{env}}.
|
|
2
|
+
# Every value here feeds mesh.layers.MeshCore (see index.ts). Deploy with:
|
|
3
|
+
# mesh deploy up (from this directory)
|
|
4
|
+
config:
|
|
5
|
+
aws:region: {{region}}
|
|
6
|
+
aws:profile: {{profile}}
|
|
7
|
+
mesh:pulumiStateBucket: {{stateBucket}}
|
|
8
|
+
|
|
9
|
+
# VPC — MeshCore calculates public/private subnet CIDRs automatically.
|
|
10
|
+
mesh:vpc:
|
|
11
|
+
cidr: "10.0.0.0/16"
|
|
12
|
+
azCount: 2
|
|
13
|
+
|
|
14
|
+
# EKS — the platform's runtime. Sized for a small tenant; scale nodes as
|
|
15
|
+
# apps land. Set `mesh:eks: false` for a core-only (no cluster) deploy.
|
|
16
|
+
mesh:eks:
|
|
17
|
+
version: "1.34"
|
|
18
|
+
nodeInstanceType: "m6i.large"
|
|
19
|
+
minNodes: 2
|
|
20
|
+
maxNodes: 6
|
|
21
|
+
desiredNodes: 2 # initial size only — the Cluster Autoscaler owns this after creation
|
|
22
|
+
addons:
|
|
23
|
+
ebsCsiDriver: true
|
|
24
|
+
metricsServer: true
|
|
25
|
+
clusterAutoscaler: true
|
|
26
|
+
albController: true
|
|
27
|
+
externalDns: true
|
|
28
|
+
certManager: true
|
|
29
|
+
prometheusStack:
|
|
30
|
+
enableGrafana: true
|
|
31
|
+
enableAlertManager: false
|
|
32
|
+
retention: "15d"
|
|
33
|
+
storageSize: "20Gi"
|
|
34
|
+
# Loki — log aggregation the Hub's logs view reads.
|
|
35
|
+
loki:
|
|
36
|
+
enabled: true
|
|
37
|
+
retentionDays: 30
|
|
38
|
+
storageSize: "10Gi"
|
|
39
|
+
|
|
40
|
+
# Shared RDS for app databases + SpiceDB (via the database provisioner).
|
|
41
|
+
# Set to false to skip; apps can bring their own.
|
|
42
|
+
mesh:rds:
|
|
43
|
+
engine: postgres
|
|
44
|
+
instanceClass: db.t4g.small
|
|
45
|
+
allocatedStorage: 20
|
|
46
|
+
|
|
47
|
+
# Public DNS — required for ingress (Temporal UI, Zitadel, Hub).
|
|
48
|
+
# The zone must exist (or be delegated) in this account.
|
|
49
|
+
mesh:dns:
|
|
50
|
+
publicZoneName: {{env}}.{{domain}}
|
|
51
|
+
|
|
52
|
+
# Peering with another tenant's core (optional):
|
|
53
|
+
# mesh:peering:
|
|
54
|
+
# peerWith:
|
|
55
|
+
# tenant: mesh
|
|
56
|
+
# env: dev
|
|
57
|
+
# accountId: "159923586610"
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import * as pulumi from "@pulumi/pulumi";
|
|
2
|
+
import * as aws from "@pulumi/aws";
|
|
3
|
+
import { mesh, parseEnvFromStack } from "@mesh-tech/infra-components";
|
|
4
|
+
|
|
5
|
+
// ============================================================================
|
|
6
|
+
// Configuration
|
|
7
|
+
// ============================================================================
|
|
8
|
+
|
|
9
|
+
const config = new pulumi.Config("mesh");
|
|
10
|
+
const awsConfig = new pulumi.Config("aws");
|
|
11
|
+
|
|
12
|
+
const tenant = config.require("tenant");
|
|
13
|
+
const region = awsConfig.require("region");
|
|
14
|
+
const env = parseEnvFromStack(tenant);
|
|
15
|
+
const pulumiStateBucket = config.require("pulumiStateBucket");
|
|
16
|
+
|
|
17
|
+
// Get AWS account ID
|
|
18
|
+
const callerIdentity = await aws.getCallerIdentity();
|
|
19
|
+
const awsAccountId = callerIdentity.accountId;
|
|
20
|
+
|
|
21
|
+
// ============================================================================
|
|
22
|
+
// Core Infrastructure
|
|
23
|
+
// ============================================================================
|
|
24
|
+
// MeshCore creates:
|
|
25
|
+
// - VPC with public/private subnets (calculated from vpc.cidr)
|
|
26
|
+
// - EKS cluster (if eks config provided)
|
|
27
|
+
// - RDS instance (if rds config provided)
|
|
28
|
+
// - Peering IAM role (if peering.allowPeeringFrom provided)
|
|
29
|
+
// - Auto-exports to SSM: /mesh/{tenant}/{env}/core
|
|
30
|
+
//
|
|
31
|
+
|
|
32
|
+
const meshCore = new mesh.layers.MeshCore("core", {
|
|
33
|
+
tenant,
|
|
34
|
+
env,
|
|
35
|
+
region,
|
|
36
|
+
awsAccountId,
|
|
37
|
+
pulumiStateBucket,
|
|
38
|
+
vpc: config.requireObject("vpc"),
|
|
39
|
+
eks: config.getObject("eks") ?? false,
|
|
40
|
+
rds: config.getObject("rds") ?? false,
|
|
41
|
+
rdsBastion: config.getObject("rdsBastion") ?? config.getBoolean("rdsBastion") ?? false,
|
|
42
|
+
peering: config.getObject("peering"),
|
|
43
|
+
dns: config.getObject("dns"),
|
|
44
|
+
externalTenants: config.getObject("externalTenants"),
|
|
45
|
+
// serviceMesh: false to disable, object to configure, undefined for defaults
|
|
46
|
+
serviceMesh: config.get("serviceMesh") === "false" ? false : config.getObject("serviceMesh"),
|
|
47
|
+
// Secrets (set via: pulumi config set --secret mesh:newRelicLicenseKey <key>)
|
|
48
|
+
newRelicLicenseKey: config.getSecret("newRelicLicenseKey"),
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
// ============================================================================
|
|
52
|
+
// Stack Exports
|
|
53
|
+
// ============================================================================
|
|
54
|
+
// These are available via `pulumi stack output`
|
|
55
|
+
|
|
56
|
+
export const stack = pulumi.getStack();
|
|
57
|
+
export const tenantName = tenant;
|
|
58
|
+
export const environment = env;
|
|
59
|
+
export const accountId = awsAccountId;
|
|
60
|
+
|
|
61
|
+
// All core infrastructure outputs (includes VPC, EKS, RDS, IAM, peering, ssmPath)
|
|
62
|
+
export const core = meshCore.outputs;
|